Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
number of tests, all because of the codecs/_multibytecodecs issue described
here (it's not a Py3K issue, just something Py3K discovers):
http://mail.python.org/pipermail/python-dev/2006-April/064051.html

Hye-Shik Chang promised to look for a fix, so no need to fix it here. The
tests that are expected to break are:

test_codecencodings_cn
test_codecencodings_hk
test_codecencodings_jp
test_codecencodings_kr
test_codecencodings_tw
test_codecs
test_multibytecodec

This merge fixes an actual test failure (test_weakref) in this branch,
though, so I believe merging is the right thing to do anyway.
diff --git a/Modules/Setup.dist b/Modules/Setup.dist
index 3a512b5..49c8425 100644
--- a/Modules/Setup.dist
+++ b/Modules/Setup.dist
@@ -236,9 +236,9 @@
 
 # The md5 module implements the RSA Data Security, Inc. MD5
 # Message-Digest Algorithm, described in RFC 1321.  The necessary files
-# md5c.c and md5.h are included here.
+# md5.c and md5.h are included here.
 
-#md5 md5module.c md5c.c
+#md5 md5module.c md5.c
 
 
 # The sha module implements the SHA checksum algorithm.
diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c
index 8e9ec0f..1641e20 100644
--- a/Modules/_bsddb.c
+++ b/Modules/_bsddb.c
@@ -101,6 +101,10 @@
 static char *rcs_id = "$Id$";
 
 
+#if (PY_VERSION_HEX < 0x02050000)
+#define Py_ssize_t      int
+#endif
+
 #ifdef WITH_THREAD
 
 /* These are for when calling Python --> C */
@@ -4688,7 +4692,11 @@
 
 
 static PyMappingMethods DB_mapping = {
+#if (PY_VERSION_HEX < 0x02050000)
+        (inquiry)DB_length,          /*mp_length*/
+#else
         (lenfunc)DB_length,          /*mp_length*/
+#endif
         (binaryfunc)DB_subscript,    /*mp_subscript*/
         (objobjargproc)DB_ass_sub,   /*mp_ass_subscript*/
 };
@@ -5385,9 +5393,21 @@
     ADD_INT(d, DB_SET_TXN_TIMEOUT);
 #endif
 
+    /* The exception name must be correct for pickled exception *
+     * objects to unpickle properly.                            */
+#ifdef PYBSDDB_STANDALONE  /* different value needed for standalone pybsddb */
+#define PYBSDDB_EXCEPTION_BASE  "bsddb3.db."
+#else
+#define PYBSDDB_EXCEPTION_BASE  "bsddb.db."
+#endif
+
+    /* All the rest of the exceptions derive only from DBError */
+#define MAKE_EX(name)   name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
+                        PyDict_SetItemString(d, #name, name)
+
     /* The base exception class is DBError */
-    DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
-    PyDict_SetItemString(d, "DBError", DBError);
+    DBError = NULL;     /* used in MAKE_EX so that it derives from nothing */
+    MAKE_EX(DBError);
 
     /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
      * from both DBError and KeyError, since the API only supports
@@ -5401,10 +5421,6 @@
     PyDict_DelItemString(d, "KeyError");
 
 
-    /* All the rest of the exceptions derive only from DBError */
-#define MAKE_EX(name)   name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
-                        PyDict_SetItemString(d, #name, name)
-
 #if !INCOMPLETE_IS_WARNING
     MAKE_EX(DBIncompleteError);
 #endif
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 469cd64..4704c16 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -37,6 +37,28 @@
 #		define PyMODINIT_FUNC void
 #	endif /* __cplusplus */
 #endif
+
+#ifndef Py_CLEAR
+#define Py_CLEAR(op)						\
+	do {							\
+		if (op) {					\
+			PyObject *tmp = (PyObject *)(op);	\
+			(op) = NULL;				\
+			Py_DECREF(tmp);				\
+		}						\
+	} while (0)
+#endif
+#ifndef Py_VISIT
+#define Py_VISIT(op)							\
+        do { 								\
+                if (op) {						\
+                        int vret = visit((PyObject *)(op), arg);	\
+                        if (vret)					\
+                                return vret;				\
+                }							\
+        } while (0)
+#endif
+
 /* end 2.2 compatibility macros */
 
 #define IS_BASESTRING(o) \
@@ -812,28 +834,18 @@
 static int
 Reader_traverse(ReaderObj *self, visitproc visit, void *arg)
 {
-	int err;
-#define VISIT(SLOT) \
-	if (SLOT) { \
-		err = visit((PyObject *)(SLOT), arg); \
-		if (err) \
-			return err; \
-	}
-	VISIT(self->dialect);
-	VISIT(self->input_iter);
-	VISIT(self->fields);
+	Py_VISIT(self->dialect);
+	Py_VISIT(self->input_iter);
+	Py_VISIT(self->fields);
 	return 0;
 }
 
 static int
 Reader_clear(ReaderObj *self)
 {
-        Py_XDECREF(self->dialect);
-        Py_XDECREF(self->input_iter);
-        Py_XDECREF(self->fields);
-        self->dialect = NULL;
-        self->input_iter = NULL;
-        self->fields = NULL;
+	Py_CLEAR(self->dialect);
+	Py_CLEAR(self->input_iter);
+	Py_CLEAR(self->fields);
 	return 0;
 }
 
@@ -1245,25 +1257,16 @@
 static int
 Writer_traverse(WriterObj *self, visitproc visit, void *arg)
 {
-	int err;
-#define VISIT(SLOT) \
-	if (SLOT) { \
-		err = visit((PyObject *)(SLOT), arg); \
-		if (err) \
-			return err; \
-	}
-	VISIT(self->dialect);
-	VISIT(self->writeline);
+	Py_VISIT(self->dialect);
+	Py_VISIT(self->writeline);
 	return 0;
 }
 
 static int
 Writer_clear(WriterObj *self)
 {
-        Py_XDECREF(self->dialect);
-        Py_XDECREF(self->writeline);
-	self->dialect = NULL;
-	self->writeline = NULL;
+	Py_CLEAR(self->dialect);
+	Py_CLEAR(self->writeline);
 	return 0;
 }
 
@@ -1495,7 +1498,7 @@
 PyDoc_STRVAR(csv_writer_doc,
 "    csv_writer = csv.writer(fileobj [, dialect='excel']\n"
 "                            [optional keyword args])\n"
-"    for row in csv_writer:\n"
+"    for row in sequence:\n"
 "        csv_writer.writerow(row)\n"
 "\n"
 "    [or]\n"
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 926c85b..e6d6aa4 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -105,6 +105,10 @@
 #include <ffi.h>
 #ifdef MS_WIN32
 #include <windows.h>
+#include <malloc.h>
+#ifndef IS_INTRESOURCE
+#define IS_INTRESOURCE(x) (((size_t)(x) >> 16) == 0)
+#endif
 # ifdef _WIN32_WCE
 /* Unlike desktop Windows, WinCE has both W and A variants of
    GetProcAddress, but the default W version is not what we want */
@@ -285,6 +289,7 @@
 	if (PyCArg_CheckExact(value)) {
 		PyCArgObject *p = (PyCArgObject *)value;
 		PyObject *ob = p->obj;
+		const char *ob_name;
 		StgDictObject *dict;
 		dict = PyType_stgdict(type);
 
@@ -296,10 +301,10 @@
 			Py_INCREF(value);
 			return value;
 		}
+		ob_name = (ob) ? ob->ob_type->tp_name : "???";
 		PyErr_Format(PyExc_TypeError,
 			     "expected %s instance instead of pointer to %s",
-			     ((PyTypeObject *)type)->tp_name,
-			     ob->ob_type->tp_name);
+			     ((PyTypeObject *)type)->tp_name, ob_name);
 		return NULL;
 	}
 #if 1
@@ -506,12 +511,12 @@
 static int
 PointerType_SetProto(StgDictObject *stgdict, PyObject *proto)
 {
-	if (proto && !PyType_Check(proto)) {
+	if (!proto || !PyType_Check(proto)) {
 		PyErr_SetString(PyExc_TypeError,
 				"_type_ must be a type");
 		return -1;
 	}
-	if (proto && !PyType_stgdict(proto)) {
+	if (!PyType_stgdict(proto)) {
 		PyErr_SetString(PyExc_TypeError,
 				"_type_ must have storage info");
 		return -1;
@@ -543,8 +548,8 @@
 		return NULL;
 	stgdict->size = sizeof(void *);
 	stgdict->align = getentry("P")->pffi_type->alignment;
-	stgdict->length = 2;
-	stgdict->ffi_type = ffi_type_pointer;
+	stgdict->length = 1;
+	stgdict->ffi_type_pointer = ffi_type_pointer;
 
 	proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */
 	if (proto && -1 == PointerType_SetProto(stgdict, proto)) {
@@ -899,7 +904,7 @@
 	PyObject *typedict;
 	int length;
 
-	int itemsize, itemalign, itemlen;
+	int itemsize, itemalign;
 
 	typedict = PyTuple_GetItem(args, 2);
 	if (!typedict)
@@ -936,7 +941,6 @@
 
 	itemsize = itemdict->size;
 	itemalign = itemdict->align;
-	itemlen = itemdict->length;
 
 	stgdict->size = itemsize * length;
 	stgdict->align = itemalign;
@@ -945,7 +949,7 @@
 	stgdict->proto = proto;
 
 	/* Arrays are passed as pointers to function calls. */
-	stgdict->ffi_type = ffi_type_pointer;
+	stgdict->ffi_type_pointer = ffi_type_pointer;
 
 	/* create the new instance (which is a class,
 	   since we are a metatype!) */
@@ -1264,9 +1268,13 @@
 	PyTypeObject *result;
 	StgDictObject *stgdict;
 	PyObject *name = PyTuple_GET_ITEM(args, 0);
-	PyObject *swapped_args = PyTuple_New(PyTuple_GET_SIZE(args));
+	PyObject *swapped_args;
 	static PyObject *suffix;
-	int i;
+	Py_ssize_t i;
+
+	swapped_args = PyTuple_New(PyTuple_GET_SIZE(args));
+	if (!swapped_args)
+		return NULL;
 
 	if (suffix == NULL)
 #ifdef WORDS_BIGENDIAN
@@ -1275,8 +1283,10 @@
 		suffix = PyString_FromString("_be");
 #endif
 
-	Py_INCREF(suffix);
-	PyString_ConcatAndDel(&name, suffix);
+	Py_INCREF(name);
+	PyString_Concat(&name, suffix);
+	if (name == NULL)
+		return NULL;
 
 	PyTuple_SET_ITEM(swapped_args, 0, name);
 	for (i=1; i<PyTuple_GET_SIZE(args); ++i) {
@@ -1297,7 +1307,7 @@
 	if (!stgdict) /* XXX leaks result! */
 		return NULL;
 
-	stgdict->ffi_type = *fmt->pffi_type;
+	stgdict->ffi_type_pointer = *fmt->pffi_type;
 	stgdict->align = fmt->pffi_type->alignment;
 	stgdict->length = 0;
 	stgdict->size = fmt->pffi_type->size;
@@ -1355,7 +1365,7 @@
 
 	fmt = getentry(PyString_AS_STRING(proto));
 
-	stgdict->ffi_type = *fmt->pffi_type;
+	stgdict->ffi_type_pointer = *fmt->pffi_type;
 	stgdict->align = fmt->pffi_type->alignment;
 	stgdict->length = 0;
 	stgdict->size = fmt->pffi_type->size;
@@ -1450,6 +1460,7 @@
 		PyObject_SetAttrString(swapped, "__ctype_le__", (PyObject *)result);
 		PyObject_SetAttrString(swapped, "__ctype_be__", swapped);
 #endif
+		Py_DECREF(swapped);
 	};
 
 	return (PyObject *)result;
@@ -1624,7 +1635,7 @@
 	stgdict->size = sizeof(void *);
 	stgdict->setfunc = NULL;
 	stgdict->getfunc = NULL;
-	stgdict->ffi_type = ffi_type_pointer;
+	stgdict->ffi_type_pointer = ffi_type_pointer;
 
 	ob = PyDict_GetItemString((PyObject *)stgdict, "_flags_");
 	if (!ob || !PyInt_Check(ob)) {
@@ -1846,7 +1857,7 @@
 	StgDictObject *dict = PyObject_stgdict((PyObject *)self);
 	Py_CLEAR(self->b_objects);
 	if ((self->b_needsfree)
-	    && (dict->size > sizeof(self->b_value)))
+	    && ((size_t)dict->size > sizeof(self->b_value)))
 		PyMem_Free(self->b_ptr);
 	self->b_ptr = NULL;
 	Py_CLEAR(self->b_base);
@@ -1873,8 +1884,9 @@
 	{ NULL },
 };
 
-static Py_ssize_t CData_GetBuffer(CDataObject *self, Py_ssize_t seg, void **pptr)
+static Py_ssize_t CData_GetBuffer(PyObject *_self, Py_ssize_t seg, void **pptr)
 {
+	CDataObject *self = (CDataObject *)_self;
 	if (seg != 0) {
 		/* Hm. Must this set an exception? */
 		return -1;
@@ -1883,7 +1895,7 @@
 	return self->b_size;
 }
 
-static Py_ssize_t CData_GetSegcount(CDataObject *self, Py_ssize_t *lenp)
+static Py_ssize_t CData_GetSegcount(PyObject *_self, Py_ssize_t *lenp)
 {
 	if (lenp)
 		*lenp = 1;
@@ -1891,10 +1903,10 @@
 }
 
 static PyBufferProcs CData_as_buffer = {
-	(readbufferproc)CData_GetBuffer,
-	(writebufferproc)CData_GetBuffer,
-	(segcountproc)CData_GetSegcount,
-	(charbufferproc)NULL,
+	CData_GetBuffer,
+	CData_GetBuffer,
+	CData_GetSegcount,
+	NULL,
 };
 
 /*
@@ -1967,7 +1979,7 @@
 
 static void CData_MallocBuffer(CDataObject *obj, StgDictObject *dict)
 {
-	if (dict->size <= sizeof(obj->b_value)) {
+	if ((size_t)dict->size <= sizeof(obj->b_value)) {
 		/* No need to call malloc, can use the default buffer */
 		obj->b_ptr = (char *)&obj->b_value;
 		obj->b_needsfree = 1;
@@ -1975,7 +1987,7 @@
 		/* In python 2.4, and ctypes 0.9.6, the malloc call took about
 		   33% of the creation time for c_int().
 		*/
-		obj->b_ptr = PyMem_Malloc(dict->size);
+		obj->b_ptr = (char *)PyMem_Malloc(dict->size);
 		obj->b_needsfree = 1;
 		memset(obj->b_ptr, 0, dict->size);
 	}
@@ -2040,7 +2052,7 @@
 	if (!pd)
 		return NULL;
 	assert(CDataObject_Check(pd));
-	pd->b_ptr = buf;
+	pd->b_ptr = (char *)buf;
 	pd->b_length = dict->length;
 	pd->b_size = dict->size;
 	return (PyObject *)pd;
@@ -2383,6 +2395,11 @@
 	address = (PPROC)GetProcAddress(handle, name);
 	if (address)
 		return address;
+
+	if (((size_t)name & ~0xFFFF) == 0) {
+		return NULL;
+	}
+
 	/* It should not happen that dict is NULL, but better be safe */
 	if (dict==NULL || dict->flags & FUNCFLAG_CDECL)
 		return address;
@@ -2391,7 +2408,7 @@
 	   funcname -> _funcname@<n>
 	   where n is 0, 4, 8, 12, ..., 128
 	 */
-	mangled_name = _alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */
+	mangled_name = alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */
 	for (i = 0; i < 32; ++i) {
 		sprintf(mangled_name, "_%s@%d", name, i*4);
 		address = (PPROC)GetProcAddress(handle, mangled_name);
@@ -2488,6 +2505,28 @@
 	return 1;
 }
 
+static int
+_get_name(PyObject *obj, char **pname)
+{
+#ifdef MS_WIN32
+	if (PyInt_Check(obj) || PyLong_Check(obj)) {
+		/* We have to use MAKEINTRESOURCEA for Windows CE.
+		   Works on Windows as well, of course.
+		*/
+		*pname = MAKEINTRESOURCEA(PyInt_AsUnsignedLongMask(obj) & 0xFFFF);
+		return 1;
+	}
+#endif
+	if (PyString_Check(obj) || PyUnicode_Check(obj)) {
+		*pname = PyString_AsString(obj);
+		return *pname ? 1 : 0;
+	}
+	PyErr_SetString(PyExc_TypeError,
+			"function name must be string or integer");
+	return 0;
+}
+
+
 static PyObject *
 CFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
@@ -2499,7 +2538,7 @@
 	void *handle;
 	PyObject *paramflags = NULL;
 
-	if (!PyArg_ParseTuple(args, "sO|O", &name, &dll, &paramflags))
+	if (!PyArg_ParseTuple(args, "(O&O)|O", _get_name, &name, &dll, &paramflags))
 		return NULL;
 	if (paramflags == Py_None)
 		paramflags = NULL;
@@ -2524,9 +2563,14 @@
 #ifdef MS_WIN32
 	address = FindAddress(handle, name, (PyObject *)type);
 	if (!address) {
-		PyErr_Format(PyExc_AttributeError,
-			     "function '%s' not found",
-			     name);
+		if (!IS_INTRESOURCE(name))
+			PyErr_Format(PyExc_AttributeError,
+				     "function '%s' not found",
+				     name);
+		else
+			PyErr_Format(PyExc_AttributeError,
+				     "function ordinal %d not found",
+				     (WORD)(size_t)name);
 		return NULL;
 	}
 #else
@@ -2603,8 +2647,9 @@
   "O" - must be a callable, creates a C callable function
 
   two or more argument forms (the third argument is a paramflags tuple)
-  "sO|O" - function name, dll object (with an integer handle)
-  "is|O" - vtable index, method name, creates callable calling COM vtbl
+  "(sO)|..." - (function name, dll object (with an integer handle)), paramflags
+  "(iO)|..." - (function ordinal, dll object (with an integer handle)), paramflags
+  "is|..." - vtable index, method name, creates callable calling COM vtbl
 */
 static PyObject *
 CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -2612,19 +2657,18 @@
 	CFuncPtrObject *self;
 	PyObject *callable;
 	StgDictObject *dict;
-	THUNK thunk;
+	ffi_info *thunk;
 
 	if (PyTuple_GET_SIZE(args) == 0)
 		return GenericCData_new(type, args, kwds);
 
-	/* Shouldn't the following better be done in __init__? */
-	if (2 <= PyTuple_GET_SIZE(args)) {
-#ifdef MS_WIN32
-		if (PyInt_Check(PyTuple_GET_ITEM(args, 0)))
-			return CFuncPtr_FromVtblIndex(type, args, kwds);
-#endif
+	if (1 <= PyTuple_GET_SIZE(args) && PyTuple_Check(PyTuple_GET_ITEM(args, 0)))
 		return CFuncPtr_FromDll(type, args, kwds);
-	}
+
+#ifdef MS_WIN32
+	if (2 <= PyTuple_GET_SIZE(args) && PyInt_Check(PyTuple_GET_ITEM(args, 0)))
+		return CFuncPtr_FromVtblIndex(type, args, kwds);
+#endif
 
 	if (1 == PyTuple_GET_SIZE(args)
 	    && (PyInt_Check(PyTuple_GET_ITEM(args, 0))
@@ -2781,7 +2825,7 @@
 static PyObject *
 _build_callargs(CFuncPtrObject *self, PyObject *argtypes,
 		PyObject *inargs, PyObject *kwds,
-		int *poutmask, int *pinoutmask, int *pnumretvals)
+		int *poutmask, int *pinoutmask, unsigned int *pnumretvals)
 {
 	PyObject *paramflags = self->paramflags;
 	PyObject *callargs;
@@ -2835,8 +2879,14 @@
 
 		switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) {
 		case PARAMFLAG_FIN | PARAMFLAG_FLCID:
-			/* ['in', 'lcid'] parameter.  Always taken from defval */
-			Py_INCREF(defval);
+			/* ['in', 'lcid'] parameter.  Always taken from defval,
+			 if given, else the integer 0. */
+			if (defval == NULL) {
+				defval = PyInt_FromLong(0);
+				if (defval == NULL)
+					goto error;
+			} else
+				Py_INCREF(defval);
 			PyTuple_SET_ITEM(callargs, i, defval);
 			break;
 		case (PARAMFLAG_FIN | PARAMFLAG_FOUT):
@@ -2939,9 +2989,10 @@
 */
 static PyObject *
 _build_result(PyObject *result, PyObject *callargs,
-	      int outmask, int inoutmask, int numretvals)
+	      int outmask, int inoutmask, unsigned int numretvals)
 {
-	int i, index, bit;
+	unsigned int i, index;
+	int bit;
 	PyObject *tup = NULL;
 
 	if (callargs == NULL)
@@ -2952,6 +3003,7 @@
 	}
 	Py_DECREF(result);
 
+	/* tup will not be allocated if numretvals == 1 */
 	/* allocate tuple to hold the result */
 	if (numretvals > 1) {
 		tup = PyTuple_New(numretvals);
@@ -3009,7 +3061,7 @@
 
 	int inoutmask;
 	int outmask;
-	int numretvals;
+	unsigned int numretvals;
 
 	assert(dict); /* if not, it's a bug */
 	restype = self->restype ? self->restype : dict->restype;
@@ -3145,9 +3197,11 @@
 	Py_CLEAR(self->converters);
 	Py_CLEAR(self->paramflags);
 
-	if (self->thunk)
-		FreeCallback(self->thunk);
-	self->thunk = NULL;
+	if (self->thunk) {
+		FreeClosure(self->thunk->pcl);
+		PyMem_Free(self->thunk);
+		self->thunk = NULL;
+	}
 
 	return CData_clear((CDataObject *)self);
 }
@@ -3241,7 +3295,7 @@
 
 	parg->tag = 'V';
 	stgdict = PyObject_stgdict((PyObject *)self);
-	parg->pffi_type = &stgdict->ffi_type;
+	parg->pffi_type = &stgdict->ffi_type_pointer;
 	/* For structure parameters (by value), parg->value doesn't contain the structure
 	   data itself, instead parg->value.p *points* to the structure's data
 	   See also _ctypes.c, function _call_function_pointer().
@@ -3275,6 +3329,8 @@
 		if (!fields) {
 			PyErr_Clear();
 			fields = PyTuple_New(0);
+			if (!fields)
+				return -1;
 		}
 
 		if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) {
@@ -3445,8 +3501,9 @@
 }
 
 static PyObject *
-Array_item(CDataObject *self, int index)
+Array_item(PyObject *_self, Py_ssize_t index)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int offset, size;
 	StgDictObject *stgdict;
 
@@ -3469,8 +3526,9 @@
 }
 
 static PyObject *
-Array_slice(CDataObject *self, Py_ssize_t ilow, Py_ssize_t ihigh)
+Array_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh)
 {
+	CDataObject *self = (CDataObject *)_self;
 	StgDictObject *stgdict, *itemdict;
 	PyObject *proto;
 	PyListObject *np;
@@ -3504,15 +3562,16 @@
 		return NULL;
 
 	for (i = 0; i < len; i++) {
-		PyObject *v = Array_item(self, i+ilow);
+		PyObject *v = Array_item(_self, i+ilow);
 		PyList_SET_ITEM(np, i, v);
 	}
 	return (PyObject *)np;
 }
 
 static int
-Array_ass_item(CDataObject *self, int index, PyObject *value)
+Array_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int size, offset;
 	StgDictObject *stgdict;
 	char *ptr;
@@ -3538,8 +3597,9 @@
 }
 
 static int
-Array_ass_slice(CDataObject *self, int ilow, int ihigh, PyObject *value)
+Array_ass_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *value)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int i, len;
 
 	if (value == NULL) {
@@ -3570,7 +3630,7 @@
 		int result;
 		if (item == NULL)
 			return -1;
-		result = Array_ass_item(self, i+ilow, item);
+		result = Array_ass_item(_self, i+ilow, item);
 		Py_DECREF(item);
 		if (result == -1)
 			return -1;
@@ -3578,20 +3638,21 @@
 	return 0;
 }
 
-static int
-Array_length(CDataObject *self)
+static Py_ssize_t
+Array_length(PyObject *_self)
 {
+	CDataObject *self = (CDataObject *)_self;
 	return self->b_length;
 }
 
 static PySequenceMethods Array_as_sequence = {
-	(lenfunc)Array_length,			/* sq_length; */
+	Array_length,				/* sq_length; */
 	0,					/* sq_concat; */
 	0,					/* sq_repeat; */
-	(ssizeargfunc)Array_item,		/* sq_item; */
-	(ssizessizeargfunc)Array_slice,		/* sq_slice; */
-	(ssizeobjargproc)Array_ass_item,	/* sq_ass_item; */
-	(ssizessizeobjargproc)Array_ass_slice,	/* sq_ass_slice; */
+	Array_item,				/* sq_item; */
+	Array_slice,				/* sq_slice; */
+	Array_ass_item,				/* sq_ass_item; */
+	Array_ass_slice,			/* sq_ass_slice; */
 	0,					/* sq_contains; */
 	
 	0,					/* sq_inplace_concat; */
@@ -3942,8 +4003,9 @@
   Pointer_Type
 */
 static PyObject *
-Pointer_item(CDataObject *self, int index)
+Pointer_item(PyObject *_self, Py_ssize_t index)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int size, offset;
 	StgDictObject *stgdict, *itemdict;
 	PyObject *proto;
@@ -3969,8 +4031,9 @@
 }
 
 static int
-Pointer_ass_item(CDataObject *self, int index, PyObject *value)
+Pointer_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
 {
+	CDataObject *self = (CDataObject *)_self;
 	int size;
 	StgDictObject *stgdict;
 
@@ -4111,8 +4174,9 @@
 }
 
 static PyObject *
-Pointer_slice(CDataObject *self, Py_ssize_t ilow, Py_ssize_t ihigh)
+Pointer_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh)
 {
+	CDataObject *self = (CDataObject *)_self;
 	PyListObject *np;
 	StgDictObject *stgdict, *itemdict;
 	PyObject *proto;
@@ -4142,7 +4206,7 @@
 		return NULL;
 
 	for (i = 0; i < len; i++) {
-		PyObject *v = Pointer_item(self, i+ilow);
+		PyObject *v = Pointer_item(_self, i+ilow);
 		PyList_SET_ITEM(np, i, v);
 	}
 	return (PyObject *)np;
@@ -4152,9 +4216,9 @@
 	0,					/* inquiry sq_length; */
 	0,					/* binaryfunc sq_concat; */
 	0,					/* intargfunc sq_repeat; */
-	(ssizeargfunc)Pointer_item,		/* intargfunc sq_item; */
-	(ssizessizeargfunc)Pointer_slice,	/* intintargfunc sq_slice; */
-	(ssizeobjargproc)Pointer_ass_item,	/* intobjargproc sq_ass_item; */
+	Pointer_item,				/* intargfunc sq_item; */
+	Pointer_slice,				/* intintargfunc sq_slice; */
+	Pointer_ass_item,			/* intobjargproc sq_ass_item; */
 	0,					/* intintobjargproc sq_ass_slice; */
 	0,					/* objobjproc sq_contains; */
 	/* Added in release 2.0 */
@@ -4334,6 +4398,42 @@
 	return PyString_FromStringAndSize(ptr, size);
 }
 
+static int
+cast_check_pointertype(PyObject *arg)
+{
+	StgDictObject *dict;
+
+	if (PointerTypeObject_Check(arg))
+		return 1;
+	dict = PyType_stgdict(arg);
+	if (dict) {
+		if (PyString_Check(dict->proto)
+		    && (strchr("sPzUZXO", PyString_AS_STRING(dict->proto)[0]))) {
+			/* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
+			return 1;
+		}
+	}
+	PyErr_Format(PyExc_TypeError,
+		     "cast() argument 2 must be a pointer type, not %s",
+		     PyType_Check(arg)
+		     ? ((PyTypeObject *)arg)->tp_name
+		     : arg->ob_type->tp_name);
+	return 0;
+}
+
+static PyObject *
+cast(void *ptr, PyObject *ctype)
+{
+	CDataObject *result;
+	if (0 == cast_check_pointertype(ctype))
+		return NULL;
+	result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL);
+	if (result == NULL)
+		return NULL;
+	/* Should we assert that result is a pointer type? */
+	memcpy(result->b_ptr, &ptr, sizeof(void *));
+	return (PyObject *)result;
+}
 
 #ifdef CTYPES_UNICODE
 static PyObject *
@@ -4469,14 +4569,25 @@
 	PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove));
 	PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset));
 	PyModule_AddObject(m, "_string_at_addr", PyLong_FromVoidPtr(string_at));
+	PyModule_AddObject(m, "_cast_addr", PyLong_FromVoidPtr(cast));
 #ifdef CTYPES_UNICODE
 	PyModule_AddObject(m, "_wstring_at_addr", PyLong_FromVoidPtr(wstring_at));
 #endif
 
-#ifdef RTLD_LOCAL
+/* If RTLD_LOCAL is not defined (Windows!), set it to zero. */
+#ifndef RTLD_LOCAL
+#define RTLD_LOCAL 0
+#endif
+
+/* If RTLD_GLOBAL is not defined (cygwin), set it to the same value as
+   RTLD_LOCAL.
+*/
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL RTLD_LOCAL
+#endif
+
 	PyModule_AddObject(m, "RTLD_LOCAL", PyInt_FromLong(RTLD_LOCAL));
 	PyModule_AddObject(m, "RTLD_GLOBAL", PyInt_FromLong(RTLD_GLOBAL));
-#endif
 	
 	PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL);
 	if (PyExc_ArgError) {
diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
index a46f5e4..ad3b047 100644
--- a/Modules/_ctypes/_ctypes_test.c
+++ b/Modules/_ctypes/_ctypes_test.c
@@ -51,21 +51,21 @@
 	*presult = a + b;
 }
 
-EXPORT(int) _testfunc_i_bhilfd(char b, short h, int i, long l, float f, double d)
+EXPORT(int) _testfunc_i_bhilfd(signed char b, short h, int i, long l, float f, double d)
 {
 //	printf("_testfunc_i_bhilfd got %d %d %d %ld %f %f\n",
 //	       b, h, i, l, f, d);
 	return (int)(b + h + i + l + f + d);
 }
 
-EXPORT(float) _testfunc_f_bhilfd(char b, short h, int i, long l, float f, double d)
+EXPORT(float) _testfunc_f_bhilfd(signed char b, short h, int i, long l, float f, double d)
 {
 //	printf("_testfunc_f_bhilfd got %d %d %d %ld %f %f\n",
 //	       b, h, i, l, f, d);
 	return (float)(b + h + i + l + f + d);
 }
 
-EXPORT(double) _testfunc_d_bhilfd(char b, short h, int i, long l, float f, double d)
+EXPORT(double) _testfunc_d_bhilfd(signed char b, short h, int i, long l, float f, double d)
 {
 //	printf("_testfunc_d_bhilfd got %d %d %d %ld %f %f\n",
 //	       b, h, i, l, f, d);
@@ -74,7 +74,7 @@
 
 EXPORT(char *) _testfunc_p_p(void *s)
 {
-	return s;
+	return (char *)s;
 }
 
 EXPORT(void *) _testfunc_c_p_p(int *argcp, char **argv)
@@ -89,7 +89,7 @@
 
 EXPORT(char *) my_strdup(char *src)
 {
-	char *dst = malloc(strlen(src)+1);
+	char *dst = (char *)malloc(strlen(src)+1);
 	if (!dst)
 		return NULL;
 	strcpy(dst, src);
@@ -99,8 +99,8 @@
 #ifdef HAVE_WCHAR_H
 EXPORT(wchar_t *) my_wcsdup(wchar_t *src)
 {
-	int len = wcslen(src);
-	wchar_t *ptr = malloc((len + 1) * sizeof(wchar_t));
+	size_t len = wcslen(src);
+	wchar_t *ptr = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
 	if (ptr == NULL)
 		return NULL;
 	memcpy(ptr, src, (len+1) * sizeof(wchar_t));
@@ -152,13 +152,13 @@
 }
 
 #ifdef HAVE_LONG_LONG
-EXPORT(PY_LONG_LONG) _testfunc_q_bhilfdq(char b, short h, int i, long l, float f,
+EXPORT(PY_LONG_LONG) _testfunc_q_bhilfdq(signed char b, short h, int i, long l, float f,
 				     double d, PY_LONG_LONG q)
 {
 	return (PY_LONG_LONG)(b + h + i + l + f + d + q);
 }
 
-EXPORT(PY_LONG_LONG) _testfunc_q_bhilfd(char b, short h, int i, long l, float f, double d)
+EXPORT(PY_LONG_LONG) _testfunc_q_bhilfd(signed char b, short h, int i, long l, float f, double d)
 {
 	return (PY_LONG_LONG)(b + h + i + l + f + d);
 }
@@ -191,7 +191,7 @@
 {
 	static char message[] = "Hello, World";
 	if (p) {
-		*p = malloc(sizeof(char *));
+		*p = (char **)malloc(sizeof(char *));
 		printf("malloc returned %p\n", *p);
 		**p = message;
 		return 1;
@@ -385,7 +385,7 @@
 #define S last_tf_arg_s = (PY_LONG_LONG)c
 #define U last_tf_arg_u = (unsigned PY_LONG_LONG)c
 
-EXPORT(char) tf_b(char c) { S; return c/3; }
+EXPORT(signed char) tf_b(signed char c) { S; return c/3; }
 EXPORT(unsigned char) tf_B(unsigned char c) { U; return c/3; }
 EXPORT(short) tf_h(short c) { S; return c/3; }
 EXPORT(unsigned short) tf_H(unsigned short c) { U; return c/3; }
@@ -399,7 +399,7 @@
 EXPORT(double) tf_d(double c) { S; return c/3; }
 
 #ifdef MS_WIN32
-EXPORT(char) __stdcall s_tf_b(char c) { S; return c/3; }
+EXPORT(signed char) __stdcall s_tf_b(signed char c) { S; return c/3; }
 EXPORT(unsigned char) __stdcall s_tf_B(unsigned char c) { U; return c/3; }
 EXPORT(short) __stdcall s_tf_h(short c) { S; return c/3; }
 EXPORT(unsigned short) __stdcall s_tf_H(unsigned short c) { U; return c/3; }
@@ -414,33 +414,33 @@
 #endif
 /*******/
 
-EXPORT(char) tf_bb(char x, char c) { S; return c/3; }
-EXPORT(unsigned char) tf_bB(char x, unsigned char c) { U; return c/3; }
-EXPORT(short) tf_bh(char x, short c) { S; return c/3; }
-EXPORT(unsigned short) tf_bH(char x, unsigned short c) { U; return c/3; }
-EXPORT(int) tf_bi(char x, int c) { S; return c/3; }
-EXPORT(unsigned int) tf_bI(char x, unsigned int c) { U; return c/3; }
-EXPORT(long) tf_bl(char x, long c) { S; return c/3; }
-EXPORT(unsigned long) tf_bL(char x, unsigned long c) { U; return c/3; }
-EXPORT(PY_LONG_LONG) tf_bq(char x, PY_LONG_LONG c) { S; return c/3; }
-EXPORT(unsigned PY_LONG_LONG) tf_bQ(char x, unsigned PY_LONG_LONG c) { U; return c/3; }
-EXPORT(float) tf_bf(char x, float c) { S; return c/3; }
-EXPORT(double) tf_bd(char x, double c) { S; return c/3; }
+EXPORT(signed char) tf_bb(signed char x, signed char c) { S; return c/3; }
+EXPORT(unsigned char) tf_bB(signed char x, unsigned char c) { U; return c/3; }
+EXPORT(short) tf_bh(signed char x, short c) { S; return c/3; }
+EXPORT(unsigned short) tf_bH(signed char x, unsigned short c) { U; return c/3; }
+EXPORT(int) tf_bi(signed char x, int c) { S; return c/3; }
+EXPORT(unsigned int) tf_bI(signed char x, unsigned int c) { U; return c/3; }
+EXPORT(long) tf_bl(signed char x, long c) { S; return c/3; }
+EXPORT(unsigned long) tf_bL(signed char x, unsigned long c) { U; return c/3; }
+EXPORT(PY_LONG_LONG) tf_bq(signed char x, PY_LONG_LONG c) { S; return c/3; }
+EXPORT(unsigned PY_LONG_LONG) tf_bQ(signed char x, unsigned PY_LONG_LONG c) { U; return c/3; }
+EXPORT(float) tf_bf(signed char x, float c) { S; return c/3; }
+EXPORT(double) tf_bd(signed char x, double c) { S; return c/3; }
 EXPORT(void) tv_i(int c) { S; return; }
 
 #ifdef MS_WIN32
-EXPORT(char) __stdcall s_tf_bb(char x, char c) { S; return c/3; }
-EXPORT(unsigned char) __stdcall s_tf_bB(char x, unsigned char c) { U; return c/3; }
-EXPORT(short) __stdcall s_tf_bh(char x, short c) { S; return c/3; }
-EXPORT(unsigned short) __stdcall s_tf_bH(char x, unsigned short c) { U; return c/3; }
-EXPORT(int) __stdcall s_tf_bi(char x, int c) { S; return c/3; }
-EXPORT(unsigned int) __stdcall s_tf_bI(char x, unsigned int c) { U; return c/3; }
-EXPORT(long) __stdcall s_tf_bl(char x, long c) { S; return c/3; }
-EXPORT(unsigned long) __stdcall s_tf_bL(char x, unsigned long c) { U; return c/3; }
-EXPORT(PY_LONG_LONG) __stdcall s_tf_bq(char x, PY_LONG_LONG c) { S; return c/3; }
-EXPORT(unsigned PY_LONG_LONG) __stdcall s_tf_bQ(char x, unsigned PY_LONG_LONG c) { U; return c/3; }
-EXPORT(float) __stdcall s_tf_bf(char x, float c) { S; return c/3; }
-EXPORT(double) __stdcall s_tf_bd(char x, double c) { S; return c/3; }
+EXPORT(signed char) __stdcall s_tf_bb(signed char x, signed char c) { S; return c/3; }
+EXPORT(unsigned char) __stdcall s_tf_bB(signed char x, unsigned char c) { U; return c/3; }
+EXPORT(short) __stdcall s_tf_bh(signed char x, short c) { S; return c/3; }
+EXPORT(unsigned short) __stdcall s_tf_bH(signed char x, unsigned short c) { U; return c/3; }
+EXPORT(int) __stdcall s_tf_bi(signed char x, int c) { S; return c/3; }
+EXPORT(unsigned int) __stdcall s_tf_bI(signed char x, unsigned int c) { U; return c/3; }
+EXPORT(long) __stdcall s_tf_bl(signed char x, long c) { S; return c/3; }
+EXPORT(unsigned long) __stdcall s_tf_bL(signed char x, unsigned long c) { U; return c/3; }
+EXPORT(PY_LONG_LONG) __stdcall s_tf_bq(signed char x, PY_LONG_LONG c) { S; return c/3; }
+EXPORT(unsigned PY_LONG_LONG) __stdcall s_tf_bQ(signed char x, unsigned PY_LONG_LONG c) { U; return c/3; }
+EXPORT(float) __stdcall s_tf_bf(signed char x, float c) { S; return c/3; }
+EXPORT(double) __stdcall s_tf_bd(signed char x, double c) { S; return c/3; }
 EXPORT(void) __stdcall s_tv_i(int c) { S; return; }
 #endif
 
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index 2948d98..8c29c55 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -264,16 +264,6 @@
 	PyGILState_Release(state);
 }
 
-typedef struct {
-	ffi_closure *pcl; /* the C callable */
-	ffi_cif cif;
-	PyObject *converters;
-	PyObject *callable;
-	SETFUNC setfunc;
-	ffi_type *restype;
-	ffi_type *atypes[0];
-} ffi_info;
-
 static void closure_fcn(ffi_cif *cif,
 			void *resp,
 			void **args,
@@ -289,16 +279,10 @@
 			  args);
 }
 
-void FreeCallback(THUNK thunk)
-{
-	FreeClosure(((ffi_info *)thunk)->pcl);
-	PyMem_Free(thunk);
-}
-
-THUNK AllocFunctionCallback(PyObject *callable,
-			    PyObject *converters,
-			    PyObject *restype,
-			    int is_cdecl)
+ffi_info *AllocFunctionCallback(PyObject *callable,
+				PyObject *converters,
+				PyObject *restype,
+				int is_cdecl)
 {
 	int result;
 	ffi_info *p;
@@ -313,13 +297,14 @@
 	}
 	p->pcl = MallocClosure();
 	if (p->pcl == NULL) {
-		PyMem_Free(p);
 		PyErr_NoMemory();
-		return NULL;
+		goto error;
 	}
 
 	for (i = 0; i < nArgs; ++i) {
 		PyObject *cnv = PySequence_GetItem(converters, i);
+		if (cnv == NULL)
+			goto error;
 		p->atypes[i] = GetType(cnv);
 		Py_DECREF(cnv);
 	}
@@ -330,12 +315,10 @@
 		p->restype = &ffi_type_void;
 	} else {
 		StgDictObject *dict = PyType_stgdict(restype);
-		if (dict == NULL) {
-			PyMem_Free(p);
-			return NULL;
-		}
+		if (dict == NULL)
+			goto error;
 		p->setfunc = dict->setfunc;
-		p->restype = &dict->ffi_type;
+		p->restype = &dict->ffi_type_pointer;
 	}
 
 	cc = FFI_DEFAULT_ABI;
@@ -349,21 +332,26 @@
 	if (result != FFI_OK) {
 		PyErr_Format(PyExc_RuntimeError,
 			     "ffi_prep_cif failed with %d", result);
-		PyMem_Free(p);
-		return NULL;
+		goto error;
 	}
 	result = ffi_prep_closure(p->pcl, &p->cif, closure_fcn, p);
 	if (result != FFI_OK) {
 		PyErr_Format(PyExc_RuntimeError,
 			     "ffi_prep_closure failed with %d", result);
-		PyMem_Free(p);
-		return NULL;
+		goto error;
 	}
 
 	p->converters = converters;
 	p->callable = callable;
+	return p;
 
-	return (THUNK)p;
+  error:
+	if (p) {
+		if (p->pcl)
+			FreeClosure(p->pcl);
+		PyMem_Free(p);
+	}
+	return NULL;
 }
 
 /****************************************************************************
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 9d9e322..8163f49 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -64,14 +64,17 @@
 #endif
 
 #ifdef MS_WIN32
-#define alloca _alloca
+#include <malloc.h>
 #endif
 
 #include <ffi.h>
 #include "ctypes.h"
 
-#ifdef _DEBUG
-#define DEBUG_EXCEPTIONS /* */
+#if defined(_DEBUG) || defined(__MINGW32__)
+/* Don't use structured exception handling on Windows if this is defined.
+   MingW, AFAIK, doesn't support it.
+*/
+#define DONT_USE_SEH
 #endif
 
 #ifdef MS_WIN32
@@ -96,6 +99,7 @@
 	return lpMsgBuf;
 }
 
+#ifndef DONT_USE_SEH
 void SetException(DWORD code, EXCEPTION_RECORD *pr)
 {
 	TCHAR *lpMsgBuf;
@@ -254,6 +258,7 @@
 	*record = *ptrs->ExceptionRecord;
 	return EXCEPTION_EXECUTE_HANDLER;
 }
+#endif
 
 static PyObject *
 check_hresult(PyObject *self, PyObject *args)
@@ -576,14 +581,14 @@
 	/* This little trick works correctly with MSVC.
 	   It returns small structures in registers
 	*/
-	if (dict->ffi_type.type == FFI_TYPE_STRUCT) {
-		if (dict->ffi_type.size <= 4)
+	if (dict->ffi_type_pointer.type == FFI_TYPE_STRUCT) {
+		if (dict->ffi_type_pointer.size <= 4)
 			return &ffi_type_sint32;
-		else if (dict->ffi_type.size <= 8)
+		else if (dict->ffi_type_pointer.size <= 8)
 			return &ffi_type_sint64;
 	}
 #endif
-	return &dict->ffi_type;
+	return &dict->ffi_type_pointer;
 }
 
 
@@ -612,9 +617,11 @@
 	int cc;
 #ifdef MS_WIN32
 	int delta;
+#ifndef DONT_USE_SEH
 	DWORD dwExceptionCode = 0;
 	EXCEPTION_RECORD record;
 #endif
+#endif
 	/* XXX check before here */
 	if (restype == NULL) {
 		PyErr_SetString(PyExc_RuntimeError,
@@ -640,14 +647,14 @@
 	if ((flags & FUNCFLAG_PYTHONAPI) == 0)
 		Py_UNBLOCK_THREADS
 #ifdef MS_WIN32
-#ifndef DEBUG_EXCEPTIONS
+#ifndef DONT_USE_SEH
 	__try {
 #endif
 		delta =
 #endif
 			ffi_call(&cif, (void *)pProc, resmem, avalues);
 #ifdef MS_WIN32
-#ifndef DEBUG_EXCEPTIONS
+#ifndef DONT_USE_SEH
 	}
 	__except (HandleException(GetExceptionInformation(),
 				  &dwExceptionCode, &record)) {
@@ -658,10 +665,12 @@
 	if ((flags & FUNCFLAG_PYTHONAPI) == 0)
 		Py_BLOCK_THREADS
 #ifdef MS_WIN32
+#ifndef DONT_USE_SEH
 	if (dwExceptionCode) {
 		SetException(dwExceptionCode, &record);
 		return -1;
 	}
+#endif
 	if (delta < 0) {
 		if (flags & FUNCFLAG_CDECL)
 			PyErr_Format(PyExc_ValueError,
@@ -758,6 +767,8 @@
 	if (cls_str) {
 		PyString_ConcatAndDel(&s, cls_str);
 		PyString_ConcatAndDel(&s, PyString_FromString(": "));
+		if (s == NULL)
+			goto error;
 	} else
 		PyErr_Clear();
 	msg_str = PyObject_Str(v);
@@ -766,12 +777,15 @@
 	else {
 		PyErr_Clear();
 		PyString_ConcatAndDel(&s, PyString_FromString("???"));
+		if (s == NULL)
+			goto error;
 	}
 	PyErr_SetObject(exc_class, s);
+error:
 	Py_XDECREF(tp);
 	Py_XDECREF(v);
 	Py_XDECREF(tb);
-	Py_DECREF(s);
+	Py_XDECREF(s);
 }
 
 
@@ -1363,7 +1377,7 @@
 converter(PyObject *obj, void **address)
 {
 	*address = PyLong_AsVoidPtr(obj);
-	return address != NULL;
+	return *address != NULL;
 }
 
 static PyObject *
@@ -1423,71 +1437,7 @@
 }
 #endif
 
-static char cast_doc[] =
-"cast(cobject, ctype) -> ctype-instance\n\
-\n\
-Create an instance of ctype, and copy the internal memory buffer\n\
-of cobject to the new instance.  Should be used to cast one type\n\
-of pointer to another type of pointer.\n\
-Doesn't work correctly with ctypes integers.\n";
-
-static int cast_check_pointertype(PyObject *arg, PyObject **pobj)
-{
-	StgDictObject *dict;
-
-	if (PointerTypeObject_Check(arg)) {
-		*pobj = arg;
-		return 1;
-	}
-	dict = PyType_stgdict(arg);
-	if (dict) {
-		if (PyString_Check(dict->proto)
-		    && (strchr("sPzUZXO", PyString_AS_STRING(dict->proto)[0]))) {
-			/* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
-			*pobj = arg;
-			return 1;
-		}
-	}
-	if (PyType_Check(arg)) {
-		PyErr_Format(PyExc_TypeError,
-			     "cast() argument 2 must be a pointer type, not %s",
-			     ((PyTypeObject *)arg)->tp_name);
-	} else {
-		PyErr_Format(PyExc_TypeError,
-			     "cast() argument 2 must be a pointer type, not a %s",
-			     arg->ob_type->tp_name);
-	}
-	return 0;
-}
-
-static PyObject *cast(PyObject *self, PyObject *args)
-{
-	PyObject *obj, *ctype;
-	struct argument a;
-	CDataObject *result;
-
-	/* We could and should allow array types for the second argument
-	   also, but we cannot use the simple memcpy below for them. */
-	if (!PyArg_ParseTuple(args, "OO&:cast", &obj, &cast_check_pointertype, &ctype))
-		return NULL;
-	if (-1 == ConvParam(obj, 1, &a))
-		return NULL;
-	result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL);
-	if (result == NULL) {
-		Py_XDECREF(a.keep);
-		return NULL;
-	}
-	// result->b_size
-	// a.ffi_type->size
-	memcpy(result->b_ptr, &a.value,
-	       min(result->b_size, (int)a.ffi_type->size));
-	Py_XDECREF(a.keep);
-	return (PyObject *)result;
-}
-
-
 PyMethodDef module_methods[] = {
-	{"cast", cast, METH_VARARGS, cast_doc},
 #ifdef CTYPES_UNICODE
 	{"set_conversion_mode", set_conversion_mode, METH_VARARGS, set_conversion_mode_doc},
 #endif
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c
index 336f265..7bef412 100644
--- a/Modules/_ctypes/cfield.c
+++ b/Modules/_ctypes/cfield.c
@@ -499,7 +499,7 @@
 	long val;
 	if (get_long(value, &val) < 0)
 		return NULL;
-	*(char *)ptr = (char)SET(*(char *)ptr, (char)val, size);
+	*(signed char *)ptr = (signed char)SET(*(signed char *)ptr, (signed char)val, size);
 	_RET(value);
 }
 
@@ -507,7 +507,7 @@
 static PyObject *
 b_get(void *ptr, unsigned size)
 {
-	char val = *(char *)ptr;
+	signed char val = *(signed char *)ptr;
 	GET_BITFIELD(val, size);
 	return PyInt_FromLong(val);
 }
@@ -536,9 +536,12 @@
 h_set(void *ptr, PyObject *value, unsigned size)
 {
 	long val;
+	short x;
 	if (get_long(value, &val) < 0)
 		return NULL;
-	*(short *)ptr = (short)SET(*(short *)ptr, (short)val, size);
+	memcpy(&x, ptr, sizeof(x));
+	x = SET(x, (short)val, size);
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
@@ -550,24 +553,28 @@
 	short field;
 	if (get_long(value, &val) < 0)
 		return NULL;
-	field = SWAP_2(*(short *)ptr);
+	memcpy(&field, ptr, sizeof(field));
+	field = SWAP_2(field);
 	field = SET(field, (short)val, size);
-	*(short *)ptr = SWAP_2(field);
+	field = SWAP_2(field);
+	memcpy(ptr, &field, sizeof(field));
 	_RET(value);
 }
 
 static PyObject *
 h_get(void *ptr, unsigned size)
 {
-	short val = *(short *)ptr;
+	short val;
+	memcpy(&val, ptr, sizeof(val));
 	GET_BITFIELD(val, size);
-	return PyInt_FromLong(val);
+	return PyInt_FromLong((long)val);
 }
 
 static PyObject *
 h_get_sw(void *ptr, unsigned size)
 {
-	short val = *(short *)ptr;
+	short val;
+	memcpy(&val, ptr, sizeof(val));
 	val = SWAP_2(val);
 	GET_BITFIELD(val, size);
 	return PyInt_FromLong(val);
@@ -577,10 +584,12 @@
 H_set(void *ptr, PyObject *value, unsigned size)
 {
 	unsigned long val;
+	unsigned short x;
 	if (get_ulong(value, &val) < 0)
 		return NULL;
-	*(unsigned short *)ptr = (unsigned short)SET(*(unsigned short *)ptr,
-						     (unsigned short)val, size);
+	memcpy(&x, ptr, sizeof(x));
+	x = SET(x, (unsigned short)val, size);
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
@@ -591,9 +600,11 @@
 	unsigned short field;
 	if (get_ulong(value, &val) < 0)
 		return NULL;
-	field = SWAP_2(*(unsigned short *)ptr);
+	memcpy(&field, ptr, sizeof(field));
+	field = SWAP_2(field);
 	field = SET(field, (unsigned short)val, size);
-	*(unsigned short *)ptr = SWAP_2(field);
+	field = SWAP_2(field);
+	memcpy(ptr, &field, sizeof(field));
 	_RET(value);
 }
 
@@ -601,7 +612,8 @@
 static PyObject *
 H_get(void *ptr, unsigned size)
 {
-	unsigned short val = *(unsigned short *)ptr;
+	unsigned short val;
+	memcpy(&val, ptr, sizeof(val));
 	GET_BITFIELD(val, size);
 	return PyInt_FromLong(val);
 }
@@ -609,7 +621,8 @@
 static PyObject *
 H_get_sw(void *ptr, unsigned size)
 {
-	unsigned short val = *(unsigned short *)ptr;
+	unsigned short val;
+	memcpy(&val, ptr, sizeof(val));
 	val = SWAP_2(val);
 	GET_BITFIELD(val, size);
 	return PyInt_FromLong(val);
@@ -619,9 +632,12 @@
 i_set(void *ptr, PyObject *value, unsigned size)
 {
 	long val;
+	int x;
 	if (get_long(value, &val) < 0)
 		return NULL;
-	*(int *)ptr = (int)SET(*(int *)ptr, (int)val, size);
+	memcpy(&x, ptr, sizeof(x));
+	x = SET(x, (int)val, size);
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
@@ -632,9 +648,11 @@
 	int field;
 	if (get_long(value, &val) < 0)
 		return NULL;
-	field = SWAP_INT(*(int *)ptr);
+	memcpy(&field, ptr, sizeof(field));
+	field = SWAP_INT(field);
 	field = SET(field, (int)val, size);
-	*(int *)ptr = SWAP_INT(field);
+	field = SWAP_INT(field);
+	memcpy(ptr, &field, sizeof(field));
 	_RET(value);
 }
 
@@ -642,7 +660,8 @@
 static PyObject *
 i_get(void *ptr, unsigned size)
 {
-	int val = *(int *)ptr;
+	int val;
+	memcpy(&val, ptr, sizeof(val));
 	GET_BITFIELD(val, size);
 	return PyInt_FromLong(val);
 }
@@ -650,7 +669,8 @@
 static PyObject *
 i_get_sw(void *ptr, unsigned size)
 {
-	int val = *(int *)ptr;
+	int val;
+	memcpy(&val, ptr, sizeof(val));
 	val = SWAP_INT(val);
 	GET_BITFIELD(val, size);
 	return PyInt_FromLong(val);
@@ -684,9 +704,12 @@
 I_set(void *ptr, PyObject *value, unsigned size)
 {
 	unsigned long val;
+	unsigned int x;
 	if (get_ulong(value, &val) < 0)
 		return  NULL;
-	*(unsigned int *)ptr = (unsigned int)SET(*(unsigned int *)ptr, (unsigned int)val, size);
+	memcpy(&x, ptr, sizeof(x));
+	x = SET(x, (unsigned int)val, size);
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
@@ -697,9 +720,10 @@
 	unsigned int field;
 	if (get_ulong(value, &val) < 0)
 		return  NULL;
-	field = SWAP_INT(*(unsigned int *)ptr);
+	memcpy(&field, ptr, sizeof(field));
 	field = (unsigned int)SET(field, (unsigned int)val, size);
-	*(unsigned int *)ptr = SWAP_INT(field);
+	field = SWAP_INT(field);
+	memcpy(ptr, &field, sizeof(field));
 	_RET(value);
 }
 
@@ -707,7 +731,8 @@
 static PyObject *
 I_get(void *ptr, unsigned size)
 {
-	unsigned int val = *(unsigned int *)ptr;
+	unsigned int val;
+	memcpy(&val, ptr, sizeof(val));
 	GET_BITFIELD(val, size);
 	return PyLong_FromUnsignedLong(val);
 }
@@ -715,7 +740,8 @@
 static PyObject *
 I_get_sw(void *ptr, unsigned size)
 {
-	unsigned int val = *(unsigned int *)ptr;
+	unsigned int val;
+	memcpy(&val, ptr, sizeof(val));
 	val = SWAP_INT(val);
 	GET_BITFIELD(val, size);
 	return PyLong_FromUnsignedLong(val);
@@ -725,9 +751,12 @@
 l_set(void *ptr, PyObject *value, unsigned size)
 {
 	long val;
+	long x;
 	if (get_long(value, &val) < 0)
 		return NULL;
-	*(long *)ptr = (long)SET(*(long *)ptr, val, size);
+	memcpy(&x, ptr, sizeof(x));
+	x = SET(x, val, size);
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
@@ -738,9 +767,11 @@
 	long field;
 	if (get_long(value, &val) < 0)
 		return NULL;
-	field = SWAP_LONG(*(long *)ptr);
+	memcpy(&field, ptr, sizeof(field));
+	field = SWAP_LONG(field);
 	field = (long)SET(field, val, size);
-	*(long *)ptr = SWAP_LONG(field);
+	field = SWAP_LONG(field);
+	memcpy(ptr, &field, sizeof(field));
 	_RET(value);
 }
 
@@ -748,7 +779,8 @@
 static PyObject *
 l_get(void *ptr, unsigned size)
 {
-	long val = *(long *)ptr;
+	long val;
+	memcpy(&val, ptr, sizeof(val));
 	GET_BITFIELD(val, size);
 	return PyInt_FromLong(val);
 }
@@ -756,7 +788,8 @@
 static PyObject *
 l_get_sw(void *ptr, unsigned size)
 {
-	long val = *(long *)ptr;
+	long val;
+	memcpy(&val, ptr, sizeof(val));
 	val = SWAP_LONG(val);
 	GET_BITFIELD(val, size);
 	return PyInt_FromLong(val);
@@ -766,9 +799,12 @@
 L_set(void *ptr, PyObject *value, unsigned size)
 {
 	unsigned long val;
+	unsigned long x;
 	if (get_ulong(value, &val) < 0)
 		return  NULL;
-	*(unsigned long *)ptr = (unsigned long)SET(*(unsigned long *)ptr, val, size);
+	memcpy(&x, ptr, sizeof(x));
+	x = SET(x, val, size);
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
@@ -779,9 +815,11 @@
 	unsigned long field;
 	if (get_ulong(value, &val) < 0)
 		return  NULL;
-	field = SWAP_LONG(*(unsigned long *)ptr);
+	memcpy(&field, ptr, sizeof(field));
+	field = SWAP_LONG(field);
 	field = (unsigned long)SET(field, val, size);
-	*(unsigned long *)ptr = SWAP_LONG(field);
+	field = SWAP_LONG(field);
+	memcpy(ptr, &field, sizeof(field));
 	_RET(value);
 }
 
@@ -789,7 +827,8 @@
 static PyObject *
 L_get(void *ptr, unsigned size)
 {
-	unsigned long val = *(unsigned long *)ptr;
+	unsigned long val;
+	memcpy(&val, ptr, sizeof(val));
 	GET_BITFIELD(val, size);
 	return PyLong_FromUnsignedLong(val);
 }
@@ -797,7 +836,8 @@
 static PyObject *
 L_get_sw(void *ptr, unsigned size)
 {
-	unsigned long val = *(unsigned long *)ptr;
+	unsigned long val;
+	memcpy(&val, ptr, sizeof(val));
 	val = SWAP_LONG(val);
 	GET_BITFIELD(val, size);
 	return PyLong_FromUnsignedLong(val);
@@ -808,9 +848,12 @@
 q_set(void *ptr, PyObject *value, unsigned size)
 {
 	PY_LONG_LONG val;
+	PY_LONG_LONG x;
 	if (get_longlong(value, &val) < 0)
 		return NULL;
-	*(PY_LONG_LONG *)ptr = (PY_LONG_LONG)SET(*(PY_LONG_LONG *)ptr, val, size);
+	memcpy(&x, ptr, sizeof(x));
+	x = SET(x, val, size);
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
@@ -821,16 +864,19 @@
 	PY_LONG_LONG field;
 	if (get_longlong(value, &val) < 0)
 		return NULL;
-	field = SWAP_8(*(PY_LONG_LONG *)ptr);
+	memcpy(&field, ptr, sizeof(field));
+	field = SWAP_8(field);
 	field = (PY_LONG_LONG)SET(field, val, size);
-	*(PY_LONG_LONG *)ptr = SWAP_8(field);
+	field = SWAP_8(field);
+	memcpy(ptr, &field, sizeof(field));
 	_RET(value);
 }
 
 static PyObject *
 q_get(void *ptr, unsigned size)
 {
-	PY_LONG_LONG val = *(PY_LONG_LONG *)ptr;
+	PY_LONG_LONG val;
+	memcpy(&val, ptr, sizeof(val));
 	GET_BITFIELD(val, size);
 	return PyLong_FromLongLong(val);
 }
@@ -838,7 +884,8 @@
 static PyObject *
 q_get_sw(void *ptr, unsigned size)
 {
-	PY_LONG_LONG val = *(PY_LONG_LONG *)ptr;
+	PY_LONG_LONG val;
+	memcpy(&val, ptr, sizeof(val));
 	val = SWAP_8(val);
 	GET_BITFIELD(val, size);
 	return PyLong_FromLongLong(val);
@@ -848,9 +895,12 @@
 Q_set(void *ptr, PyObject *value, unsigned size)
 {
 	unsigned PY_LONG_LONG val;
+	unsigned PY_LONG_LONG x;
 	if (get_ulonglong(value, &val) < 0)
 		return NULL;
-	*(unsigned PY_LONG_LONG *)ptr = (unsigned PY_LONG_LONG)SET(*(unsigned PY_LONG_LONG *)ptr, val, size);
+	memcpy(&x, ptr, sizeof(x));
+	x = SET(x, val, size);
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
@@ -861,16 +911,19 @@
 	unsigned PY_LONG_LONG field;
 	if (get_ulonglong(value, &val) < 0)
 		return NULL;
-	field = SWAP_8(*(unsigned PY_LONG_LONG *)ptr);
+	memcpy(&field, ptr, sizeof(field));
+	field = SWAP_8(field);
 	field = (unsigned PY_LONG_LONG)SET(field, val, size);
-	*(unsigned PY_LONG_LONG *)ptr = SWAP_8(field);
+	field = SWAP_8(field);
+	memcpy(ptr, &field, sizeof(field));
 	_RET(value);
 }
 
 static PyObject *
 Q_get(void *ptr, unsigned size)
 {
-	unsigned PY_LONG_LONG val = *(unsigned PY_LONG_LONG *)ptr;
+	unsigned PY_LONG_LONG val;
+	memcpy(&val, ptr, sizeof(val));
 	GET_BITFIELD(val, size);
 	return PyLong_FromUnsignedLongLong(val);
 }
@@ -878,7 +931,8 @@
 static PyObject *
 Q_get_sw(void *ptr, unsigned size)
 {
-	unsigned PY_LONG_LONG val = *(unsigned PY_LONG_LONG *)ptr;
+	unsigned PY_LONG_LONG val;
+	memcpy(&val, ptr, sizeof(val));
 	val = SWAP_8(val);
 	GET_BITFIELD(val, size);
 	return PyLong_FromUnsignedLongLong(val);
@@ -903,14 +957,16 @@
 			     value->ob_type->tp_name);
 		return NULL;
 	}
-	*(double *)ptr = x;
+	memcpy(ptr, &x, sizeof(double));
 	_RET(value);
 }
 
 static PyObject *
 d_get(void *ptr, unsigned size)
 {
-	return PyFloat_FromDouble(*(double *)ptr);
+	double val;
+	memcpy(&val, ptr, sizeof(val));
+	return PyFloat_FromDouble(val);
 }
 
 static PyObject *
@@ -957,14 +1013,16 @@
 			     value->ob_type->tp_name);
 		return NULL;
 	}
-	*(float *)ptr = x;
+	memcpy(ptr, &x, sizeof(x));
 	_RET(value);
 }
 
 static PyObject *
 f_get(void *ptr, unsigned size)
 {
-	return PyFloat_FromDouble(*(float *)ptr);
+	float val;
+	memcpy(&val, ptr, sizeof(val));
+	return PyFloat_FromDouble(val);
 }
 
 static PyObject *
@@ -1317,6 +1375,7 @@
 		if (-1 == PyUnicode_AsWideChar((PyUnicodeObject *)value,
 					       buffer, PyUnicode_GET_SIZE(value))) {
 			Py_DECREF(value);
+			Py_DECREF(keep);
 			return NULL;
 		}
 		Py_DECREF(value);
diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h
index 179dcf1..7988595 100644
--- a/Modules/_ctypes/ctypes.h
+++ b/Modules/_ctypes/ctypes.h
@@ -2,15 +2,6 @@
 
 #if (PY_VERSION_HEX < 0x02050000)
 typedef int Py_ssize_t;
-#define lenfunc inquiry
-#define readbufferproc getreadbufferproc
-#define writebufferproc getwritebufferproc
-#define segcountproc getsegcountproc
-#define charbufferproc getcharbufferproc
-#define ssizeargfunc intargfunc
-#define ssizessizeargfunc intintargfunc
-#define ssizeobjargproc intobjargproc
-#define ssizessizeobjargproc intintobjargproc
 #endif
 
 #ifndef MS_WIN32
@@ -30,8 +21,9 @@
 #define PY_LONG_LONG LONG_LONG
 #endif
 
-typedef int (*THUNK)(void);
 typedef struct tagCDataObject CDataObject;
+typedef PyObject *(* GETFUNC)(void *, unsigned size);
+typedef PyObject *(* SETFUNC)(void *, PyObject *value, unsigned size);
 
 /* A default buffer in CDataObject, which can be used for small C types.  If
 this buffer is too small, PyMem_Malloc will be called to create a larger one,
@@ -72,6 +64,16 @@
 };
 
 typedef struct {
+	ffi_closure *pcl; /* the C callable */
+	ffi_cif cif;
+	PyObject *converters;
+	PyObject *callable;
+	SETFUNC setfunc;
+	ffi_type *restype;
+	ffi_type *atypes[0];
+} ffi_info;
+
+typedef struct {
 	/* First part identical to tagCDataObject */
 	PyObject_HEAD
 	char *b_ptr;		/* pointer to memory block */
@@ -85,7 +87,7 @@
 	union value b_value;
 	/* end of tagCDataObject, additional fields follow */
 
-	THUNK thunk;
+	ffi_info *thunk;
 	PyObject *callable;
 
 	/* These two fields will override the ones in the type's stgdict if
@@ -154,17 +156,12 @@
 
 extern void init_callbacks_in_module(PyObject *m);
 
-extern THUNK AllocFunctionCallback(PyObject *callable,
-				   PyObject *converters,
-				   PyObject *restype,
-				   int stdcall);
-extern void FreeCallback(THUNK);
-
 extern PyMethodDef module_methods[];
 
-typedef PyObject *(* GETFUNC)(void *, unsigned size);
-typedef PyObject *(* SETFUNC)(void *, PyObject *value, unsigned size);
-
+extern ffi_info *AllocFunctionCallback(PyObject *callable,
+				       PyObject *converters,
+				       PyObject *restype,
+				       int stdcall);
 /* a table entry describing a predefined ctypes type */
 struct fielddesc {
 	char code;
@@ -201,7 +198,7 @@
 	Py_ssize_t size;	/* number of bytes */
 	Py_ssize_t align;	/* alignment requirements */
 	Py_ssize_t length;	/* number of fields */
-	ffi_type ffi_type;
+	ffi_type ffi_type_pointer;
 	PyObject *proto;	/* Only for Pointer/ArrayObject */
 	SETFUNC setfunc;	/* Only for simple objects */
 	GETFUNC getfunc;	/* Only for simple objects */
diff --git a/Modules/_ctypes/libffi/configure b/Modules/_ctypes/libffi/configure
index 0991b63..c1e5cd4 100755
--- a/Modules/_ctypes/libffi/configure
+++ b/Modules/_ctypes/libffi/configure
@@ -3490,6 +3490,7 @@
 i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-freebsd* | i*86-*-kfreebsd*-gnu) TARGET=X86; TARGETDIR=x86;;
 i*86-*-netbsdelf* | i*86-*-knetbsd*-gnu) TARGET=X86; TARGETDIR=x86;;
+i*86-*-openbsd*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-rtems*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-win32*) TARGET=X86_WIN32; TARGETDIR=x86;;
 i*86-*-cygwin*) TARGET=X86_WIN32; TARGETDIR=x86;;
diff --git a/Modules/_ctypes/libffi/configure.ac b/Modules/_ctypes/libffi/configure.ac
index 76bf16e..c7f05d6 100644
--- a/Modules/_ctypes/libffi/configure.ac
+++ b/Modules/_ctypes/libffi/configure.ac
@@ -28,6 +28,7 @@
 i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-freebsd* | i*86-*-kfreebsd*-gnu) TARGET=X86; TARGETDIR=x86;;
 i*86-*-netbsdelf* | i*86-*-knetbsd*-gnu) TARGET=X86; TARGETDIR=x86;;
+i*86-*-openbsd*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-rtems*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-win32*) TARGET=X86_WIN32; TARGETDIR=x86;;
 i*86-*-cygwin*) TARGET=X86_WIN32; TARGETDIR=x86;;
diff --git a/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S b/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S
index 7959838..6d9a364 100644
--- a/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S
+++ b/Modules/_ctypes/libffi/src/powerpc/darwin_closure.S
@@ -246,7 +246,7 @@
 /* END(ffi_closure_ASM)  */
 
 .data
-.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
 EH_frame1:
 	.set	L$set$0,LECIE1-LSCIE1
 	.long	L$set$0	; Length of Common Information Entry
diff --git a/Modules/_ctypes/libffi/src/x86/ffi.c b/Modules/_ctypes/libffi/src/x86/ffi.c
index e4d5fc3..7f792b7 100644
--- a/Modules/_ctypes/libffi/src/x86/ffi.c
+++ b/Modules/_ctypes/libffi/src/x86/ffi.c
@@ -121,7 +121,7 @@
   switch (cif->rtype->type)
     {
     case FFI_TYPE_VOID:
-#ifndef X86_WIN32
+#if !defined(X86_WIN32) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
     case FFI_TYPE_STRUCT:
 #endif
     case FFI_TYPE_SINT64:
@@ -135,7 +135,7 @@
       cif->flags = FFI_TYPE_SINT64;
       break;
 
-#ifdef X86_WIN32
+#if defined(X86_WIN32) || defined(__OpenBSD__) || defined(__FreeBSD__)
     case FFI_TYPE_STRUCT:
       if (cif->rtype->size == 1)
         {
diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c
index cb3d599..336be37 100644
--- a/Modules/_ctypes/stgdict.c
+++ b/Modules/_ctypes/stgdict.c
@@ -38,7 +38,7 @@
 StgDict_dealloc(StgDictObject *self)
 {
 	StgDict_clear(self);
-	PyMem_Free(self->ffi_type.elements);
+	PyMem_Free(self->ffi_type_pointer.elements);
 	PyDict_Type.tp_dealloc((PyObject *)self);
 }
 
@@ -49,8 +49,8 @@
 	int size;
 
 	StgDict_clear(dst);
-	PyMem_Free(dst->ffi_type.elements);
-	dst->ffi_type.elements = NULL;
+	PyMem_Free(dst->ffi_type_pointer.elements);
+	dst->ffi_type_pointer.elements = NULL;
 
 	d = (char *)dst;
 	s = (char *)src;
@@ -64,13 +64,15 @@
 	Py_XINCREF(dst->restype);
 	Py_XINCREF(dst->checker);
 
-	if (src->ffi_type.elements == NULL)
+	if (src->ffi_type_pointer.elements == NULL)
 		return 0;
 	size = sizeof(ffi_type *) * (src->length + 1);
-	dst->ffi_type.elements = PyMem_Malloc(size);
-	if (dst->ffi_type.elements == NULL)
+	dst->ffi_type_pointer.elements = PyMem_Malloc(size);
+	if (dst->ffi_type_pointer.elements == NULL)
 		return -1;
-	memcpy(dst->ffi_type.elements, src->ffi_type.elements, size);
+	memcpy(dst->ffi_type_pointer.elements,
+	       src->ffi_type_pointer.elements,
+	       size);
 	return 0;
 }
 
@@ -234,8 +236,8 @@
 	   stuff is sucessfully finished. */
 	stgdict->flags |= DICTFLAG_FINAL;	/* set final */
 
-	if (stgdict->ffi_type.elements)
-		PyMem_Free(stgdict->ffi_type.elements);
+	if (stgdict->ffi_type_pointer.elements)
+		PyMem_Free(stgdict->ffi_type_pointer.elements);
 
 	basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
 	if (basedict && !use_broken_old_ctypes_semantics) {
@@ -243,10 +245,12 @@
 		align = basedict->align;
 		union_size = 0;
 		total_align = align ? align : 1;
-		stgdict->ffi_type.type = FFI_TYPE_STRUCT;
-		stgdict->ffi_type.elements = PyMem_Malloc(sizeof(ffi_type *) * (basedict->length + len + 1));
-		memset(stgdict->ffi_type.elements, 0, sizeof(ffi_type *) * (basedict->length + len + 1));
-		memcpy(stgdict->ffi_type.elements, basedict->ffi_type.elements,
+		stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
+		stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (basedict->length + len + 1));
+		memset(stgdict->ffi_type_pointer.elements, 0,
+		       sizeof(ffi_type *) * (basedict->length + len + 1));
+		memcpy(stgdict->ffi_type_pointer.elements,
+		       basedict->ffi_type_pointer.elements,
 		       sizeof(ffi_type *) * (basedict->length));
 		ffi_ofs = basedict->length;
 	} else {
@@ -255,9 +259,10 @@
 		align = 0;
 		union_size = 0;
 		total_align = 1;
-		stgdict->ffi_type.type = FFI_TYPE_STRUCT;
-		stgdict->ffi_type.elements = PyMem_Malloc(sizeof(ffi_type *) * (len + 1));
-		memset(stgdict->ffi_type.elements, 0, sizeof(ffi_type *) * (len + 1));
+		stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
+		stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (len + 1));
+		memset(stgdict->ffi_type_pointer.elements, 0,
+		       sizeof(ffi_type *) * (len + 1));
 		ffi_ofs = 0;
 	}
 
@@ -283,10 +288,10 @@
 				     i);
 			return -1;
 		}
-		stgdict->ffi_type.elements[ffi_ofs + i] = &dict->ffi_type;
+		stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
 		dict->flags |= DICTFLAG_FINAL; /* mark field type final */
 		if (PyTuple_Size(pair) == 3) { /* bits specified */
-			switch(dict->ffi_type.type) {
+			switch(dict->ffi_type_pointer.type) {
 			case FFI_TYPE_UINT8:
 			case FFI_TYPE_UINT16:
 			case FFI_TYPE_UINT32:
@@ -357,8 +362,8 @@
 	/* Adjust the size according to the alignment requirements */
 	size = ((size + total_align - 1) / total_align) * total_align;
 
-	stgdict->ffi_type.alignment = total_align;
-	stgdict->ffi_type.size = size;
+	stgdict->ffi_type_pointer.alignment = total_align;
+	stgdict->ffi_type_pointer.size = size;
 
 	stgdict->size = size;
 	stgdict->align = total_align;
diff --git a/Modules/_hotshot.c b/Modules/_hotshot.c
index d5b4cde..2ee4eb9 100644
--- a/Modules/_hotshot.c
+++ b/Modules/_hotshot.c
@@ -26,7 +26,7 @@
 #ifndef HAVE_GETTIMEOFDAY
 #error "This module requires gettimeofday() on non-Windows platforms!"
 #endif
-#if (defined(PYOS_OS2) && defined(PYCC_GCC))
+#if (defined(PYOS_OS2) && defined(PYCC_GCC)) || defined(__QNX__)
 #include <sys/time.h>
 #else
 #include <sys/resource.h>
@@ -308,7 +308,7 @@
     if ((err = unpack_packed_int(self, &len, 0)))
         return err;
 
-    buf = malloc(len);
+    buf = (char *)malloc(len);
     for (i=0; i < len; i++) {
         ch = fgetc(self->logfp);
 	buf[i] = ch;
@@ -918,7 +918,7 @@
 #endif
     }
 #if defined(MS_WINDOWS) || defined(PYOS_OS2) || \
-    defined(__VMS)
+    defined(__VMS) || defined (__QNX__)
     rusage_diff = -1;
 #else
     {
@@ -1403,7 +1403,7 @@
         ++rev;
     while (rev[i] != ' ' && rev[i] != '\0')
         ++i;
-    buffer = malloc(i + 1);
+    buffer = (char *)malloc(i + 1);
     if (buffer != NULL) {
         memmove(buffer, rev, i);
         buffer[i] = '\0';
diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c
index 17c71e9..d665f83 100644
--- a/Modules/_lsprof.c
+++ b/Modules/_lsprof.c
@@ -515,6 +515,7 @@
 	5
 };
 
+static int initialized;
 static PyTypeObject StatsEntryType;
 static PyTypeObject StatsSubEntryType;
 
@@ -857,8 +858,12 @@
 		return;
 	PyDict_SetItemString(d, "Profiler", (PyObject *)&PyProfiler_Type);
 
-	PyStructSequence_InitType(&StatsEntryType, &profiler_entry_desc);
-	PyStructSequence_InitType(&StatsSubEntryType, &profiler_subentry_desc);
+	if (!initialized) {
+		PyStructSequence_InitType(&StatsEntryType, 
+					  &profiler_entry_desc);
+		PyStructSequence_InitType(&StatsSubEntryType, 
+					  &profiler_subentry_desc);
+	}
 	Py_INCREF((PyObject*) &StatsEntryType);
 	Py_INCREF((PyObject*) &StatsSubEntryType);
 	PyModule_AddObject(module, "profiler_entry",
@@ -866,4 +871,5 @@
 	PyModule_AddObject(module, "profiler_subentry",
 			   (PyObject*) &StatsSubEntryType);
 	empty_tuple = PyTuple_New(0);
+	initialized = 1;
 }
diff --git a/Modules/_sqlite/adapters.c b/Modules/_sqlite/adapters.c
new file mode 100644
index 0000000..e6fde03
--- /dev/null
+++ b/Modules/_sqlite/adapters.c
@@ -0,0 +1,40 @@
+/* adapters.c - default adapters
+ *
+ * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "util.h"
+#include "module.h"
+#include "adapters.h"
+
+/* dummy, will be implemented in a later version */
+
+PyObject* adapt_date(PyObject* self, PyObject* args, PyObject* kwargs)
+{
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject* adapt_datetime(PyObject* self, PyObject* args, PyObject* kwargs)
+{
+    Py_INCREF(Py_None);
+    return Py_None;
+}
diff --git a/Modules/_sqlite/adapters.h b/Modules/_sqlite/adapters.h
new file mode 100644
index 0000000..d2e8479
--- /dev/null
+++ b/Modules/_sqlite/adapters.h
@@ -0,0 +1,33 @@
+/* adapters.h - default adapters
+ *
+ * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_ADAPTERS_H
+#define PYSQLITE_ADAPTERS_H
+#include "Python.h"
+#include "pythread.h"
+#include "sqlite3.h"
+
+PyObject* adapt_date(PyObject* self, PyObject* args, PyObject* kwargs);
+PyObject* adapt_datetime(PyObject* self, PyObject* args, PyObject* kwargs);
+
+#endif
diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c
new file mode 100644
index 0000000..d102e97
--- /dev/null
+++ b/Modules/_sqlite/cache.c
@@ -0,0 +1,362 @@
+/* cache .c - a LRU cache
+ *
+ * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "cache.h"
+
+/* only used internally */
+Node* new_node(PyObject* key, PyObject* data)
+{
+    Node* node;
+
+    node = (Node*) (NodeType.tp_alloc(&NodeType, 0));
+    if (!node) {
+        return NULL;
+    }
+
+    Py_INCREF(key);
+    node->key = key;
+
+    Py_INCREF(data);
+    node->data = data;
+
+    node->prev = NULL;
+    node->next = NULL;
+
+    return node;
+}
+
+void node_dealloc(Node* self)
+{
+    Py_DECREF(self->key);
+    Py_DECREF(self->data);
+
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+int cache_init(Cache* self, PyObject* args, PyObject* kwargs)
+{
+    PyObject* factory;
+    int size = 10;
+
+    self->factory = NULL;
+
+    if (!PyArg_ParseTuple(args, "O|i", &factory, &size))
+    {
+        return -1; 
+    }
+
+    if (size < 5) {
+        size = 5;
+    }
+    self->size = size;
+    self->first = NULL;
+    self->last = NULL;
+
+    self->mapping = PyDict_New();
+    if (!self->mapping) {
+        return -1;
+    }
+
+    Py_INCREF(factory);
+    self->factory = factory;
+
+    self->decref_factory = 1;
+
+    return 0;
+}
+
+void cache_dealloc(Cache* self)
+{
+    Node* node;
+    Node* delete_node;
+
+    if (!self->factory) {
+        /* constructor failed, just get out of here */
+        return;
+    }
+
+    node = self->first;
+    while (node) {
+        delete_node = node;
+        node = node->next;
+        Py_DECREF(delete_node);
+    }
+
+    if (self->decref_factory) {
+        Py_DECREF(self->factory);
+    }
+    Py_DECREF(self->mapping);
+
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject* cache_get(Cache* self, PyObject* args)
+{
+    PyObject* key = args;
+    Node* node;
+    Node* ptr;
+    PyObject* data;
+
+    node = (Node*)PyDict_GetItem(self->mapping, key);
+    if (node) {
+        node->count++;
+        if (node->prev && node->count > node->prev->count) {
+            ptr = node->prev;
+
+            while (ptr->prev && node->count > ptr->prev->count) {
+                ptr = ptr->prev;
+            }
+
+            if (node->next) {
+                node->next->prev = node->prev;
+            } else {
+                self->last = node->prev;
+            }
+            if (node->prev) {
+                node->prev->next = node->next;
+            }
+            if (ptr->prev) {
+                ptr->prev->next = node;
+            } else {
+                self->first = node;
+            }
+
+            node->next = ptr;
+            node->prev = ptr->prev;
+            if (!node->prev) {
+                self->first = node;
+            }
+            ptr->prev = node;
+        }
+    } else {
+        if (PyDict_Size(self->mapping) == self->size) {
+            if (self->last) {
+                node = self->last;
+
+                if (PyDict_DelItem(self->mapping, self->last->key) != 0) {
+                    return NULL;
+                }
+
+                if (node->prev) {
+                    node->prev->next = NULL;
+                }
+                self->last = node->prev;
+                node->prev = NULL;
+
+                Py_DECREF(node);
+            }
+        }
+
+        data = PyObject_CallFunction(self->factory, "O", key);
+
+        if (!data) {
+            return NULL;
+        }
+
+        node = new_node(key, data);
+        if (!node) {
+            return NULL;
+        }
+        node->prev = self->last;
+
+        Py_DECREF(data);
+
+        if (PyDict_SetItem(self->mapping, key, (PyObject*)node) != 0) {
+            Py_DECREF(node);
+            return NULL;
+        }
+
+        if (self->last) {
+            self->last->next = node;
+        } else {
+            self->first = node;
+        }
+        self->last = node;
+    }
+
+    Py_INCREF(node->data);
+    return node->data;
+}
+
+PyObject* cache_display(Cache* self, PyObject* args)
+{
+    Node* ptr;
+    PyObject* prevkey;
+    PyObject* nextkey;
+    PyObject* fmt_args;
+    PyObject* template;
+    PyObject* display_str;
+
+    ptr = self->first;
+
+    while (ptr) {
+        if (ptr->prev) {
+            prevkey = ptr->prev->key;
+        } else {
+            prevkey = Py_None;
+        }
+        Py_INCREF(prevkey);
+
+        if (ptr->next) {
+            nextkey = ptr->next->key;
+        } else {
+            nextkey = Py_None;
+        }
+        Py_INCREF(nextkey);
+
+        fmt_args = Py_BuildValue("OOO", prevkey, ptr->key, nextkey);
+        if (!fmt_args) {
+            return NULL;
+        }
+        template = PyString_FromString("%s <- %s ->%s\n");
+        if (!template) {
+            return NULL;
+        }
+        display_str = PyString_Format(template, fmt_args);
+        Py_DECREF(template);
+        Py_DECREF(fmt_args);
+        if (!display_str) {
+            return NULL;
+        }
+        PyObject_Print(display_str, stdout, Py_PRINT_RAW);
+        Py_DECREF(display_str);
+
+        Py_DECREF(prevkey);
+        Py_DECREF(nextkey);
+
+        ptr = ptr->next;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef cache_methods[] = {
+    {"get", (PyCFunction)cache_get, METH_O,
+        PyDoc_STR("Gets an entry from the cache.")},
+    {"display", (PyCFunction)cache_display, METH_NOARGS,
+        PyDoc_STR("For debugging only.")},
+    {NULL, NULL}
+};
+
+PyTypeObject NodeType = {
+        PyObject_HEAD_INIT(NULL)
+        0,                                              /* ob_size */
+        MODULE_NAME "Node",                             /* tp_name */
+        sizeof(Node),                                   /* tp_basicsize */
+        0,                                              /* tp_itemsize */
+        (destructor)node_dealloc,                       /* tp_dealloc */
+        0,                                              /* tp_print */
+        0,                                              /* tp_getattr */
+        0,                                              /* tp_setattr */
+        0,                                              /* tp_compare */
+        0,                                              /* tp_repr */
+        0,                                              /* tp_as_number */
+        0,                                              /* tp_as_sequence */
+        0,                                              /* tp_as_mapping */
+        0,                                              /* tp_hash */
+        0,                                              /* tp_call */
+        0,                                              /* tp_str */
+        0,                                              /* tp_getattro */
+        0,                                              /* tp_setattro */
+        0,                                              /* tp_as_buffer */
+        Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,         /* tp_flags */
+        0,                                              /* tp_doc */
+        0,                                              /* tp_traverse */
+        0,                                              /* tp_clear */
+        0,                                              /* tp_richcompare */
+        0,                                              /* tp_weaklistoffset */
+        0,                                              /* tp_iter */
+        0,                                              /* tp_iternext */
+        0,                                              /* tp_methods */
+        0,                                              /* tp_members */
+        0,                                              /* tp_getset */
+        0,                                              /* tp_base */
+        0,                                              /* tp_dict */
+        0,                                              /* tp_descr_get */
+        0,                                              /* tp_descr_set */
+        0,                                              /* tp_dictoffset */
+        (initproc)0,                                    /* tp_init */
+        0,                                              /* tp_alloc */
+        0,                                              /* tp_new */
+        0                                               /* tp_free */
+};
+
+PyTypeObject CacheType = {
+        PyObject_HEAD_INIT(NULL)
+        0,                                              /* ob_size */
+        MODULE_NAME ".Cache",                           /* tp_name */
+        sizeof(Cache),                                  /* tp_basicsize */
+        0,                                              /* tp_itemsize */
+        (destructor)cache_dealloc,                      /* tp_dealloc */
+        0,                                              /* tp_print */
+        0,                                              /* tp_getattr */
+        0,                                              /* tp_setattr */
+        0,                                              /* tp_compare */
+        0,                                              /* tp_repr */
+        0,                                              /* tp_as_number */
+        0,                                              /* tp_as_sequence */
+        0,                                              /* tp_as_mapping */
+        0,                                              /* tp_hash */
+        0,                                              /* tp_call */
+        0,                                              /* tp_str */
+        0,                                              /* tp_getattro */
+        0,                                              /* tp_setattro */
+        0,                                              /* tp_as_buffer */
+        Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,         /* tp_flags */
+        0,                                              /* tp_doc */
+        0,                                              /* tp_traverse */
+        0,                                              /* tp_clear */
+        0,                                              /* tp_richcompare */
+        0,                                              /* tp_weaklistoffset */
+        0,                                              /* tp_iter */
+        0,                                              /* tp_iternext */
+        cache_methods,                                  /* tp_methods */
+        0,                                              /* tp_members */
+        0,                                              /* tp_getset */
+        0,                                              /* tp_base */
+        0,                                              /* tp_dict */
+        0,                                              /* tp_descr_get */
+        0,                                              /* tp_descr_set */
+        0,                                              /* tp_dictoffset */
+        (initproc)cache_init,                           /* tp_init */
+        0,                                              /* tp_alloc */
+        0,                                              /* tp_new */
+        0                                               /* tp_free */
+};
+
+extern int cache_setup_types(void)
+{
+    int rc;
+
+    NodeType.tp_new = PyType_GenericNew;
+    CacheType.tp_new = PyType_GenericNew;
+
+    rc = PyType_Ready(&NodeType);
+    if (rc < 0) {
+        return rc;
+    }
+
+    rc = PyType_Ready(&CacheType);
+    return rc;
+}
diff --git a/Modules/_sqlite/cache.h b/Modules/_sqlite/cache.h
new file mode 100644
index 0000000..5cc16f3
--- /dev/null
+++ b/Modules/_sqlite/cache.h
@@ -0,0 +1,61 @@
+/* cache.h - definitions for the LRU cache
+ *
+ * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_CACHE_H
+#define PYSQLITE_CACHE_H
+#include "Python.h"
+
+typedef struct _Node
+{
+    PyObject_HEAD
+    PyObject* key;
+    PyObject* data;
+    long count;
+    struct _Node* prev;
+    struct _Node* next;
+} Node;
+
+typedef struct
+{
+    PyObject_HEAD
+    int size;
+    PyObject* mapping;
+    PyObject* factory;
+    Node* first;
+    Node* last;
+    int decref_factory;
+} Cache;
+
+extern PyTypeObject NodeType;
+extern PyTypeObject CacheType;
+
+int node_init(Node* self, PyObject* args, PyObject* kwargs);
+void node_dealloc(Node* self);
+
+int cache_init(Cache* self, PyObject* args, PyObject* kwargs);
+void cache_dealloc(Cache* self);
+PyObject* cache_get(Cache* self, PyObject* args);
+
+int cache_setup_types(void);
+
+#endif
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
new file mode 100644
index 0000000..78aad37
--- /dev/null
+++ b/Modules/_sqlite/connection.c
@@ -0,0 +1,1082 @@
+/* connection.c - the connection type
+ *
+ * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ * 
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "cache.h"
+#include "module.h"
+#include "connection.h"
+#include "statement.h"
+#include "cursor.h"
+#include "prepare_protocol.h"
+#include "util.h"
+#include "sqlitecompat.h"
+
+#include "pythread.h"
+
+static int connection_set_isolation_level(Connection* self, PyObject* isolation_level);
+
+int connection_init(Connection* self, PyObject* args, PyObject* kwargs)
+{
+    static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL};
+
+    char* database;
+    int detect_types = 0;
+    PyObject* isolation_level = NULL;
+    PyObject* factory = NULL;
+    int check_same_thread = 1;
+    int cached_statements = 100;
+    double timeout = 5.0;
+    int rc;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOi", kwlist,
+                                     &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements))
+    {
+        return -1; 
+    }
+
+    self->begin_statement = NULL;
+
+    self->statement_cache = NULL;
+
+    Py_INCREF(Py_None);
+    self->row_factory = Py_None;
+
+    Py_INCREF(&PyUnicode_Type);
+    self->text_factory = (PyObject*)&PyUnicode_Type;
+
+    Py_BEGIN_ALLOW_THREADS
+    rc = sqlite3_open(database, &self->db);
+    Py_END_ALLOW_THREADS
+
+    if (rc != SQLITE_OK) {
+        _seterror(self->db);
+        return -1;
+    }
+
+    if (!isolation_level) {
+        isolation_level = PyString_FromString("");
+    } else {
+        Py_INCREF(isolation_level);
+    }
+    self->isolation_level = NULL;
+    connection_set_isolation_level(self, isolation_level);
+    Py_DECREF(isolation_level);
+
+    self->statement_cache = (Cache*)PyObject_CallFunction((PyObject*)&CacheType, "Oi", self, cached_statements);
+    if (PyErr_Occurred()) {
+        return -1;
+    }
+
+    /* By default, the Cache class INCREFs the factory in its initializer, and
+     * decrefs it in its deallocator method. Since this would create a circular
+     * reference here, we're breaking it by decrementing self, and telling the
+     * cache class to not decref the factory (self) in its deallocator.
+     */
+    self->statement_cache->decref_factory = 0;
+    Py_DECREF(self);
+
+    self->inTransaction = 0;
+    self->detect_types = detect_types;
+    self->timeout = timeout;
+    (void)sqlite3_busy_timeout(self->db, (int)(timeout*1000));
+
+    self->thread_ident = PyThread_get_thread_ident();
+    self->check_same_thread = check_same_thread;
+
+    self->function_pinboard = PyDict_New();
+    if (!self->function_pinboard) {
+        return -1;
+    }
+
+    self->collations = PyDict_New();
+    if (!self->collations) {
+        return -1;
+    }
+
+    self->Warning = Warning;
+    self->Error = Error;
+    self->InterfaceError = InterfaceError;
+    self->DatabaseError = DatabaseError;
+    self->DataError = DataError;
+    self->OperationalError = OperationalError;
+    self->IntegrityError = IntegrityError;
+    self->InternalError = InternalError;
+    self->ProgrammingError = ProgrammingError;
+    self->NotSupportedError = NotSupportedError;
+
+    return 0;
+}
+
+void flush_statement_cache(Connection* self)
+{
+    Node* node;
+    Statement* statement;
+
+    node = self->statement_cache->first;
+
+    while (node) {
+        statement = (Statement*)(node->data);
+        (void)statement_finalize(statement);
+        node = node->next;
+    }
+
+    Py_DECREF(self->statement_cache);
+    self->statement_cache = (Cache*)PyObject_CallFunction((PyObject*)&CacheType, "O", self);
+    Py_DECREF(self);
+    self->statement_cache->decref_factory = 0;
+}
+
+void reset_all_statements(Connection* self)
+{
+    Node* node;
+    Statement* statement;
+
+    node = self->statement_cache->first;
+
+    while (node) {
+        statement = (Statement*)(node->data);
+        (void)statement_reset(statement);
+        node = node->next;
+    }
+}
+
+void connection_dealloc(Connection* self)
+{
+    Py_XDECREF(self->statement_cache);
+
+    /* Clean up if user has not called .close() explicitly. */
+    if (self->db) {
+        Py_BEGIN_ALLOW_THREADS
+        sqlite3_close(self->db);
+        Py_END_ALLOW_THREADS
+    }
+
+    if (self->begin_statement) {
+        PyMem_Free(self->begin_statement);
+    }
+    Py_XDECREF(self->isolation_level);
+    Py_XDECREF(self->function_pinboard);
+    Py_XDECREF(self->row_factory);
+    Py_XDECREF(self->text_factory);
+    Py_XDECREF(self->collations);
+
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+PyObject* connection_cursor(Connection* self, PyObject* args, PyObject* kwargs)
+{
+    static char *kwlist[] = {"factory", NULL, NULL};
+    PyObject* factory = NULL;
+    PyObject* cursor;
+
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
+                                     &factory)) {
+        return NULL;
+    }
+
+    if (!check_thread(self) || !check_connection(self)) {
+        return NULL;
+    }
+
+    if (factory == NULL) {
+        factory = (PyObject*)&CursorType;
+    }
+
+    cursor = PyObject_CallFunction(factory, "O", self);
+
+    if (cursor && self->row_factory != Py_None) {
+        Py_XDECREF(((Cursor*)cursor)->row_factory);
+        Py_INCREF(self->row_factory);
+        ((Cursor*)cursor)->row_factory = self->row_factory;
+    }
+
+    return cursor;
+}
+
+PyObject* connection_close(Connection* self, PyObject* args)
+{
+    int rc;
+
+    if (!check_thread(self)) {
+        return NULL;
+    }
+
+    flush_statement_cache(self);
+
+    if (self->db) {
+        Py_BEGIN_ALLOW_THREADS
+        rc = sqlite3_close(self->db);
+        Py_END_ALLOW_THREADS
+
+        if (rc != SQLITE_OK) {
+            _seterror(self->db);
+            return NULL;
+        } else {
+            self->db = NULL;
+        }
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+/*
+ * Checks if a connection object is usable (i. e. not closed).
+ *
+ * 0 => error; 1 => ok
+ */
+int check_connection(Connection* con)
+{
+    if (!con->db) {
+        PyErr_SetString(ProgrammingError, "Cannot operate on a closed database.");
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
+PyObject* _connection_begin(Connection* self)
+{
+    int rc;
+    const char* tail;
+    sqlite3_stmt* statement;
+
+    Py_BEGIN_ALLOW_THREADS
+    rc = sqlite3_prepare(self->db, self->begin_statement, -1, &statement, &tail);
+    Py_END_ALLOW_THREADS
+
+    if (rc != SQLITE_OK) {
+        _seterror(self->db);
+        goto error;
+    }
+
+    rc = _sqlite_step_with_busyhandler(statement, self);
+    if (rc == SQLITE_DONE) {
+        self->inTransaction = 1;
+    } else {
+        _seterror(self->db);
+    }
+
+    Py_BEGIN_ALLOW_THREADS
+    rc = sqlite3_finalize(statement);
+    Py_END_ALLOW_THREADS
+
+    if (rc != SQLITE_OK && !PyErr_Occurred()) {
+        _seterror(self->db);
+    }
+
+error:
+    if (PyErr_Occurred()) {
+        return NULL;
+    } else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+}
+
+PyObject* connection_commit(Connection* self, PyObject* args)
+{
+    int rc;
+    const char* tail;
+    sqlite3_stmt* statement;
+
+    if (!check_thread(self) || !check_connection(self)) {
+        return NULL;
+    }
+
+    if (self->inTransaction) {
+        Py_BEGIN_ALLOW_THREADS
+        rc = sqlite3_prepare(self->db, "COMMIT", -1, &statement, &tail);
+        Py_END_ALLOW_THREADS
+        if (rc != SQLITE_OK) {
+            _seterror(self->db);
+            goto error;
+        }
+
+        rc = _sqlite_step_with_busyhandler(statement, self);
+        if (rc == SQLITE_DONE) {
+            self->inTransaction = 0;
+        } else {
+            _seterror(self->db);
+        }
+
+        Py_BEGIN_ALLOW_THREADS
+        rc = sqlite3_finalize(statement);
+        Py_END_ALLOW_THREADS
+        if (rc != SQLITE_OK && !PyErr_Occurred()) {
+            _seterror(self->db);
+        }
+
+    }
+
+error:
+    if (PyErr_Occurred()) {
+        return NULL;
+    } else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+}
+
+PyObject* connection_rollback(Connection* self, PyObject* args)
+{
+    int rc;
+    const char* tail;
+    sqlite3_stmt* statement;
+
+    if (!check_thread(self) || !check_connection(self)) {
+        return NULL;
+    }
+
+    if (self->inTransaction) {
+        reset_all_statements(self);
+
+        Py_BEGIN_ALLOW_THREADS
+        rc = sqlite3_prepare(self->db, "ROLLBACK", -1, &statement, &tail);
+        Py_END_ALLOW_THREADS
+        if (rc != SQLITE_OK) {
+            _seterror(self->db);
+            goto error;
+        }
+
+        rc = _sqlite_step_with_busyhandler(statement, self);
+        if (rc == SQLITE_DONE) {
+            self->inTransaction = 0;
+        } else {
+            _seterror(self->db);
+        }
+
+        Py_BEGIN_ALLOW_THREADS
+        rc = sqlite3_finalize(statement);
+        Py_END_ALLOW_THREADS
+        if (rc != SQLITE_OK && !PyErr_Occurred()) {
+            _seterror(self->db);
+        }
+
+    }
+
+error:
+    if (PyErr_Occurred()) {
+        return NULL;
+    } else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+}
+
+void _set_result(sqlite3_context* context, PyObject* py_val)
+{
+    long longval;
+    const char* buffer;
+    Py_ssize_t buflen;
+    PyObject* stringval;
+
+    if (PyErr_Occurred()) {
+        /* Errors in callbacks are ignored, and we return NULL */
+        PyErr_Clear();
+        sqlite3_result_null(context);
+    } else if (py_val == Py_None) {
+        sqlite3_result_null(context);
+    } else if (PyInt_Check(py_val)) {
+        longval = PyInt_AsLong(py_val);
+        /* TODO: investigate what to do with range overflows - long vs. long long */
+        sqlite3_result_int64(context, (PY_LONG_LONG)longval);
+    } else if (PyFloat_Check(py_val)) {
+        sqlite3_result_double(context, PyFloat_AsDouble(py_val));
+    } else if (PyBuffer_Check(py_val)) {
+        if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) {
+            PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
+        }
+        sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT);
+    } else if (PyString_Check(py_val)) {
+        sqlite3_result_text(context, PyString_AsString(py_val), -1, SQLITE_TRANSIENT);
+    } else if (PyUnicode_Check(py_val)) {
+        stringval = PyUnicode_AsUTF8String(py_val);
+        sqlite3_result_text(context, PyString_AsString(stringval), -1, SQLITE_TRANSIENT);
+        Py_DECREF(stringval);
+    } else {
+        /* TODO: raise error */
+    }
+}
+
+PyObject* _build_py_params(sqlite3_context *context, int argc, sqlite3_value** argv)
+{
+    PyObject* args;
+    int i;
+    sqlite3_value* cur_value;
+    PyObject* cur_py_value;
+    const char* val_str;
+    PY_LONG_LONG val_int;
+    Py_ssize_t buflen;
+    void* raw_buffer;
+
+    args = PyTuple_New(argc);
+    if (!args) {
+        return NULL;
+    }
+
+    for (i = 0; i < argc; i++) {
+        cur_value = argv[i];
+        switch (sqlite3_value_type(argv[i])) {
+            case SQLITE_INTEGER:
+                val_int = sqlite3_value_int64(cur_value);
+                cur_py_value = PyInt_FromLong((long)val_int);
+                break;
+            case SQLITE_FLOAT:
+                cur_py_value = PyFloat_FromDouble(sqlite3_value_double(cur_value));
+                break;
+            case SQLITE_TEXT:
+                val_str = (const char*)sqlite3_value_text(cur_value);
+                cur_py_value = PyUnicode_DecodeUTF8(val_str, strlen(val_str), NULL);
+                /* TODO: have a way to show errors here */
+                if (!cur_py_value) {
+                    Py_INCREF(Py_None);
+                    cur_py_value = Py_None;
+                }
+                break;
+            case SQLITE_BLOB:
+                buflen = sqlite3_value_bytes(cur_value);
+                cur_py_value = PyBuffer_New(buflen);
+                if (!cur_py_value) {
+                    /* TODO: error */
+                }
+                if (PyObject_AsWriteBuffer(cur_py_value, &raw_buffer, &buflen)) {
+                    /* TODO: error */
+                }
+                memcpy(raw_buffer, sqlite3_value_blob(cur_value), buflen);
+                break;
+            case SQLITE_NULL:
+            default:
+                Py_INCREF(Py_None);
+                cur_py_value = Py_None;
+        }
+        PyTuple_SetItem(args, i, cur_py_value);
+
+    }
+
+    return args;
+}
+
+void _func_callback(sqlite3_context* context, int argc, sqlite3_value** argv)
+{
+    PyObject* args;
+    PyObject* py_func;
+    PyObject* py_retval;
+
+
+    PyGILState_STATE threadstate;
+
+    threadstate = PyGILState_Ensure();
+
+    py_func = (PyObject*)sqlite3_user_data(context);
+
+    args = _build_py_params(context, argc, argv);
+
+    py_retval = PyObject_CallObject(py_func, args);
+    Py_DECREF(args);
+
+    _set_result(context, py_retval);
+    Py_XDECREF(py_retval);
+
+    PyGILState_Release(threadstate);
+}
+
+static void _step_callback(sqlite3_context *context, int argc, sqlite3_value** params)
+{
+    PyObject* args;
+    PyObject* function_result;
+    PyObject* aggregate_class;
+    PyObject** aggregate_instance;
+    PyObject* stepmethod;
+
+    PyGILState_STATE threadstate;
+
+    threadstate = PyGILState_Ensure();
+
+    aggregate_class = (PyObject*)sqlite3_user_data(context);
+
+    aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*));
+
+    if (*aggregate_instance == 0) {
+        *aggregate_instance = PyObject_CallFunction(aggregate_class, "");
+
+        if (PyErr_Occurred())
+        {
+            PyErr_Clear();
+            *aggregate_instance = 0;
+            PyGILState_Release(threadstate);
+            return;
+        }
+    }
+
+    stepmethod = PyObject_GetAttrString(*aggregate_instance, "step");
+    if (!stepmethod)
+    {
+        PyGILState_Release(threadstate);
+        return;
+    }
+
+    args = _build_py_params(context, argc, params);
+
+    function_result = PyObject_CallObject(stepmethod, args);
+    Py_DECREF(args);
+    Py_DECREF(stepmethod);
+
+    if (function_result == NULL) {
+        PyErr_Clear();
+    } else {
+        Py_DECREF(function_result);
+    }
+
+    PyGILState_Release(threadstate);
+}
+
+void _final_callback(sqlite3_context* context)
+{
+    PyObject* args;
+    PyObject* function_result;
+    PyObject** aggregate_instance;
+    PyObject* aggregate_class;
+    PyObject* finalizemethod;
+
+    PyGILState_STATE threadstate;
+
+    threadstate = PyGILState_Ensure();
+
+    aggregate_class = (PyObject*)sqlite3_user_data(context);
+
+    aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*));
+    if (!*aggregate_instance) {
+        /* this branch is executed if there was an exception in the aggregate's
+         * __init__ */
+
+        PyGILState_Release(threadstate);
+        return;
+    }
+
+    finalizemethod = PyObject_GetAttrString(*aggregate_instance, "finalize");
+
+    if (!finalizemethod) {
+        /*
+        PyErr_SetString(ProgrammingError, "finalize method missing");
+        goto error;
+        */
+        Py_INCREF(Py_None);
+        function_result = Py_None;
+    } else {
+        args = PyTuple_New(0);
+        if (!args)
+                return;
+        function_result = PyObject_CallObject(finalizemethod, args);
+        Py_DECREF(args);
+        Py_DECREF(finalizemethod);
+    }
+
+    _set_result(context, function_result);
+    Py_XDECREF(*aggregate_instance);
+    Py_XDECREF(function_result);
+
+    PyGILState_Release(threadstate);
+}
+
+
+PyObject* connection_create_function(Connection* self, PyObject* args, PyObject* kwargs)
+{
+    static char *kwlist[] = {"name", "narg", "func", NULL, NULL};
+
+    PyObject* func;
+    char* name;
+    int narg;
+    int rc;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO", kwlist,
+                                     &name, &narg, &func))
+    {
+        return NULL;
+    }
+
+    rc = sqlite3_create_function(self->db, name, narg, SQLITE_UTF8, (void*)func, _func_callback, NULL, NULL);
+
+    PyDict_SetItem(self->function_pinboard, func, Py_None);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject* connection_create_aggregate(Connection* self, PyObject* args, PyObject* kwargs)
+{
+    PyObject* aggregate_class;
+
+    int n_arg;
+    char* name;
+    static char *kwlist[] = { "name", "n_arg", "aggregate_class", NULL };
+    int rc;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO:create_aggregate",
+                                      kwlist, &name, &n_arg, &aggregate_class)) {
+        return NULL;
+    }
+
+    rc = sqlite3_create_function(self->db, name, n_arg, SQLITE_UTF8, (void*)aggregate_class, 0, &_step_callback, &_final_callback);
+    if (rc != SQLITE_OK) {
+        _seterror(self->db);
+        return NULL;
+    } else {
+        PyDict_SetItem(self->function_pinboard, aggregate_class, Py_None);
+
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+}
+
+int check_thread(Connection* self)
+{
+    if (self->check_same_thread) {
+        if (PyThread_get_thread_ident() != self->thread_ident) {
+            PyErr_Format(ProgrammingError,
+                        "SQLite objects created in a thread can only be used in that same thread."
+                        "The object was created in thread id %ld and this is thread id %ld",
+                        self->thread_ident, PyThread_get_thread_ident());
+            return 0;
+        }
+
+    }
+
+    return 1;
+}
+
+static PyObject* connection_get_isolation_level(Connection* self, void* unused)
+{
+    Py_INCREF(self->isolation_level);
+    return self->isolation_level;
+}
+
+static PyObject* connection_get_total_changes(Connection* self, void* unused)
+{
+    if (!check_connection(self)) {
+        return NULL;
+    } else {
+        return Py_BuildValue("i", sqlite3_total_changes(self->db));
+    }
+}
+
+static int connection_set_isolation_level(Connection* self, PyObject* isolation_level)
+{
+    PyObject* empty;
+    PyObject* res;
+    PyObject* begin_statement;
+
+    Py_XDECREF(self->isolation_level);
+
+    if (self->begin_statement) {
+        PyMem_Free(self->begin_statement);
+        self->begin_statement = NULL;
+    }
+
+    if (isolation_level == Py_None) {
+        Py_INCREF(Py_None);
+        self->isolation_level = Py_None;
+
+        empty = PyTuple_New(0);
+        if (!empty) {
+            return -1;
+        }
+        res = connection_commit(self, empty);
+        if (!res) {
+            return -1;
+        }
+        Py_DECREF(empty);
+        Py_DECREF(res);
+
+        self->inTransaction = 0;
+    } else {
+        Py_INCREF(isolation_level);
+        self->isolation_level = isolation_level;
+
+        begin_statement = PyString_FromString("BEGIN ");
+        if (!begin_statement) {
+            return -1;
+        }
+        PyString_Concat(&begin_statement, isolation_level);
+        if (!begin_statement) {
+            return -1;
+        }
+
+        self->begin_statement = PyMem_Malloc(PyString_Size(begin_statement) + 2);
+        if (!self->begin_statement) {
+            return -1;
+        }
+
+        strcpy(self->begin_statement, PyString_AsString(begin_statement));
+        Py_DECREF(begin_statement);
+    }
+
+    return 0;
+}
+
+PyObject* connection_call(Connection* self, PyObject* args, PyObject* kwargs)
+{
+    PyObject* sql;
+    Statement* statement;
+    int rc;
+
+    if (!PyArg_ParseTuple(args, "O", &sql)) {
+        return NULL;
+    }
+
+    statement = PyObject_New(Statement, &StatementType);
+    if (!statement) {
+        return NULL;
+    }
+
+    rc = statement_create(statement, self, sql);
+
+    if (rc != SQLITE_OK) {
+        if (rc == PYSQLITE_TOO_MUCH_SQL) {
+            PyErr_SetString(Warning, "You can only execute one statement at a time.");
+        } else if (rc == PYSQLITE_SQL_WRONG_TYPE) {
+            PyErr_SetString(Warning, "SQL is of wrong type. Must be string or unicode.");
+        } else {
+            _seterror(self->db);
+        }
+
+        Py_DECREF(statement);
+        statement = 0;
+    }
+
+    return (PyObject*)statement;
+}
+
+PyObject* connection_execute(Connection* self, PyObject* args, PyObject* kwargs)
+{
+    PyObject* cursor = 0;
+    PyObject* result = 0;
+    PyObject* method = 0;
+
+    cursor = PyObject_CallMethod((PyObject*)self, "cursor", "");
+    if (!cursor) {
+        goto error;
+    }
+
+    method = PyObject_GetAttrString(cursor, "execute");
+    if (!method) {
+        Py_DECREF(cursor);
+        cursor = 0;
+        goto error;
+    }
+
+    result = PyObject_CallObject(method, args);
+    if (!result) {
+        Py_DECREF(cursor);
+        cursor = 0;
+    }
+
+error:
+    Py_XDECREF(result);
+    Py_XDECREF(method);
+
+    return cursor;
+}
+
+PyObject* connection_executemany(Connection* self, PyObject* args, PyObject* kwargs)
+{
+    PyObject* cursor = 0;
+    PyObject* result = 0;
+    PyObject* method = 0;
+
+    cursor = PyObject_CallMethod((PyObject*)self, "cursor", "");
+    if (!cursor) {
+        goto error;
+    }
+
+    method = PyObject_GetAttrString(cursor, "executemany");
+    if (!method) {
+        Py_DECREF(cursor);
+        cursor = 0;
+        goto error;
+    }
+
+    result = PyObject_CallObject(method, args);
+    if (!result) {
+        Py_DECREF(cursor);
+        cursor = 0;
+    }
+
+error:
+    Py_XDECREF(result);
+    Py_XDECREF(method);
+
+    return cursor;
+}
+
+PyObject* connection_executescript(Connection* self, PyObject* args, PyObject* kwargs)
+{
+    PyObject* cursor = 0;
+    PyObject* result = 0;
+    PyObject* method = 0;
+
+    cursor = PyObject_CallMethod((PyObject*)self, "cursor", "");
+    if (!cursor) {
+        goto error;
+    }
+
+    method = PyObject_GetAttrString(cursor, "executescript");
+    if (!method) {
+        Py_DECREF(cursor);
+        cursor = 0;
+        goto error;
+    }
+
+    result = PyObject_CallObject(method, args);
+    if (!result) {
+        Py_DECREF(cursor);
+        cursor = 0;
+    }
+
+error:
+    Py_XDECREF(result);
+    Py_XDECREF(method);
+
+    return cursor;
+}
+
+/* ------------------------- COLLATION CODE ------------------------ */
+
+static int
+collation_callback(
+        void* context,
+        int text1_length, const void* text1_data,
+        int text2_length, const void* text2_data)
+{
+    PyObject* callback = (PyObject*)context;
+    PyObject* string1 = 0;
+    PyObject* string2 = 0;
+    PyGILState_STATE gilstate;
+
+    PyObject* retval = NULL;
+    int result = 0;
+
+    gilstate = PyGILState_Ensure();
+
+    if (PyErr_Occurred()) {
+        goto finally;
+    }
+
+    string1 = PyString_FromStringAndSize((const char*)text1_data, text1_length);
+    string2 = PyString_FromStringAndSize((const char*)text2_data, text2_length);
+
+    if (!string1 || !string2) {
+        goto finally; /* failed to allocate strings */
+    }
+
+    retval = PyObject_CallFunctionObjArgs(callback, string1, string2, NULL);
+
+    if (!retval) {
+        /* execution failed */
+        goto finally;
+    }
+
+    result = PyInt_AsLong(retval);
+    if (PyErr_Occurred()) {
+        result = 0;
+    }
+
+finally:
+    Py_XDECREF(string1);
+    Py_XDECREF(string2);
+    Py_XDECREF(retval);
+
+    PyGILState_Release(gilstate);
+
+    return result;
+}
+
+static PyObject *
+connection_create_collation(Connection* self, PyObject* args)
+{
+    PyObject* callable;
+    PyObject* uppercase_name = 0;
+    PyObject* name;
+    PyObject* retval;
+    char* chk;
+    int rc;
+
+    if (!check_thread(self) || !check_connection(self)) {
+        goto finally;
+    }
+
+    if (!PyArg_ParseTuple(args, "O!O:create_collation(name, callback)", &PyString_Type, &name, &callable)) {
+        goto finally;
+    }
+
+    uppercase_name = PyObject_CallMethod(name, "upper", "");
+    if (!uppercase_name) {
+        goto finally;
+    }
+
+    chk = PyString_AsString(uppercase_name);
+    while (*chk) {
+        if ((*chk >= '0' && *chk <= '9')
+         || (*chk >= 'A' && *chk <= 'Z')
+         || (*chk == '_'))
+        {
+            chk++;
+        } else {
+            PyErr_SetString(ProgrammingError, "invalid character in collation name");
+            goto finally;
+        }
+    }
+
+    if (callable != Py_None && !PyCallable_Check(callable)) {
+        PyErr_SetString(PyExc_TypeError, "parameter must be callable");
+        goto finally;
+    }
+
+    if (callable != Py_None) {
+        PyDict_SetItem(self->collations, uppercase_name, callable);
+    } else {
+        PyDict_DelItem(self->collations, uppercase_name);
+    }
+
+    rc = sqlite3_create_collation(self->db,
+                                  PyString_AsString(uppercase_name),
+                                  SQLITE_UTF8,
+                                  (callable != Py_None) ? callable : NULL,
+                                  (callable != Py_None) ? collation_callback : NULL);
+    if (rc != SQLITE_OK) {
+        PyDict_DelItem(self->collations, uppercase_name);
+        _seterror(self->db);
+        goto finally;
+    }
+
+finally:
+    Py_XDECREF(uppercase_name);
+
+    if (PyErr_Occurred()) {
+        retval = NULL;
+    } else {
+        Py_INCREF(Py_None);
+        retval = Py_None;
+    }
+
+    return retval;
+}
+
+static char connection_doc[] =
+PyDoc_STR("<missing docstring>");
+
+static PyGetSetDef connection_getset[] = {
+    {"isolation_level",  (getter)connection_get_isolation_level, (setter)connection_set_isolation_level},
+    {"total_changes",  (getter)connection_get_total_changes, (setter)0},
+    {NULL}
+};
+
+static PyMethodDef connection_methods[] = {
+    {"cursor", (PyCFunction)connection_cursor, METH_VARARGS|METH_KEYWORDS,
+        PyDoc_STR("Return a cursor for the connection.")},
+    {"close", (PyCFunction)connection_close, METH_NOARGS,
+        PyDoc_STR("Closes the connection.")},
+    {"commit", (PyCFunction)connection_commit, METH_NOARGS,
+        PyDoc_STR("Commit the current transaction.")},
+    {"rollback", (PyCFunction)connection_rollback, METH_NOARGS,
+        PyDoc_STR("Roll back the current transaction.")},
+    {"create_function", (PyCFunction)connection_create_function, METH_VARARGS|METH_KEYWORDS,
+        PyDoc_STR("Creates a new function. Non-standard.")},
+    {"create_aggregate", (PyCFunction)connection_create_aggregate, METH_VARARGS|METH_KEYWORDS,
+        PyDoc_STR("Creates a new aggregate. Non-standard.")},
+    {"execute", (PyCFunction)connection_execute, METH_VARARGS,
+        PyDoc_STR("Executes a SQL statement. Non-standard.")},
+    {"executemany", (PyCFunction)connection_executemany, METH_VARARGS,
+        PyDoc_STR("Repeatedly executes a SQL statement. Non-standard.")},
+    {"executescript", (PyCFunction)connection_executescript, METH_VARARGS,
+        PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")},
+    {"create_collation", (PyCFunction)connection_create_collation, METH_VARARGS,
+        PyDoc_STR("Creates a collation function.")},
+    {NULL, NULL}
+};
+
+static struct PyMemberDef connection_members[] =
+{
+    {"Warning", T_OBJECT, offsetof(Connection, Warning), RO},
+    {"Error", T_OBJECT, offsetof(Connection, Error), RO},
+    {"InterfaceError", T_OBJECT, offsetof(Connection, InterfaceError), RO},
+    {"DatabaseError", T_OBJECT, offsetof(Connection, DatabaseError), RO},
+    {"DataError", T_OBJECT, offsetof(Connection, DataError), RO},
+    {"OperationalError", T_OBJECT, offsetof(Connection, OperationalError), RO},
+    {"IntegrityError", T_OBJECT, offsetof(Connection, IntegrityError), RO},
+    {"InternalError", T_OBJECT, offsetof(Connection, InternalError), RO},
+    {"ProgrammingError", T_OBJECT, offsetof(Connection, ProgrammingError), RO},
+    {"NotSupportedError", T_OBJECT, offsetof(Connection, NotSupportedError), RO},
+    {"row_factory", T_OBJECT, offsetof(Connection, row_factory)},
+    {"text_factory", T_OBJECT, offsetof(Connection, text_factory)},
+    {NULL}
+};
+
+PyTypeObject ConnectionType = {
+        PyObject_HEAD_INIT(NULL)
+        0,                                              /* ob_size */
+        MODULE_NAME ".Connection",                      /* tp_name */
+        sizeof(Connection),                             /* tp_basicsize */
+        0,                                              /* tp_itemsize */
+        (destructor)connection_dealloc,                 /* tp_dealloc */
+        0,                                              /* tp_print */
+        0,                                              /* tp_getattr */
+        0,                                              /* tp_setattr */
+        0,                                              /* tp_compare */
+        0,                                              /* tp_repr */
+        0,                                              /* tp_as_number */
+        0,                                              /* tp_as_sequence */
+        0,                                              /* tp_as_mapping */
+        0,                                              /* tp_hash */
+        (ternaryfunc)connection_call,                   /* tp_call */
+        0,                                              /* tp_str */
+        0,                                              /* tp_getattro */
+        0,                                              /* tp_setattro */
+        0,                                              /* tp_as_buffer */
+        Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,         /* tp_flags */
+        connection_doc,                                 /* tp_doc */
+        0,                                              /* tp_traverse */
+        0,                                              /* tp_clear */
+        0,                                              /* tp_richcompare */
+        0,                                              /* tp_weaklistoffset */
+        0,                                              /* tp_iter */
+        0,                                              /* tp_iternext */
+        connection_methods,                             /* tp_methods */
+        connection_members,                             /* tp_members */
+        connection_getset,                              /* tp_getset */
+        0,                                              /* tp_base */
+        0,                                              /* tp_dict */
+        0,                                              /* tp_descr_get */
+        0,                                              /* tp_descr_set */
+        0,                                              /* tp_dictoffset */
+        (initproc)connection_init,                      /* tp_init */
+        0,                                              /* tp_alloc */
+        0,                                              /* tp_new */
+        0                                               /* tp_free */
+};
+
+extern int connection_setup_types(void)
+{
+    ConnectionType.tp_new = PyType_GenericNew;
+    return PyType_Ready(&ConnectionType);
+}
diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h
new file mode 100644
index 0000000..faae6e4
--- /dev/null
+++ b/Modules/_sqlite/connection.h
@@ -0,0 +1,106 @@
+/* connection.h - definitions for the connection type
+ *
+ * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_CONNECTION_H
+#define PYSQLITE_CONNECTION_H
+#include "Python.h"
+#include "pythread.h"
+#include "structmember.h"
+
+#include "cache.h"
+#include "module.h"
+
+#include "sqlite3.h"
+
+typedef struct
+{
+    PyObject_HEAD
+    sqlite3* db;
+
+    int inTransaction;
+    int detect_types;
+
+    /* the timeout value in seconds for database locks */
+    double timeout;
+
+    /* for internal use in the timeout handler: when did the timeout handler
+     * first get called with count=0? */
+    double timeout_started;
+
+    /* None for autocommit, otherwise a PyString with the isolation level */
+    PyObject* isolation_level;
+
+    /* NULL for autocommit, otherwise a string with the BEGIN statment; will be
+     * freed in connection destructor */
+    char* begin_statement;
+
+    int check_same_thread;
+    long thread_ident;
+
+    Cache* statement_cache;
+
+    PyObject* row_factory;
+
+    PyObject* text_factory;
+
+    /* remember references to functions/classes used in
+     * create_function/create/aggregate, use these as dictionary keys, so we
+     * can keep the total system refcount constant by clearing that dictionary
+     * in connection_dealloc */
+    PyObject* function_pinboard;
+
+    /* a dictionary of registered collation name => collation callable mappings */
+    PyObject* collations;
+
+    /* Exception objects */
+    PyObject* Warning;
+    PyObject* Error;
+    PyObject* InterfaceError;
+    PyObject* DatabaseError;
+    PyObject* DataError;
+    PyObject* OperationalError;
+    PyObject* IntegrityError;
+    PyObject* InternalError;
+    PyObject* ProgrammingError;
+    PyObject* NotSupportedError;
+} Connection;
+
+extern PyTypeObject ConnectionType;
+
+PyObject* connection_alloc(PyTypeObject* type, int aware);
+void connection_dealloc(Connection* self);
+PyObject* connection_cursor(Connection* self, PyObject* args, PyObject* kwargs);
+PyObject* connection_close(Connection* self, PyObject* args);
+PyObject* _connection_begin(Connection* self);
+PyObject* connection_begin(Connection* self, PyObject* args);
+PyObject* connection_commit(Connection* self, PyObject* args);
+PyObject* connection_rollback(Connection* self, PyObject* args);
+PyObject* connection_new(PyTypeObject* type, PyObject* args, PyObject* kw);
+int connection_init(Connection* self, PyObject* args, PyObject* kwargs);
+
+int check_thread(Connection* self);
+int check_connection(Connection* con);
+
+int connection_setup_types(void);
+
+#endif
diff --git a/Modules/_sqlite/converters.c b/Modules/_sqlite/converters.c
new file mode 100644
index 0000000..018063a
--- /dev/null
+++ b/Modules/_sqlite/converters.c
@@ -0,0 +1,40 @@
+/* converters.c - default converters
+ *
+ * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "util.h"
+#include "module.h"
+#include "adapters.h"
+
+/* dummy, will be implemented in a later version */
+
+PyObject* convert_date(PyObject* self, PyObject* args, PyObject* kwargs)
+{
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject* convert_timestamp(PyObject* self, PyObject* args, PyObject* kwargs)
+{
+    Py_INCREF(Py_None);
+    return Py_None;
+}
diff --git a/Modules/_sqlite/converters.h b/Modules/_sqlite/converters.h
new file mode 100644
index 0000000..df3768a
--- /dev/null
+++ b/Modules/_sqlite/converters.h
@@ -0,0 +1,33 @@
+/* converters.h - default converters
+ *
+ * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_CONVERTERS_H
+#define PYSQLITE_CONVERTERS_H
+#include "Python.h"
+#include "pythread.h"
+#include "sqlite3.h"
+
+PyObject* convert_date(PyObject* self, PyObject* args, PyObject* kwargs);
+PyObject* convert_timestamp(PyObject* self, PyObject* args, PyObject* kwargs);
+
+#endif
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
new file mode 100644
index 0000000..c6b8c77
--- /dev/null
+++ b/Modules/_sqlite/cursor.c
@@ -0,0 +1,1027 @@
+/* cursor.c - the cursor type
+ *
+ * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "cursor.h"
+#include "module.h"
+#include "util.h"
+#include "sqlitecompat.h"
+
+/* used to decide wether to call PyInt_FromLong or PyLong_FromLongLong */
+#define INT32_MIN (-2147483647 - 1)
+#define INT32_MAX 2147483647
+
+PyObject* cursor_iternext(Cursor *self);
+
+static StatementKind detect_statement_type(char* statement)
+{
+    char buf[20];
+    char* src;
+    char* dst;
+
+    src = statement;
+    /* skip over whitepace */
+    while (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') {
+        src++;
+    }
+
+    if (*src == 0)
+        return STATEMENT_INVALID;
+
+    dst = buf;
+    *dst = 0;
+    while (isalpha(*src) && dst - buf < sizeof(buf) - 2) {
+        *dst++ = tolower(*src++);
+    }
+
+    *dst = 0;
+
+    if (!strcmp(buf, "select")) {
+        return STATEMENT_SELECT;
+    } else if (!strcmp(buf, "insert")) {
+        return STATEMENT_INSERT;
+    } else if (!strcmp(buf, "update")) {
+        return STATEMENT_UPDATE;
+    } else if (!strcmp(buf, "delete")) {
+        return STATEMENT_DELETE;
+    } else if (!strcmp(buf, "replace")) {
+        return STATEMENT_REPLACE;
+    } else {
+        return STATEMENT_OTHER;
+    }
+}
+
+int cursor_init(Cursor* self, PyObject* args, PyObject* kwargs)
+{
+    Connection* connection;
+
+    if (!PyArg_ParseTuple(args, "O!", &ConnectionType, &connection))
+    {
+        return -1; 
+    }
+
+    Py_INCREF(connection);
+    self->connection = connection;
+    self->statement = NULL;
+    self->next_row = NULL;
+
+    self->row_cast_map = PyList_New(0);
+    if (!self->row_cast_map) {
+        return -1;
+    }
+
+    Py_INCREF(Py_None);
+    self->description = Py_None;
+
+    Py_INCREF(Py_None);
+    self->lastrowid= Py_None;
+
+    self->arraysize = 1;
+
+    self->rowcount = PyInt_FromLong(-1L);
+    if (!self->rowcount) {
+        return -1;
+    }
+
+    Py_INCREF(Py_None);
+    self->row_factory = Py_None;
+
+    if (!check_thread(self->connection)) {
+        return -1;
+    }
+
+    return 0;
+}
+
+void cursor_dealloc(Cursor* self)
+{
+    int rc;
+
+    /* Reset the statement if the user has not closed the cursor */
+    if (self->statement) {
+        rc = statement_reset(self->statement);
+        Py_DECREF(self->statement);
+    }
+
+    Py_XDECREF(self->connection);
+    Py_XDECREF(self->row_cast_map);
+    Py_XDECREF(self->description);
+    Py_XDECREF(self->lastrowid);
+    Py_XDECREF(self->rowcount);
+    Py_XDECREF(self->row_factory);
+    Py_XDECREF(self->next_row);
+
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+int build_row_cast_map(Cursor* self)
+{
+    int i;
+    const char* type_start = (const char*)-1;
+    const char* pos;
+
+    const char* colname;
+    const char* decltype;
+    PyObject* py_decltype;
+    PyObject* converter;
+    PyObject* key;
+
+    if (!self->connection->detect_types) {
+        return 0;
+    }
+
+    Py_XDECREF(self->row_cast_map);
+    self->row_cast_map = PyList_New(0);
+
+    for (i = 0; i < sqlite3_column_count(self->statement->st); i++) {
+        converter = NULL;
+
+        if (self->connection->detect_types | PARSE_COLNAMES) {
+            colname = sqlite3_column_name(self->statement->st, i);
+
+            for (pos = colname; *pos != 0; pos++) {
+                if (*pos == '[') {
+                    type_start = pos + 1;
+                } else if (*pos == ']' && type_start != (const char*)-1) {
+                    key = PyString_FromStringAndSize(type_start, pos - type_start);
+                    if (!key) {
+                        /* creating a string failed, but it is too complicated
+                         * to propagate the error here, we just assume there is
+                         * no converter and proceed */
+                        break;
+                    }
+
+                    converter = PyDict_GetItem(converters, key);
+                    Py_DECREF(key);
+                    break;
+                }
+
+            }
+        }
+
+        if (!converter && self->connection->detect_types | PARSE_DECLTYPES) {
+            decltype = sqlite3_column_decltype(self->statement->st, i);
+            if (decltype) {
+                for (pos = decltype;;pos++) {
+                    if (*pos == ' ' || *pos == 0) {
+                        py_decltype = PyString_FromStringAndSize(decltype, pos - decltype);
+                        if (!py_decltype) {
+                            return -1;
+                        }
+                        break;
+                    }
+                }
+
+                converter = PyDict_GetItem(converters, py_decltype);
+                Py_DECREF(py_decltype);
+            }
+        }
+
+        if (!converter) {
+            converter = Py_None;
+        }
+
+        if (PyList_Append(self->row_cast_map, converter) != 0) {
+            if (converter != Py_None) {
+                Py_DECREF(converter);
+            }
+            Py_XDECREF(self->row_cast_map);
+            self->row_cast_map = NULL;
+
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+PyObject* _build_column_name(const char* colname)
+{
+    const char* pos;
+
+    if (!colname) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    for (pos = colname;; pos++) {
+        if (*pos == 0 || *pos == ' ') {
+            return PyString_FromStringAndSize(colname, pos - colname);
+        }
+    }
+}
+
+PyObject* unicode_from_string(const char* val_str, int optimize)
+{
+    const char* check;
+    int is_ascii = 0;
+
+    if (optimize) {
+        is_ascii = 1;
+
+        check = val_str;
+        while (*check) {
+            if (*check & 0x80) {
+                is_ascii = 0;
+                break;
+            }
+
+            check++;
+        }
+    }
+
+    if (is_ascii) {
+        return PyString_FromString(val_str);
+    } else {
+        return PyUnicode_DecodeUTF8(val_str, strlen(val_str), NULL);
+    }
+}
+
+/*
+ * Returns a row from the currently active SQLite statement
+ *
+ * Precondidition:
+ * - sqlite3_step() has been called before and it returned SQLITE_ROW.
+ */
+PyObject* _fetch_one_row(Cursor* self)
+{
+    int i, numcols;
+    PyObject* row;
+    PyObject* item = NULL;
+    int coltype;
+    PY_LONG_LONG intval;
+    PyObject* converter;
+    PyObject* converted;
+    Py_ssize_t nbytes;
+    PyObject* buffer;
+    void* raw_buffer;
+    const char* val_str;
+    char buf[200];
+
+    Py_BEGIN_ALLOW_THREADS
+    numcols = sqlite3_data_count(self->statement->st);
+    Py_END_ALLOW_THREADS
+
+    row = PyTuple_New(numcols);
+    if (!row) {
+        return NULL;
+    }
+
+    for (i = 0; i < numcols; i++) {
+        if (self->connection->detect_types) {
+            converter = PyList_GetItem(self->row_cast_map, i);
+            if (!converter) {
+                converter = Py_None;
+            }
+        } else {
+            converter = Py_None;
+        }
+
+        if (converter != Py_None) {
+            val_str = (const char*)sqlite3_column_text(self->statement->st, i);
+            if (!val_str) {
+                Py_INCREF(Py_None);
+                converted = Py_None;
+            } else {
+                item = PyString_FromString(val_str);
+                if (!item) {
+                    return NULL;
+                }
+                converted = PyObject_CallFunction(converter, "O", item);
+                if (!converted) {
+                    /* TODO: have a way to log these errors */
+                    Py_INCREF(Py_None);
+                    converted = Py_None;
+                    PyErr_Clear();
+                }
+                Py_DECREF(item);
+            }
+        } else {
+            Py_BEGIN_ALLOW_THREADS
+            coltype = sqlite3_column_type(self->statement->st, i);
+            Py_END_ALLOW_THREADS
+            if (coltype == SQLITE_NULL) {
+                Py_INCREF(Py_None);
+                converted = Py_None;
+            } else if (coltype == SQLITE_INTEGER) {
+                intval = sqlite3_column_int64(self->statement->st, i);
+                if (intval < INT32_MIN || intval > INT32_MAX) {
+                    converted = PyLong_FromLongLong(intval);
+                } else {
+                    converted = PyInt_FromLong((long)intval);
+                }
+            } else if (coltype == SQLITE_FLOAT) {
+                converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i));
+            } else if (coltype == SQLITE_TEXT) {
+                val_str = (const char*)sqlite3_column_text(self->statement->st, i);
+                if ((self->connection->text_factory == (PyObject*)&PyUnicode_Type)
+                    || (self->connection->text_factory == OptimizedUnicode)) {
+
+                    converted = unicode_from_string(val_str,
+                        self->connection->text_factory == OptimizedUnicode ? 1 : 0);
+
+                    if (!converted) {
+                        PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column %s with text %s",
+                                    sqlite3_column_name(self->statement->st, i), val_str);
+                        PyErr_SetString(OperationalError, buf);
+                    }
+                } else if (self->connection->text_factory == (PyObject*)&PyString_Type) {
+                    converted = PyString_FromString(val_str);
+                } else {
+                    converted = PyObject_CallFunction(self->connection->text_factory, "s", val_str);
+                }
+            } else {
+                /* coltype == SQLITE_BLOB */
+                nbytes = sqlite3_column_bytes(self->statement->st, i);
+                buffer = PyBuffer_New(nbytes);
+                if (!buffer) {
+                    break;
+                }
+                if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &nbytes)) {
+                    break;
+                }
+                memcpy(raw_buffer, sqlite3_column_blob(self->statement->st, i), nbytes);
+                converted = buffer;
+            }
+        }
+
+        PyTuple_SetItem(row, i, converted);
+    }
+
+    if (PyErr_Occurred()) {
+        Py_DECREF(row);
+        row = NULL;
+    }
+
+    return row;
+}
+
+PyObject* _query_execute(Cursor* self, int multiple, PyObject* args)
+{
+    PyObject* operation;
+    PyObject* operation_bytestr = NULL;
+    char* operation_cstr;
+    PyObject* parameters_list = NULL;
+    PyObject* parameters_iter = NULL;
+    PyObject* parameters = NULL;
+    int i;
+    int rc;
+    PyObject* func_args;
+    PyObject* result;
+    int numcols;
+    PY_LONG_LONG lastrowid;
+    int statement_type;
+    PyObject* descriptor;
+    PyObject* second_argument = NULL;
+    long rowcount = 0;
+
+    if (!check_thread(self->connection) || !check_connection(self->connection)) {
+        return NULL;
+    }
+
+    Py_XDECREF(self->next_row);
+    self->next_row = NULL;
+
+    if (multiple) {
+        /* executemany() */
+        if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) {
+            return NULL; 
+        }
+
+        if (!PyString_Check(operation) && !PyUnicode_Check(operation)) {
+            PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode");
+            return NULL;
+        }
+
+        if (PyIter_Check(second_argument)) {
+            /* iterator */
+            Py_INCREF(second_argument);
+            parameters_iter = second_argument;
+        } else {
+            /* sequence */
+            parameters_iter = PyObject_GetIter(second_argument);
+            if (!parameters_iter)
+            {
+                return NULL;
+            }
+        }
+    } else {
+        /* execute() */
+        if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) {
+            return NULL; 
+        }
+
+        if (!PyString_Check(operation) && !PyUnicode_Check(operation)) {
+            PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode");
+            return NULL;
+        }
+
+        parameters_list = PyList_New(0);
+        if (!parameters_list) {
+            return NULL;
+        }
+
+        if (second_argument == NULL) {
+            second_argument = PyTuple_New(0);
+            if (!second_argument) {
+                goto error;
+            }
+        } else {
+            Py_INCREF(second_argument);
+        }
+        if (PyList_Append(parameters_list, second_argument) != 0) {
+            Py_DECREF(second_argument);
+            goto error;
+        }
+        Py_DECREF(second_argument);
+
+        parameters_iter = PyObject_GetIter(parameters_list);
+        if (!parameters_iter) {
+            goto error;
+        }
+    }
+
+    if (self->statement != NULL) {
+        /* There is an active statement */
+        rc = statement_reset(self->statement);
+    }
+
+    if (PyString_Check(operation)) {
+        operation_cstr = PyString_AsString(operation);
+    } else {
+        operation_bytestr = PyUnicode_AsUTF8String(operation);
+        if (!operation_bytestr) {
+            goto error;
+        }
+
+        operation_cstr = PyString_AsString(operation_bytestr);
+    }
+
+    /* reset description and rowcount */
+    Py_DECREF(self->description);
+    Py_INCREF(Py_None);
+    self->description = Py_None;
+
+    Py_DECREF(self->rowcount);
+    self->rowcount = PyInt_FromLong(-1L);
+    if (!self->rowcount) {
+        goto error;
+    }
+
+    statement_type = detect_statement_type(operation_cstr);
+    if (self->connection->begin_statement) {
+        switch (statement_type) {
+            case STATEMENT_UPDATE:
+            case STATEMENT_DELETE:
+            case STATEMENT_INSERT:
+            case STATEMENT_REPLACE:
+                if (!self->connection->inTransaction) {
+                    result = _connection_begin(self->connection);
+                    if (!result) {
+                        goto error;
+                    }
+                    Py_DECREF(result);
+                }
+                break;
+            case STATEMENT_OTHER:
+                /* it's a DDL statement or something similar
+                   - we better COMMIT first so it works for all cases */
+                if (self->connection->inTransaction) {
+                    func_args = PyTuple_New(0);
+                    if (!func_args) {
+                        goto error;
+                    }
+                    result = connection_commit(self->connection, func_args);
+                    Py_DECREF(func_args);
+                    if (!result) {
+                        goto error;
+                    }
+                    Py_DECREF(result);
+                }
+                break;
+            case STATEMENT_SELECT:
+                if (multiple) {
+                    PyErr_SetString(ProgrammingError,
+                                "You cannot execute SELECT statements in executemany().");
+                    goto error;
+                }
+                break;
+        }
+    }
+
+    func_args = PyTuple_New(1);
+    if (!func_args) {
+        goto error;
+    }
+    Py_INCREF(operation);
+    if (PyTuple_SetItem(func_args, 0, operation) != 0) {
+        goto error;
+    }
+
+    if (self->statement) {
+        (void)statement_reset(self->statement);
+        Py_DECREF(self->statement);
+    }
+
+    self->statement = (Statement*)cache_get(self->connection->statement_cache, func_args);
+    Py_DECREF(func_args);
+
+    if (!self->statement) {
+        goto error;
+    }
+
+    if (self->statement->in_use) {
+        Py_DECREF(self->statement);
+        self->statement = PyObject_New(Statement, &StatementType);
+        if (!self->statement) {
+            goto error;
+        }
+        rc = statement_create(self->statement, self->connection, operation);
+        if (rc != SQLITE_OK) {
+            self->statement = 0;
+            goto error;
+        }
+    }
+
+    statement_reset(self->statement);
+    statement_mark_dirty(self->statement);
+
+    while (1) {
+        parameters = PyIter_Next(parameters_iter);
+        if (!parameters) {
+            break;
+        }
+
+        statement_mark_dirty(self->statement);
+
+        statement_bind_parameters(self->statement, parameters);
+        if (PyErr_Occurred()) {
+            goto error;
+        }
+
+        if (build_row_cast_map(self) != 0) {
+            PyErr_SetString(OperationalError, "Error while building row_cast_map");
+            goto error;
+        }
+
+        rc = _sqlite_step_with_busyhandler(self->statement->st, self->connection);
+        if (rc != SQLITE_DONE && rc != SQLITE_ROW) {
+            rc = statement_reset(self->statement);
+            if (rc == SQLITE_SCHEMA) {
+                rc = statement_recompile(self->statement, parameters);
+                if (rc == SQLITE_OK) {
+                    rc = _sqlite_step_with_busyhandler(self->statement->st, self->connection);
+                } else {
+                    _seterror(self->connection->db);
+                    goto error;
+                }
+            } else {
+                _seterror(self->connection->db);
+                goto error;
+            }
+        }
+
+        if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) {
+            Py_BEGIN_ALLOW_THREADS
+            numcols = sqlite3_column_count(self->statement->st);
+            Py_END_ALLOW_THREADS
+
+            if (self->description == Py_None) {
+                Py_DECREF(self->description);
+                self->description = PyTuple_New(numcols);
+                if (!self->description) {
+                    goto error;
+                }
+                for (i = 0; i < numcols; i++) {
+                    descriptor = PyTuple_New(7);
+                    if (!descriptor) {
+                        goto error;
+                    }
+                    PyTuple_SetItem(descriptor, 0, _build_column_name(sqlite3_column_name(self->statement->st, i)));
+                    Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 1, Py_None);
+                    Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 2, Py_None);
+                    Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 3, Py_None);
+                    Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 4, Py_None);
+                    Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 5, Py_None);
+                    Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 6, Py_None);
+                    PyTuple_SetItem(self->description, i, descriptor);
+                }
+            }
+        }
+
+        if (rc == SQLITE_ROW) {
+            if (multiple) {
+                PyErr_SetString(ProgrammingError, "executemany() can only execute DML statements.");
+                goto error;
+            }
+
+            self->next_row = _fetch_one_row(self);
+        } else if (rc == SQLITE_DONE && !multiple) {
+            statement_reset(self->statement);
+            Py_DECREF(self->statement);
+            self->statement = 0;
+        }
+
+        switch (statement_type) {
+            case STATEMENT_UPDATE:
+            case STATEMENT_DELETE:
+            case STATEMENT_INSERT:
+            case STATEMENT_REPLACE:
+                Py_BEGIN_ALLOW_THREADS
+                rowcount += (long)sqlite3_changes(self->connection->db);
+                Py_END_ALLOW_THREADS
+                Py_DECREF(self->rowcount);
+                self->rowcount = PyInt_FromLong(rowcount);
+        }
+
+        Py_DECREF(self->lastrowid);
+        if (statement_type == STATEMENT_INSERT) {
+            Py_BEGIN_ALLOW_THREADS
+            lastrowid = sqlite3_last_insert_rowid(self->connection->db);
+            Py_END_ALLOW_THREADS
+            self->lastrowid = PyInt_FromLong((long)lastrowid);
+        } else {
+            Py_INCREF(Py_None);
+            self->lastrowid = Py_None;
+        }
+
+        if (multiple) {
+            rc = statement_reset(self->statement);
+        }
+        Py_XDECREF(parameters);
+    }
+
+error:
+    Py_XDECREF(operation_bytestr);
+    Py_XDECREF(parameters);
+    Py_XDECREF(parameters_iter);
+    Py_XDECREF(parameters_list);
+
+    if (PyErr_Occurred()) {
+        return NULL;
+    } else {
+        Py_INCREF(self);
+        return (PyObject*)self;
+    }
+}
+
+PyObject* cursor_execute(Cursor* self, PyObject* args)
+{
+    return _query_execute(self, 0, args);
+}
+
+PyObject* cursor_executemany(Cursor* self, PyObject* args)
+{
+    return _query_execute(self, 1, args);
+}
+
+PyObject* cursor_executescript(Cursor* self, PyObject* args)
+{
+    PyObject* script_obj;
+    PyObject* script_str = NULL;
+    const char* script_cstr;
+    sqlite3_stmt* statement;
+    int rc;
+    PyObject* func_args;
+    PyObject* result;
+    int statement_completed = 0;
+
+    if (!PyArg_ParseTuple(args, "O", &script_obj)) {
+        return NULL; 
+    }
+
+    if (!check_thread(self->connection) || !check_connection(self->connection)) {
+        return NULL;
+    }
+
+    if (PyString_Check(script_obj)) {
+        script_cstr = PyString_AsString(script_obj);
+    } else if (PyUnicode_Check(script_obj)) {
+        script_str = PyUnicode_AsUTF8String(script_obj);
+        if (!script_str) {
+            return NULL;
+        }
+
+        script_cstr = PyString_AsString(script_str);
+    } else {
+        PyErr_SetString(PyExc_ValueError, "script argument must be unicode or string.");
+        return NULL;
+    }
+
+    /* commit first */
+    func_args = PyTuple_New(0);
+    if (!func_args) {
+        goto error;
+    }
+    result = connection_commit(self->connection, func_args);
+    Py_DECREF(func_args);
+    if (!result) {
+        goto error;
+    }
+    Py_DECREF(result);
+
+    while (1) {
+        if (!sqlite3_complete(script_cstr)) {
+            break;
+        }
+        statement_completed = 1;
+
+        rc = sqlite3_prepare(self->connection->db,
+                             script_cstr,
+                             -1,
+                             &statement,
+                             &script_cstr);
+        if (rc != SQLITE_OK) {
+            _seterror(self->connection->db);
+            goto error;
+        }
+
+        /* execute statement, and ignore results of SELECT statements */
+        rc = SQLITE_ROW;
+        while (rc == SQLITE_ROW) {
+            rc = _sqlite_step_with_busyhandler(statement, self->connection);
+        }
+
+        if (rc != SQLITE_DONE) {
+            (void)sqlite3_finalize(statement);
+            _seterror(self->connection->db);
+            goto error;
+        }
+
+        rc = sqlite3_finalize(statement);
+        if (rc != SQLITE_OK) {
+            _seterror(self->connection->db);
+            goto error;
+        }
+    }
+
+error:
+    Py_XDECREF(script_str);
+
+    if (!statement_completed) {
+        PyErr_SetString(ProgrammingError, "you did not provide a complete SQL statement");
+    }
+
+    if (PyErr_Occurred()) {
+        return NULL;
+    } else {
+        Py_INCREF(self);
+        return (PyObject*)self;
+    }
+}
+
+PyObject* cursor_getiter(Cursor *self)
+{
+    Py_INCREF(self);
+    return (PyObject*)self;
+}
+
+PyObject* cursor_iternext(Cursor *self)
+{
+    PyObject* next_row_tuple;
+    PyObject* next_row;
+    int rc;
+
+    if (!check_thread(self->connection) || !check_connection(self->connection)) {
+        return NULL;
+    }
+
+    if (!self->next_row) {
+         if (self->statement) {
+            (void)statement_reset(self->statement);
+            Py_DECREF(self->statement);
+            self->statement = NULL;
+        }
+        return NULL;
+    }
+
+    next_row_tuple = self->next_row;
+    self->next_row = NULL;
+
+    if (self->row_factory != Py_None) {
+        next_row = PyObject_CallFunction(self->row_factory, "OO", self, next_row_tuple);
+        Py_DECREF(next_row_tuple);
+    } else {
+        next_row = next_row_tuple;
+    }
+
+    rc = _sqlite_step_with_busyhandler(self->statement->st, self->connection);
+    if (rc != SQLITE_DONE && rc != SQLITE_ROW) {
+        Py_DECREF(next_row);
+        _seterror(self->connection->db);
+        return NULL;
+    }
+
+    if (rc == SQLITE_ROW) {
+        self->next_row = _fetch_one_row(self);
+    }
+
+    return next_row;
+}
+
+PyObject* cursor_fetchone(Cursor* self, PyObject* args)
+{
+    PyObject* row;
+
+    row = cursor_iternext(self);
+    if (!row && !PyErr_Occurred()) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    return row;
+}
+
+PyObject* cursor_fetchmany(Cursor* self, PyObject* args)
+{
+    PyObject* row;
+    PyObject* list;
+    int maxrows = self->arraysize;
+    int counter = 0;
+
+    if (!PyArg_ParseTuple(args, "|i", &maxrows)) {
+        return NULL; 
+    }
+
+    list = PyList_New(0);
+    if (!list) {
+        return NULL;
+    }
+
+    /* just make sure we enter the loop */
+    row = Py_None;
+
+    while (row) {
+        row = cursor_iternext(self);
+        if (row) {
+            PyList_Append(list, row);
+            Py_DECREF(row);
+        } else {
+            break;
+        }
+
+        if (++counter == maxrows) {
+            break;
+        }
+    }
+
+    if (PyErr_Occurred()) {
+        Py_DECREF(list);
+        return NULL;
+    } else {
+        return list;
+    }
+}
+
+PyObject* cursor_fetchall(Cursor* self, PyObject* args)
+{
+    PyObject* row;
+    PyObject* list;
+
+    list = PyList_New(0);
+    if (!list) {
+        return NULL;
+    }
+
+    /* just make sure we enter the loop */
+    row = (PyObject*)Py_None;
+
+    while (row) {
+        row = cursor_iternext(self);
+        if (row) {
+            PyList_Append(list, row);
+            Py_DECREF(row);
+        }
+    }
+
+    if (PyErr_Occurred()) {
+        Py_DECREF(list);
+        return NULL;
+    } else {
+        return list;
+    }
+}
+
+PyObject* pysqlite_noop(Connection* self, PyObject* args)
+{
+    /* don't care, return None */
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject* cursor_close(Cursor* self, PyObject* args)
+{
+    if (!check_thread(self->connection) || !check_connection(self->connection)) {
+        return NULL;
+    }
+
+    if (self->statement) {
+        (void)statement_reset(self->statement);
+        Py_DECREF(self->statement);
+        self->statement = 0;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef cursor_methods[] = {
+    {"execute", (PyCFunction)cursor_execute, METH_VARARGS,
+        PyDoc_STR("Executes a SQL statement.")},
+    {"executemany", (PyCFunction)cursor_executemany, METH_VARARGS,
+        PyDoc_STR("Repeatedly executes a SQL statement.")},
+    {"executescript", (PyCFunction)cursor_executescript, METH_VARARGS,
+        PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")},
+    {"fetchone", (PyCFunction)cursor_fetchone, METH_NOARGS,
+        PyDoc_STR("Fetches several rows from the resultset.")},
+    {"fetchmany", (PyCFunction)cursor_fetchmany, METH_VARARGS,
+        PyDoc_STR("Fetches all rows from the resultset.")},
+    {"fetchall", (PyCFunction)cursor_fetchall, METH_NOARGS,
+        PyDoc_STR("Fetches one row from the resultset.")},
+    {"close", (PyCFunction)cursor_close, METH_NOARGS,
+        PyDoc_STR("Closes the cursor.")},
+    {"setinputsizes", (PyCFunction)pysqlite_noop, METH_VARARGS,
+        PyDoc_STR("Required by DB-API. Does nothing in pysqlite.")},
+    {"setoutputsize", (PyCFunction)pysqlite_noop, METH_VARARGS,
+        PyDoc_STR("Required by DB-API. Does nothing in pysqlite.")},
+    {NULL, NULL}
+};
+
+static struct PyMemberDef cursor_members[] =
+{
+    {"connection", T_OBJECT, offsetof(Cursor, connection), RO},
+    {"description", T_OBJECT, offsetof(Cursor, description), RO},
+    {"arraysize", T_INT, offsetof(Cursor, arraysize), 0},
+    {"lastrowid", T_OBJECT, offsetof(Cursor, lastrowid), RO},
+    {"rowcount", T_OBJECT, offsetof(Cursor, rowcount), RO},
+    {"row_factory", T_OBJECT, offsetof(Cursor, row_factory), 0},
+    {NULL}
+};
+
+PyTypeObject CursorType = {
+        PyObject_HEAD_INIT(NULL)
+        0,                                              /* ob_size */
+        MODULE_NAME ".Cursor",                          /* tp_name */
+        sizeof(Cursor),                                 /* tp_basicsize */
+        0,                                              /* tp_itemsize */
+        (destructor)cursor_dealloc,                     /* tp_dealloc */
+        0,                                              /* tp_print */
+        0,                                              /* tp_getattr */
+        0,                                              /* tp_setattr */
+        0,                                              /* tp_compare */
+        0,                                              /* tp_repr */
+        0,                                              /* tp_as_number */
+        0,                                              /* tp_as_sequence */
+        0,                                              /* tp_as_mapping */
+        0,                                              /* tp_hash */
+        0,                                              /* tp_call */
+        0,                                              /* tp_str */
+        0,                                              /* tp_getattro */
+        0,                                              /* tp_setattro */
+        0,                                              /* tp_as_buffer */
+        Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_ITER|Py_TPFLAGS_BASETYPE, /* tp_flags */
+        0,                                              /* tp_doc */
+        0,                                              /* tp_traverse */
+        0,                                              /* tp_clear */
+        0,                                              /* tp_richcompare */
+        0,                                              /* tp_weaklistoffset */
+        (getiterfunc)cursor_getiter,                    /* tp_iter */
+        (iternextfunc)cursor_iternext,                  /* tp_iternext */
+        cursor_methods,                                 /* tp_methods */
+        cursor_members,                                 /* tp_members */
+        0,                                              /* tp_getset */
+        0,                                              /* tp_base */
+        0,                                              /* tp_dict */
+        0,                                              /* tp_descr_get */
+        0,                                              /* tp_descr_set */
+        0,                                              /* tp_dictoffset */
+        (initproc)cursor_init,                          /* tp_init */
+        0,                                              /* tp_alloc */
+        0,                                              /* tp_new */
+        0                                               /* tp_free */
+};
+
+extern int cursor_setup_types(void)
+{
+    CursorType.tp_new = PyType_GenericNew;
+    return PyType_Ready(&CursorType);
+}
diff --git a/Modules/_sqlite/cursor.h b/Modules/_sqlite/cursor.h
new file mode 100644
index 0000000..7f56799
--- /dev/null
+++ b/Modules/_sqlite/cursor.h
@@ -0,0 +1,71 @@
+/* cursor.h - definitions for the cursor type
+ *
+ * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_CURSOR_H
+#define PYSQLITE_CURSOR_H
+#include "Python.h"
+
+#include "statement.h"
+#include "connection.h"
+#include "module.h"
+
+typedef struct
+{
+    PyObject_HEAD
+    Connection* connection;
+    PyObject* description;
+    PyObject* row_cast_map;
+    int arraysize;
+    PyObject* lastrowid;
+    PyObject* rowcount;
+    PyObject* row_factory;
+    Statement* statement;
+
+    /* the next row to be returned, NULL if no next row available */
+    PyObject* next_row;
+} Cursor;
+
+typedef enum {
+    STATEMENT_INVALID, STATEMENT_INSERT, STATEMENT_DELETE,
+    STATEMENT_UPDATE, STATEMENT_REPLACE, STATEMENT_SELECT,
+    STATEMENT_OTHER
+} StatementKind;
+
+extern PyTypeObject CursorType;
+
+int cursor_init(Cursor* self, PyObject* args, PyObject* kwargs);
+void cursor_dealloc(Cursor* self);
+PyObject* cursor_execute(Cursor* self, PyObject* args);
+PyObject* cursor_executemany(Cursor* self, PyObject* args);
+PyObject* cursor_getiter(Cursor *self);
+PyObject* cursor_iternext(Cursor *self);
+PyObject* cursor_fetchone(Cursor* self, PyObject* args);
+PyObject* cursor_fetchmany(Cursor* self, PyObject* args);
+PyObject* cursor_fetchall(Cursor* self, PyObject* args);
+PyObject* pysqlite_noop(Connection* self, PyObject* args);
+PyObject* cursor_close(Cursor* self, PyObject* args);
+
+int cursor_setup_types(void);
+
+#define UNKNOWN (-1)
+#endif
diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c
new file mode 100644
index 0000000..4956ac0
--- /dev/null
+++ b/Modules/_sqlite/microprotocols.c
@@ -0,0 +1,142 @@
+/* microprotocols.c - minimalist and non-validating protocols implementation
+ *
+ * Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
+ *
+ * This file is part of psycopg and was adapted for pysqlite. Federico Di
+ * Gregorio gave the permission to use it within pysqlite under the following
+ * license:
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "cursor.h"
+#include "microprotocols.h"
+#include "prepare_protocol.h"
+
+
+/** the adapters registry **/
+
+PyObject *psyco_adapters;
+
+/* microprotocols_init - initialize the adapters dictionary */
+
+int
+microprotocols_init(PyObject *dict)
+{
+    /* create adapters dictionary and put it in module namespace */
+    if ((psyco_adapters = PyDict_New()) == NULL) {
+        return -1;
+    }
+
+    return PyDict_SetItemString(dict, "adapters", psyco_adapters);
+}
+
+
+/* microprotocols_add - add a reverse type-caster to the dictionary */
+
+int
+microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast)
+{
+    PyObject* key;
+    int rc;
+
+    if (proto == NULL) proto = (PyObject*)&SQLitePrepareProtocolType;
+
+    key = Py_BuildValue("(OO)", (PyObject*)type, proto);
+    if (!key) {
+        return -1;
+    }
+
+    rc = PyDict_SetItem(psyco_adapters, key, cast);
+    Py_DECREF(key);
+
+    return rc;
+}
+
+/* microprotocols_adapt - adapt an object to the built-in protocol */
+
+PyObject *
+microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
+{
+    PyObject *adapter, *key;
+
+    /* we don't check for exact type conformance as specified in PEP 246
+       because the SQLitePrepareProtocolType type is abstract and there is no
+       way to get a quotable object to be its instance */
+
+    /* look for an adapter in the registry */
+    key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto);
+    if (!key) {
+        return NULL;
+    }
+    adapter = PyDict_GetItem(psyco_adapters, key);
+    Py_DECREF(key);
+    if (adapter) {
+        PyObject *adapted = PyObject_CallFunctionObjArgs(adapter, obj, NULL);
+        return adapted;
+    }
+
+    /* try to have the protocol adapt this object*/
+    if (PyObject_HasAttrString(proto, "__adapt__")) {
+        PyObject *adapted = PyObject_CallMethod(proto, "__adapt__", "O", obj);
+        if (adapted) {
+            if (adapted != Py_None) {
+                return adapted;
+            } else {
+                Py_DECREF(adapted);
+            }
+        }
+
+        if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError))
+            return NULL;
+    }
+
+    /* and finally try to have the object adapt itself */
+    if (PyObject_HasAttrString(obj, "__conform__")) {
+        PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto);
+        if (adapted) {
+            if (adapted != Py_None) {
+                return adapted;
+            } else {
+                Py_DECREF(adapted);
+            }
+        }
+
+        if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) {
+            return NULL;
+        }
+    }
+
+    /* else set the right exception and return NULL */
+    PyErr_SetString(ProgrammingError, "can't adapt");
+    return NULL;
+}
+
+/** module-level functions **/
+
+PyObject *
+psyco_microprotocols_adapt(Cursor *self, PyObject *args)
+{
+    PyObject *obj, *alt = NULL;
+    PyObject *proto = (PyObject*)&SQLitePrepareProtocolType;
+
+    if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL;
+    return microprotocols_adapt(obj, proto, alt);
+}
diff --git a/Modules/_sqlite/microprotocols.h b/Modules/_sqlite/microprotocols.h
new file mode 100644
index 0000000..d2d9b65
--- /dev/null
+++ b/Modules/_sqlite/microprotocols.h
@@ -0,0 +1,59 @@
+/* microprotocols.c - definitions for minimalist and non-validating protocols
+ *
+ * Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
+ *
+ * This file is part of psycopg and was adapted for pysqlite. Federico Di
+ * Gregorio gave the permission to use it within pysqlite under the following
+ * license:
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PSYCOPG_MICROPROTOCOLS_H
+#define PSYCOPG_MICROPROTOCOLS_H 1
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** adapters registry **/
+
+extern PyObject *psyco_adapters;
+
+/** the names of the three mandatory methods **/
+
+#define MICROPROTOCOLS_GETQUOTED_NAME "getquoted"
+#define MICROPROTOCOLS_GETSTRING_NAME "getstring"
+#define MICROPROTOCOLS_GETBINARY_NAME "getbinary"
+
+/** exported functions **/
+
+/* used by module.c to init the microprotocols system */
+extern int microprotocols_init(PyObject *dict);
+extern int microprotocols_add(
+    PyTypeObject *type, PyObject *proto, PyObject *cast);
+extern PyObject *microprotocols_adapt(
+    PyObject *obj, PyObject *proto, PyObject *alt);
+
+extern PyObject *
+    psyco_microprotocols_adapt(Cursor* self, PyObject *args);   
+#define psyco_microprotocols_adapt_doc \
+    "adapt(obj, protocol, alternate) -> adapt obj to given protocol"
+    
+#endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */
diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c
new file mode 100644
index 0000000..1537e79
--- /dev/null
+++ b/Modules/_sqlite/module.c
@@ -0,0 +1,325 @@
+/* module.c - the module itself
+ *
+ * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "connection.h"
+#include "statement.h"
+#include "cursor.h"
+#include "cache.h"
+#include "prepare_protocol.h"
+#include "microprotocols.h"
+#include "row.h"
+
+#if SQLITE_VERSION_NUMBER >= 3003003
+#define HAVE_SHARED_CACHE
+#endif
+
+/* static objects at module-level */
+
+PyObject* Error, *Warning, *InterfaceError, *DatabaseError, *InternalError,
+    *OperationalError, *ProgrammingError, *IntegrityError, *DataError,
+    *NotSupportedError, *OptimizedUnicode;
+
+PyObject* converters;
+
+static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
+        kwargs)
+{
+    /* Python seems to have no way of extracting a single keyword-arg at
+     * C-level, so this code is redundant with the one in connection_init in
+     * connection.c and must always be copied from there ... */
+
+    static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL};
+    char* database;
+    int detect_types = 0;
+    PyObject* isolation_level;
+    PyObject* factory = NULL;
+    int check_same_thread = 1;
+    int cached_statements;
+    double timeout = 5.0;
+
+    PyObject* result;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOi", kwlist,
+                                     &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements))
+    {
+        return NULL; 
+    }
+
+    if (factory == NULL) {
+        factory = (PyObject*)&ConnectionType;
+    }
+
+    result = PyObject_Call(factory, args, kwargs);
+
+    return result;
+}
+
+static PyObject* module_complete(PyObject* self, PyObject* args, PyObject*
+        kwargs)
+{
+    static char *kwlist[] = {"statement", NULL, NULL};
+    char* statement;
+
+    PyObject* result;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &statement))
+    {
+        return NULL; 
+    }
+
+    if (sqlite3_complete(statement)) {
+        result = Py_True;
+    } else {
+        result = Py_False;
+    }
+
+    Py_INCREF(result);
+
+    return result;
+}
+
+#ifdef HAVE_SHARED_CACHE
+static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject*
+        kwargs)
+{
+    static char *kwlist[] = {"do_enable", NULL, NULL};
+    int do_enable;
+    int rc;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &do_enable))
+    {
+        return NULL; 
+    }
+
+    rc = sqlite3_enable_shared_cache(do_enable);
+
+    if (rc != SQLITE_OK) {
+        PyErr_SetString(OperationalError, "Changing the shared_cache flag failed");
+        return NULL;
+    } else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+}
+#endif /* HAVE_SHARED_CACHE */
+
+static PyObject* module_register_adapter(PyObject* self, PyObject* args, PyObject* kwargs)
+{
+    PyTypeObject* type;
+    PyObject* caster;
+
+    if (!PyArg_ParseTuple(args, "OO", &type, &caster)) {
+        return NULL;
+    }
+
+    microprotocols_add(type, (PyObject*)&SQLitePrepareProtocolType, caster);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject* module_register_converter(PyObject* self, PyObject* args, PyObject* kwargs)
+{
+    PyObject* name;
+    PyObject* callable;
+
+    if (!PyArg_ParseTuple(args, "OO", &name, &callable)) {
+        return NULL;
+    }
+
+    if (PyDict_SetItem(converters, name, callable) != 0) {
+        return NULL;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+void converters_init(PyObject* dict)
+{
+    converters = PyDict_New();
+    if (!converters) {
+        return;
+    }
+
+    PyDict_SetItemString(dict, "converters", converters);
+}
+
+static PyMethodDef module_methods[] = {
+    {"connect",  (PyCFunction)module_connect,  METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Creates a connection.")},
+    {"complete_statement",  (PyCFunction)module_complete,  METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Checks if a string contains a complete SQL statement.")},
+#ifdef HAVE_SHARED_CACHE
+    {"enable_shared_cache",  (PyCFunction)module_enable_shared_cache,  METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Enable or disable shared cache mode for the calling thread.")},
+#endif
+    {"register_adapter", (PyCFunction)module_register_adapter, METH_VARARGS, PyDoc_STR("Registers an adapter with sqlite's adapter registry.")},
+    {"register_converter", (PyCFunction)module_register_converter, METH_VARARGS, PyDoc_STR("Registers a converter with sqlite.")},
+    {"adapt",  (PyCFunction)psyco_microprotocols_adapt, METH_VARARGS, psyco_microprotocols_adapt_doc},
+    {NULL, NULL}
+};
+
+PyMODINIT_FUNC init_sqlite3(void)
+{
+    PyObject *module, *dict;
+    PyObject *tmp_obj;
+
+    module = Py_InitModule("_sqlite3", module_methods);
+
+    if (!module ||
+        (row_setup_types() < 0) ||
+        (cursor_setup_types() < 0) ||
+        (connection_setup_types() < 0) ||
+        (cache_setup_types() < 0) ||
+        (statement_setup_types() < 0) ||
+        (prepare_protocol_setup_types() < 0)
+       ) {
+        return;
+    }
+
+    Py_INCREF(&ConnectionType);
+    PyModule_AddObject(module, "Connection", (PyObject*) &ConnectionType);
+    Py_INCREF(&CursorType);
+    PyModule_AddObject(module, "Cursor", (PyObject*) &CursorType);
+    Py_INCREF(&CacheType);
+    PyModule_AddObject(module, "Statement", (PyObject*)&StatementType);
+    Py_INCREF(&StatementType);
+    PyModule_AddObject(module, "Cache", (PyObject*) &CacheType);
+    Py_INCREF(&SQLitePrepareProtocolType);
+    PyModule_AddObject(module, "PrepareProtocol", (PyObject*) &SQLitePrepareProtocolType);
+    Py_INCREF(&RowType);
+    PyModule_AddObject(module, "Row", (PyObject*) &RowType);
+
+    if (!(dict = PyModule_GetDict(module))) {
+        goto error;
+    }
+
+    /*** Create DB-API Exception hierarchy */
+
+    if (!(Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_StandardError, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "Error", Error);
+
+    if (!(Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_StandardError, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "Warning", Warning);
+
+    /* Error subclasses */
+
+    if (!(InterfaceError = PyErr_NewException(MODULE_NAME ".InterfaceError", Error, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "InterfaceError", InterfaceError);
+
+    if (!(DatabaseError = PyErr_NewException(MODULE_NAME ".DatabaseError", Error, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "DatabaseError", DatabaseError);
+
+    /* DatabaseError subclasses */
+
+    if (!(InternalError = PyErr_NewException(MODULE_NAME ".InternalError", DatabaseError, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "InternalError", InternalError);
+
+    if (!(OperationalError = PyErr_NewException(MODULE_NAME ".OperationalError", DatabaseError, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "OperationalError", OperationalError);
+
+    if (!(ProgrammingError = PyErr_NewException(MODULE_NAME ".ProgrammingError", DatabaseError, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError);
+
+    if (!(IntegrityError = PyErr_NewException(MODULE_NAME ".IntegrityError", DatabaseError,NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "IntegrityError", IntegrityError);
+
+    if (!(DataError = PyErr_NewException(MODULE_NAME ".DataError", DatabaseError, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "DataError", DataError);
+
+    if (!(NotSupportedError = PyErr_NewException(MODULE_NAME ".NotSupportedError", DatabaseError, NULL))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError);
+
+    /* We just need "something" unique for OptimizedUnicode. It does not really
+     * need to be a string subclass. Just anything that can act as a special
+     * marker for us. So I pulled PyCell_Type out of my magic hat.
+     */
+    Py_INCREF((PyObject*)&PyCell_Type);
+    OptimizedUnicode = (PyObject*)&PyCell_Type;
+    PyDict_SetItemString(dict, "OptimizedUnicode", OptimizedUnicode);
+
+    if (!(tmp_obj = PyInt_FromLong(PARSE_DECLTYPES))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "PARSE_DECLTYPES", tmp_obj);
+
+    if (!(tmp_obj = PyInt_FromLong(PARSE_COLNAMES))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "PARSE_COLNAMES", tmp_obj);
+
+    if (!(tmp_obj = PyString_FromString(PYSQLITE_VERSION))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "version", tmp_obj);
+
+    if (!(tmp_obj = PyString_FromString(sqlite3_libversion()))) {
+        goto error;
+    }
+    PyDict_SetItemString(dict, "sqlite_version", tmp_obj);
+
+    /* initialize microprotocols layer */
+    microprotocols_init(dict);
+
+    /* initialize the default converters */
+    converters_init(dict);
+
+    /* Original comment form _bsddb.c in the Python core. This is also still
+     * needed nowadays for Python 2.3/2.4.
+     * 
+     * PyEval_InitThreads is called here due to a quirk in python 1.5
+     * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
+     * The global interepreter lock is not initialized until the first
+     * thread is created using thread.start_new_thread() or fork() is
+     * called.  that would cause the ALLOW_THREADS here to segfault due
+     * to a null pointer reference if no threads or child processes
+     * have been created.  This works around that and is a no-op if
+     * threads have already been initialized.
+     *  (see pybsddb-users mailing list post on 2002-08-07)
+     */
+    PyEval_InitThreads();
+
+error:
+    if (PyErr_Occurred())
+    {
+        PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed");
+    }
+}
diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h
new file mode 100644
index 0000000..6694735
--- /dev/null
+++ b/Modules/_sqlite/module.h
@@ -0,0 +1,55 @@
+/* module.h - definitions for the module
+ *
+ * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_MODULE_H
+#define PYSQLITE_MODULE_H
+#include "Python.h"
+
+#define PYSQLITE_VERSION "2.2.0"
+
+extern PyObject* Error;
+extern PyObject* Warning;
+extern PyObject* InterfaceError;
+extern PyObject* DatabaseError;
+extern PyObject* InternalError;
+extern PyObject* OperationalError;
+extern PyObject* ProgrammingError;
+extern PyObject* IntegrityError;
+extern PyObject* DataError;
+extern PyObject* NotSupportedError;
+
+extern PyObject* OptimizedUnicode;
+
+/* the functions time.time() and time.sleep() */
+extern PyObject* time_time;
+extern PyObject* time_sleep;
+
+/* A dictionary, mapping colum types (INTEGER, VARCHAR, etc.) to converter
+ * functions, that convert the SQL value to the appropriate Python value.
+ * The key is uppercase.
+ */
+extern PyObject* converters;
+
+#define PARSE_DECLTYPES 1
+#define PARSE_COLNAMES 2
+#endif
diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c
new file mode 100644
index 0000000..26b663b
--- /dev/null
+++ b/Modules/_sqlite/prepare_protocol.c
@@ -0,0 +1,84 @@
+/* prepare_protocol.c - the protocol for preparing values for SQLite
+ *
+ * Copyright (C) 2005-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "prepare_protocol.h"
+
+int prepare_protocol_init(SQLitePrepareProtocol* self, PyObject* args, PyObject* kwargs)
+{
+    return 0;
+}
+
+void prepare_protocol_dealloc(SQLitePrepareProtocol* self)
+{
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+PyTypeObject SQLitePrepareProtocolType= {
+        PyObject_HEAD_INIT(NULL)
+        0,                                              /* ob_size */
+        MODULE_NAME ".PrepareProtocol",                 /* tp_name */
+        sizeof(SQLitePrepareProtocol),                  /* tp_basicsize */
+        0,                                              /* tp_itemsize */
+        (destructor)prepare_protocol_dealloc,           /* tp_dealloc */
+        0,                                              /* tp_print */
+        0,                                              /* tp_getattr */
+        0,                                              /* tp_setattr */
+        0,                                              /* tp_compare */
+        0,                                              /* tp_repr */
+        0,                                              /* tp_as_number */
+        0,                                              /* tp_as_sequence */
+        0,                                              /* tp_as_mapping */
+        0,                                              /* tp_hash */
+        0,                                              /* tp_call */
+        0,                                              /* tp_str */
+        0,                                              /* tp_getattro */
+        0,                                              /* tp_setattro */
+        0,                                              /* tp_as_buffer */
+        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
+        0,                                              /* tp_doc */
+        0,                                              /* tp_traverse */
+        0,                                              /* tp_clear */
+        0,                                              /* tp_richcompare */
+        0,                                              /* tp_weaklistoffset */
+        0,                                              /* tp_iter */
+        0,                                              /* tp_iternext */
+        0,                                              /* tp_methods */
+        0,                                              /* tp_members */
+        0,                                              /* tp_getset */
+        0,                                              /* tp_base */
+        0,                                              /* tp_dict */
+        0,                                              /* tp_descr_get */
+        0,                                              /* tp_descr_set */
+        0,                                              /* tp_dictoffset */
+        (initproc)prepare_protocol_init,                /* tp_init */
+        0,                                              /* tp_alloc */
+        0,                                              /* tp_new */
+        0                                               /* tp_free */
+};
+
+extern int prepare_protocol_setup_types(void)
+{
+    SQLitePrepareProtocolType.tp_new = PyType_GenericNew;
+    SQLitePrepareProtocolType.ob_type= &PyType_Type;
+    return PyType_Ready(&SQLitePrepareProtocolType);
+}
diff --git a/Modules/_sqlite/prepare_protocol.h b/Modules/_sqlite/prepare_protocol.h
new file mode 100644
index 0000000..2fc4f61
--- /dev/null
+++ b/Modules/_sqlite/prepare_protocol.h
@@ -0,0 +1,41 @@
+/* prepare_protocol.h - the protocol for preparing values for SQLite
+ *
+ * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_PREPARE_PROTOCOL_H
+#define PYSQLITE_PREPARE_PROTOCOL_H
+#include "Python.h"
+
+typedef struct
+{
+    PyObject_HEAD
+} SQLitePrepareProtocol;
+
+extern PyTypeObject SQLitePrepareProtocolType;
+
+int prepare_protocol_init(SQLitePrepareProtocol* self, PyObject* args, PyObject* kwargs);
+void prepare_protocol_dealloc(SQLitePrepareProtocol* self);
+
+int prepare_protocol_setup_types(void);
+
+#define UNKNOWN (-1)
+#endif
diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c
new file mode 100644
index 0000000..80b6135
--- /dev/null
+++ b/Modules/_sqlite/row.c
@@ -0,0 +1,202 @@
+/* row.c - an enhanced tuple for database rows
+ *
+ * Copyright (C) 2005-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "row.h"
+#include "cursor.h"
+#include "sqlitecompat.h"
+
+void row_dealloc(Row* self)
+{
+    Py_XDECREF(self->data);
+    Py_XDECREF(self->description);
+
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+int row_init(Row* self, PyObject* args, PyObject* kwargs)
+{
+    PyObject* data;
+    Cursor* cursor;
+
+    self->data = 0;
+    self->description = 0;
+
+    if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) {
+        return -1;
+    }
+
+    if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&CursorType)) {
+        PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument");
+        return -1;
+    }
+
+    if (!PyTuple_Check(data)) {
+        PyErr_SetString(PyExc_TypeError, "tuple required for second argument");
+        return -1;
+    }
+
+    Py_INCREF(data);
+    self->data = data;
+
+    Py_INCREF(cursor->description);
+    self->description = cursor->description;
+
+    return 0;
+}
+
+PyObject* row_subscript(Row* self, PyObject* idx)
+{
+    long _idx;
+    char* key;
+    int nitems, i;
+    char* compare_key;
+
+    char* p1;
+    char* p2;
+
+    PyObject* item;
+
+    if (PyInt_Check(idx)) {
+        _idx = PyInt_AsLong(idx);
+        item = PyTuple_GetItem(self->data, _idx);
+        Py_XINCREF(item);
+        return item;
+    } else if (PyLong_Check(idx)) {
+        _idx = PyLong_AsLong(idx);
+        item = PyTuple_GetItem(self->data, _idx);
+        Py_XINCREF(item);
+        return item;
+    } else if (PyString_Check(idx)) {
+        key = PyString_AsString(idx);
+
+        nitems = PyTuple_Size(self->description);
+
+        for (i = 0; i < nitems; i++) {
+            compare_key = PyString_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0));
+            if (!compare_key) {
+                return NULL;
+            }
+
+            p1 = key;
+            p2 = compare_key;
+
+            while (1) {
+                if ((*p1 == (char)0) || (*p2 == (char)0)) {
+                    break;
+                }
+
+                if ((*p1 | 0x20) != (*p2 | 0x20)) {
+                    break;
+                }
+
+                p1++;
+                p2++;
+            }
+
+            if ((*p1 == (char)0) && (*p2 == (char)0)) {
+                /* found item */
+                item = PyTuple_GetItem(self->data, i);
+                Py_INCREF(item);
+                return item;
+            }
+
+        }
+
+        PyErr_SetString(PyExc_IndexError, "No item with that key");
+        return NULL;
+    } else if (PySlice_Check(idx)) {
+        PyErr_SetString(PyExc_ValueError, "slices not implemented, yet");
+        return NULL;
+    } else {
+        PyErr_SetString(PyExc_IndexError, "Index must be int or string");
+        return NULL;
+    }
+}
+
+Py_ssize_t row_length(Row* self, PyObject* args, PyObject* kwargs)
+{
+    return PyTuple_GET_SIZE(self->data);
+}
+
+static int row_print(Row* self, FILE *fp, int flags)
+{
+    return (&PyTuple_Type)->tp_print(self->data, fp, flags);
+}
+
+
+PyMappingMethods row_as_mapping = {
+    /* mp_length        */ (lenfunc)row_length,
+    /* mp_subscript     */ (binaryfunc)row_subscript,
+    /* mp_ass_subscript */ (objobjargproc)0,
+};
+
+
+PyTypeObject RowType = {
+        PyObject_HEAD_INIT(NULL)
+        0,                                              /* ob_size */
+        MODULE_NAME ".Row",                             /* tp_name */
+        sizeof(Row),                                    /* tp_basicsize */
+        0,                                              /* tp_itemsize */
+        (destructor)row_dealloc,                        /* tp_dealloc */
+        (printfunc)row_print,                           /* tp_print */
+        0,                                              /* tp_getattr */
+        0,                                              /* tp_setattr */
+        0,                                              /* tp_compare */
+        0,                                              /* tp_repr */
+        0,                                              /* tp_as_number */
+        0,                                              /* tp_as_sequence */
+        0,                                              /* tp_as_mapping */
+        0,                                              /* tp_hash */
+        0,                                              /* tp_call */
+        0,                                              /* tp_str */
+        0,                                              /* tp_getattro */
+        0,                                              /* tp_setattro */
+        0,                                              /* tp_as_buffer */
+        Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,         /* tp_flags */
+        0,                                              /* tp_doc */
+        0,                                              /* tp_traverse */
+        0,                                              /* tp_clear */
+        0,                                              /* tp_richcompare */
+        0,                                              /* tp_weaklistoffset */
+        0,                                              /* tp_iter */
+        0,                                              /* tp_iternext */
+        0,                                              /* tp_methods */
+        0,                                              /* tp_members */
+        0,                                              /* tp_getset */
+        0,                                              /* tp_base */
+        0,                                              /* tp_dict */
+        0,                                              /* tp_descr_get */
+        0,                                              /* tp_descr_set */
+        0,                                              /* tp_dictoffset */
+        (initproc)row_init,                             /* tp_init */
+        0,                                              /* tp_alloc */
+        0,                                              /* tp_new */
+        0                                               /* tp_free */
+};
+
+extern int row_setup_types(void)
+{
+    RowType.tp_new = PyType_GenericNew;
+    RowType.tp_as_mapping = &row_as_mapping;
+    return PyType_Ready(&RowType);
+}
diff --git a/Modules/_sqlite/row.h b/Modules/_sqlite/row.h
new file mode 100644
index 0000000..c6e083c
--- /dev/null
+++ b/Modules/_sqlite/row.h
@@ -0,0 +1,39 @@
+/* row.h - an enhanced tuple for database rows
+ *
+ * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_ROW_H
+#define PYSQLITE_ROW_H
+#include "Python.h"
+
+typedef struct _Row
+{
+    PyObject_HEAD
+    PyObject* data;
+    PyObject* description;
+} Row;
+
+extern PyTypeObject RowType;
+
+int row_setup_types(void);
+
+#endif
diff --git a/Modules/_sqlite/sqlitecompat.h b/Modules/_sqlite/sqlitecompat.h
new file mode 100644
index 0000000..c379825
--- /dev/null
+++ b/Modules/_sqlite/sqlitecompat.h
@@ -0,0 +1,34 @@
+/* sqlitecompat.h - compatibility macros
+ *
+ * Copyright (C) 2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_COMPAT_H
+#define PYSQLITE_COMPAT_H
+
+/* define Py_ssize_t for pre-2.5 versions of Python */
+
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+typedef int (*lenfunc)(PyObject*);
+#endif
+
+#endif
diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c
new file mode 100644
index 0000000..0c93651
--- /dev/null
+++ b/Modules/_sqlite/statement.c
@@ -0,0 +1,427 @@
+/* statement.c - the statement type
+ *
+ * Copyright (C) 2005-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "statement.h"
+#include "cursor.h"
+#include "connection.h"
+#include "microprotocols.h"
+#include "prepare_protocol.h"
+#include "sqlitecompat.h"
+
+/* prototypes */
+int check_remaining_sql(const char* tail);
+
+typedef enum {
+    LINECOMMENT_1,
+    IN_LINECOMMENT,
+    COMMENTSTART_1,
+    IN_COMMENT,
+    COMMENTEND_1,
+    NORMAL
+} parse_remaining_sql_state;
+
+int statement_create(Statement* self, Connection* connection, PyObject* sql)
+{
+    const char* tail;
+    int rc;
+    PyObject* sql_str;
+    char* sql_cstr;
+
+    self->st = NULL;
+    self->in_use = 0;
+
+    if (PyString_Check(sql)) {
+        sql_str = sql;
+        Py_INCREF(sql_str);
+    } else if (PyUnicode_Check(sql)) {
+        sql_str = PyUnicode_AsUTF8String(sql);
+        if (!sql_str) {
+            rc = PYSQLITE_SQL_WRONG_TYPE;
+            return rc;
+        }
+    } else {
+        rc = PYSQLITE_SQL_WRONG_TYPE;
+        return rc;
+    }
+
+    self->sql = sql_str;
+
+    sql_cstr = PyString_AsString(sql_str);
+
+    rc = sqlite3_prepare(connection->db,
+                         sql_cstr,
+                         -1,
+                         &self->st,
+                         &tail);
+
+    self->db = connection->db;
+
+    if (rc == SQLITE_OK && check_remaining_sql(tail)) {
+        (void)sqlite3_finalize(self->st);
+        self->st = NULL;
+        rc = PYSQLITE_TOO_MUCH_SQL;
+    }
+
+    return rc;
+}
+
+int statement_bind_parameter(Statement* self, int pos, PyObject* parameter)
+{
+    int rc = SQLITE_OK;
+    long longval;
+#ifdef HAVE_LONG_LONG
+    PY_LONG_LONG longlongval;
+#endif
+    const char* buffer;
+    char* string;
+    Py_ssize_t buflen;
+    PyObject* stringval;
+
+    if (parameter == Py_None) {
+        rc = sqlite3_bind_null(self->st, pos);
+    } else if (PyInt_Check(parameter)) {
+        longval = PyInt_AsLong(parameter);
+        rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longval);
+#ifdef HAVE_LONG_LONG
+    } else if (PyLong_Check(parameter)) {
+        longlongval = PyLong_AsLongLong(parameter);
+        /* in the overflow error case, longlongval is -1, and an exception is set */
+        rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longlongval);
+#endif
+    } else if (PyFloat_Check(parameter)) {
+        rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter));
+    } else if (PyBuffer_Check(parameter)) {
+        if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) == 0) {
+            rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT);
+        } else {
+            PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
+            rc = -1;
+        }
+    } else if PyString_Check(parameter) {
+        string = PyString_AsString(parameter);
+        rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT);
+    } else if PyUnicode_Check(parameter) {
+        stringval = PyUnicode_AsUTF8String(parameter);
+        string = PyString_AsString(stringval);
+        rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT);
+        Py_DECREF(stringval);
+    } else {
+        rc = -1;
+    }
+
+    return rc;
+}
+
+void statement_bind_parameters(Statement* self, PyObject* parameters)
+{
+    PyObject* current_param;
+    PyObject* adapted;
+    const char* binding_name;
+    int i;
+    int rc;
+    int num_params_needed;
+    int num_params;
+
+    Py_BEGIN_ALLOW_THREADS
+    num_params_needed = sqlite3_bind_parameter_count(self->st);
+    Py_END_ALLOW_THREADS
+
+    if (PyDict_Check(parameters)) {
+        /* parameters passed as dictionary */
+        for (i = 1; i <= num_params_needed; i++) {
+            Py_BEGIN_ALLOW_THREADS
+            binding_name = sqlite3_bind_parameter_name(self->st, i);
+            Py_END_ALLOW_THREADS
+            if (!binding_name) {
+                PyErr_Format(ProgrammingError, "Binding %d has no name, but you supplied a dictionary (which has only names).", i);
+                return;
+            }
+
+            binding_name++; /* skip first char (the colon) */
+            current_param = PyDict_GetItemString(parameters, binding_name);
+            if (!current_param) {
+                PyErr_Format(ProgrammingError, "You did not supply a value for binding %d.", i);
+                return;
+            }
+
+            Py_INCREF(current_param);
+            adapted = microprotocols_adapt(current_param, (PyObject*)&SQLitePrepareProtocolType, NULL);
+            if (adapted) {
+                Py_DECREF(current_param);
+            } else {
+                PyErr_Clear();
+                adapted = current_param;
+            }
+
+            rc = statement_bind_parameter(self, i, adapted);
+            Py_DECREF(adapted);
+
+            if (rc != SQLITE_OK) {
+                PyErr_Format(InterfaceError, "Error binding parameter :%s - probably unsupported type.", binding_name);
+                return;
+           }
+        }
+    } else {
+        /* parameters passed as sequence */
+        num_params = PySequence_Length(parameters);
+        if (num_params != num_params_needed) {
+            PyErr_Format(ProgrammingError, "Incorrect number of bindings supplied. The current statement uses %d, and there are %d supplied.",
+                         num_params_needed, num_params);
+            return;
+        }
+        for (i = 0; i < num_params; i++) {
+            current_param = PySequence_GetItem(parameters, i);
+            if (!current_param) {
+                return;
+            }
+            adapted = microprotocols_adapt(current_param, (PyObject*)&SQLitePrepareProtocolType, NULL);
+
+            if (adapted) {
+                Py_DECREF(current_param);
+            } else {
+                PyErr_Clear();
+                adapted = current_param;
+            }
+
+            rc = statement_bind_parameter(self, i + 1, adapted);
+            Py_DECREF(adapted);
+
+            if (rc != SQLITE_OK) {
+                PyErr_Format(InterfaceError, "Error binding parameter %d - probably unsupported type.", i);
+                return;
+            }
+        }
+    }
+}
+
+int statement_recompile(Statement* self, PyObject* params)
+{
+    const char* tail;
+    int rc;
+    char* sql_cstr;
+    sqlite3_stmt* new_st;
+
+    sql_cstr = PyString_AsString(self->sql);
+
+    rc = sqlite3_prepare(self->db,
+                         sql_cstr,
+                         -1,
+                         &new_st,
+                         &tail);
+
+    if (rc == SQLITE_OK) {
+        /* The efficient sqlite3_transfer_bindings is only available in SQLite
+         * version 3.2.2 or later. For older SQLite releases, that might not
+         * even define SQLITE_VERSION_NUMBER, we do it the manual way.
+         */
+        #ifdef SQLITE_VERSION_NUMBER
+        #if SQLITE_VERSION_NUMBER >= 3002002
+        (void)sqlite3_transfer_bindings(self->st, new_st);
+        #endif
+        #else
+        statement_bind_parameters(self, params);
+        #endif
+
+        (void)sqlite3_finalize(self->st);
+        self->st = new_st;
+    }
+
+    return rc;
+}
+
+int statement_finalize(Statement* self)
+{
+    int rc;
+
+    rc = SQLITE_OK;
+    if (self->st) {
+        Py_BEGIN_ALLOW_THREADS
+        rc = sqlite3_finalize(self->st);
+        Py_END_ALLOW_THREADS
+        self->st = NULL;
+    }
+
+    self->in_use = 0;
+
+    return rc;
+}
+
+int statement_reset(Statement* self)
+{
+    int rc;
+
+    rc = SQLITE_OK;
+
+    if (self->in_use && self->st) {
+        Py_BEGIN_ALLOW_THREADS
+        rc = sqlite3_reset(self->st);
+        Py_END_ALLOW_THREADS
+
+        if (rc == SQLITE_OK) {
+            self->in_use = 0;
+        }
+    }
+
+    return rc;
+}
+
+void statement_mark_dirty(Statement* self)
+{
+    self->in_use = 1;
+}
+
+void statement_dealloc(Statement* self)
+{
+    int rc;
+
+    if (self->st) {
+        Py_BEGIN_ALLOW_THREADS
+        rc = sqlite3_finalize(self->st);
+        Py_END_ALLOW_THREADS
+    }
+
+    self->st = NULL;
+
+    Py_XDECREF(self->sql);
+
+    self->ob_type->tp_free((PyObject*)self);
+}
+
+/*
+ * Checks if there is anything left in an SQL string after SQLite compiled it.
+ * This is used to check if somebody tried to execute more than one SQL command
+ * with one execute()/executemany() command, which the DB-API and we don't
+ * allow.
+ *
+ * Returns 1 if there is more left than should be. 0 if ok.
+ */
+int check_remaining_sql(const char* tail)
+{
+    const char* pos = tail;
+
+    parse_remaining_sql_state state = NORMAL;
+
+    for (;;) {
+        switch (*pos) {
+            case 0:
+                return 0;
+            case '-':
+                if (state == NORMAL) {
+                    state  = LINECOMMENT_1;
+                } else if (state == LINECOMMENT_1) {
+                    state = IN_LINECOMMENT;
+                }
+                break;
+            case ' ':
+            case '\t':
+                break;
+            case '\n':
+            case 13:
+                if (state == IN_LINECOMMENT) {
+                    state = NORMAL;
+                }
+                break;
+            case '/':
+                if (state == NORMAL) {
+                    state = COMMENTSTART_1;
+                } else if (state == COMMENTEND_1) {
+                    state = NORMAL;
+                } else if (state == COMMENTSTART_1) {
+                    return 1;
+                }
+                break;
+            case '*':
+                if (state == NORMAL) {
+                    return 1;
+                } else if (state == LINECOMMENT_1) {
+                    return 1;
+                } else if (state == COMMENTSTART_1) {
+                    state = IN_COMMENT;
+                } else if (state == IN_COMMENT) {
+                    state = COMMENTEND_1;
+                }
+                break;
+            default:
+                if (state == COMMENTEND_1) {
+                    state = IN_COMMENT;
+                } else if (state == IN_LINECOMMENT) {
+                } else if (state == IN_COMMENT) {
+                } else {
+                    return 1;
+                }
+        }
+
+        pos++;
+    }
+
+    return 0;
+}
+
+PyTypeObject StatementType = {
+        PyObject_HEAD_INIT(NULL)
+        0,                                              /* ob_size */
+        MODULE_NAME ".Statement",                       /* tp_name */
+        sizeof(Statement),                              /* tp_basicsize */
+        0,                                              /* tp_itemsize */
+        (destructor)statement_dealloc,                  /* tp_dealloc */
+        0,                                              /* tp_print */
+        0,                                              /* tp_getattr */
+        0,                                              /* tp_setattr */
+        0,                                              /* tp_compare */
+        0,                                              /* tp_repr */
+        0,                                              /* tp_as_number */
+        0,                                              /* tp_as_sequence */
+        0,                                              /* tp_as_mapping */
+        0,                                              /* tp_hash */
+        0,                                              /* tp_call */
+        0,                                              /* tp_str */
+        0,                                              /* tp_getattro */
+        0,                                              /* tp_setattro */
+        0,                                              /* tp_as_buffer */
+        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
+        0,                                              /* tp_doc */
+        0,                                              /* tp_traverse */
+        0,                                              /* tp_clear */
+        0,                                              /* tp_richcompare */
+        0,                                              /* tp_weaklistoffset */
+        0,                                              /* tp_iter */
+        0,                                              /* tp_iternext */
+        0,                                              /* tp_methods */
+        0,                                              /* tp_members */
+        0,                                              /* tp_getset */
+        0,                                              /* tp_base */
+        0,                                              /* tp_dict */
+        0,                                              /* tp_descr_get */
+        0,                                              /* tp_descr_set */
+        0,                                              /* tp_dictoffset */
+        (initproc)0,                                    /* tp_init */
+        0,                                              /* tp_alloc */
+        0,                                              /* tp_new */
+        0                                               /* tp_free */
+};
+
+extern int statement_setup_types(void)
+{
+    StatementType.tp_new = PyType_GenericNew;
+    return PyType_Ready(&StatementType);
+}
diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h
new file mode 100644
index 0000000..e45a0fc
--- /dev/null
+++ b/Modules/_sqlite/statement.h
@@ -0,0 +1,58 @@
+/* statement.h - definitions for the statement type
+ *
+ * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_STATEMENT_H
+#define PYSQLITE_STATEMENT_H
+#include "Python.h"
+
+#include "connection.h"
+#include "sqlite3.h"
+
+#define PYSQLITE_TOO_MUCH_SQL (-100)
+#define PYSQLITE_SQL_WRONG_TYPE (-101)
+
+typedef struct
+{
+    PyObject_HEAD
+    sqlite3* db;
+    sqlite3_stmt* st;
+    PyObject* sql;
+    int in_use;
+} Statement;
+
+extern PyTypeObject StatementType;
+
+int statement_create(Statement* self, Connection* connection, PyObject* sql);
+void statement_dealloc(Statement* self);
+
+int statement_bind_parameter(Statement* self, int pos, PyObject* parameter);
+void statement_bind_parameters(Statement* self, PyObject* parameters);
+
+int statement_recompile(Statement* self, PyObject* parameters);
+int statement_finalize(Statement* self);
+int statement_reset(Statement* self);
+void statement_mark_dirty(Statement* self);
+
+int statement_setup_types(void);
+
+#endif
diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c
new file mode 100644
index 0000000..33748a6
--- /dev/null
+++ b/Modules/_sqlite/util.c
@@ -0,0 +1,96 @@
+/* util.c - various utility functions
+ *
+ * Copyright (C) 2005-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "module.h"
+#include "connection.h"
+
+int _sqlite_step_with_busyhandler(sqlite3_stmt* statement, Connection* connection
+)
+{
+    int rc;
+
+    Py_BEGIN_ALLOW_THREADS
+    rc = sqlite3_step(statement);
+    Py_END_ALLOW_THREADS
+
+    return rc;
+}
+
+/**
+ * Checks the SQLite error code and sets the appropriate DB-API exception.
+ * Returns the error code (0 means no error occured).
+ */
+int _seterror(sqlite3* db)
+{
+    int errorcode;
+
+    errorcode = sqlite3_errcode(db);
+
+    switch (errorcode)
+    {
+        case SQLITE_OK:
+            PyErr_Clear();
+            break;
+        case SQLITE_INTERNAL:
+        case SQLITE_NOTFOUND:
+            PyErr_SetString(InternalError, sqlite3_errmsg(db));
+            break;
+        case SQLITE_NOMEM:
+            (void)PyErr_NoMemory();
+            break;
+        case SQLITE_ERROR:
+        case SQLITE_PERM:
+        case SQLITE_ABORT:
+        case SQLITE_BUSY:
+        case SQLITE_LOCKED:
+        case SQLITE_READONLY:
+        case SQLITE_INTERRUPT:
+        case SQLITE_IOERR:
+        case SQLITE_FULL:
+        case SQLITE_CANTOPEN:
+        case SQLITE_PROTOCOL:
+        case SQLITE_EMPTY:
+        case SQLITE_SCHEMA:
+            PyErr_SetString(OperationalError, sqlite3_errmsg(db));
+            break;
+        case SQLITE_CORRUPT:
+            PyErr_SetString(DatabaseError, sqlite3_errmsg(db));
+            break;
+        case SQLITE_TOOBIG:
+            PyErr_SetString(DataError, sqlite3_errmsg(db));
+            break;
+        case SQLITE_CONSTRAINT:
+        case SQLITE_MISMATCH:
+            PyErr_SetString(IntegrityError, sqlite3_errmsg(db));
+            break;
+        case SQLITE_MISUSE:
+            PyErr_SetString(ProgrammingError, sqlite3_errmsg(db));
+            break;
+        default:
+            PyErr_SetString(DatabaseError, sqlite3_errmsg(db));
+            break;
+    }
+
+    return errorcode;
+}
+
diff --git a/Modules/_sqlite/util.h b/Modules/_sqlite/util.h
new file mode 100644
index 0000000..e99a4dd
--- /dev/null
+++ b/Modules/_sqlite/util.h
@@ -0,0 +1,38 @@
+/* util.h - various utility functions
+ *
+ * Copyright (C) 2005-2006 Gerhard Häring <gh@ghaering.de>
+ *
+ * This file is part of pysqlite.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef PYSQLITE_UTIL_H
+#define PYSQLITE_UTIL_H
+#include "Python.h"
+#include "pythread.h"
+#include "sqlite3.h"
+#include "connection.h"
+
+int _sqlite_step_with_busyhandler(sqlite3_stmt* statement, Connection* connection);
+
+/**
+ * Checks the SQLite error code and sets the appropriate DB-API exception.
+ * Returns the error code (0 means no error occured).
+ */
+int _seterror(sqlite3* db);
+#endif
diff --git a/Modules/_sre.c b/Modules/_sre.c
index 81223d7..4af08ed 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -275,7 +275,7 @@
             data_stack_dealloc(state);
             return SRE_ERROR_MEMORY;
         }
-        state->data_stack = stack;
+        state->data_stack = (char *)stack;
         state->data_stack_size = cursize;
     }
     return 0;
@@ -335,7 +335,7 @@
 {
     /* check if pointer is at given position */
 
-    int this, that;
+    int thisp, thatp;
 
     switch (at) {
 
@@ -362,57 +362,57 @@
     case SRE_AT_BOUNDARY:
         if (state->beginning == state->end)
             return 0;
-        that = ((void*) ptr > state->beginning) ?
+        thatp = ((void*) ptr > state->beginning) ?
             SRE_IS_WORD((int) ptr[-1]) : 0;
-        this = ((void*) ptr < state->end) ?
+        thisp = ((void*) ptr < state->end) ?
             SRE_IS_WORD((int) ptr[0]) : 0;
-        return this != that;
+        return thisp != thatp;
 
     case SRE_AT_NON_BOUNDARY:
         if (state->beginning == state->end)
             return 0;
-        that = ((void*) ptr > state->beginning) ?
+        thatp = ((void*) ptr > state->beginning) ?
             SRE_IS_WORD((int) ptr[-1]) : 0;
-        this = ((void*) ptr < state->end) ?
+        thisp = ((void*) ptr < state->end) ?
             SRE_IS_WORD((int) ptr[0]) : 0;
-        return this == that;
+        return thisp == thatp;
 
     case SRE_AT_LOC_BOUNDARY:
         if (state->beginning == state->end)
             return 0;
-        that = ((void*) ptr > state->beginning) ?
+        thatp = ((void*) ptr > state->beginning) ?
             SRE_LOC_IS_WORD((int) ptr[-1]) : 0;
-        this = ((void*) ptr < state->end) ?
+        thisp = ((void*) ptr < state->end) ?
             SRE_LOC_IS_WORD((int) ptr[0]) : 0;
-        return this != that;
+        return thisp != thatp;
 
     case SRE_AT_LOC_NON_BOUNDARY:
         if (state->beginning == state->end)
             return 0;
-        that = ((void*) ptr > state->beginning) ?
+        thatp = ((void*) ptr > state->beginning) ?
             SRE_LOC_IS_WORD((int) ptr[-1]) : 0;
-        this = ((void*) ptr < state->end) ?
+        thisp = ((void*) ptr < state->end) ?
             SRE_LOC_IS_WORD((int) ptr[0]) : 0;
-        return this == that;
+        return thisp == thatp;
 
 #if defined(HAVE_UNICODE)
     case SRE_AT_UNI_BOUNDARY:
         if (state->beginning == state->end)
             return 0;
-        that = ((void*) ptr > state->beginning) ?
+        thatp = ((void*) ptr > state->beginning) ?
             SRE_UNI_IS_WORD((int) ptr[-1]) : 0;
-        this = ((void*) ptr < state->end) ?
+        thisp = ((void*) ptr < state->end) ?
             SRE_UNI_IS_WORD((int) ptr[0]) : 0;
-        return this != that;
+        return thisp != thatp;
 
     case SRE_AT_UNI_NON_BOUNDARY:
         if (state->beginning == state->end)
             return 0;
-        that = ((void*) ptr > state->beginning) ?
+        thatp = ((void*) ptr > state->beginning) ?
             SRE_UNI_IS_WORD((int) ptr[-1]) : 0;
-        this = ((void*) ptr < state->end) ?
+        thisp = ((void*) ptr < state->end) ?
             SRE_UNI_IS_WORD((int) ptr[0]) : 0;
-        return this == that;
+        return thisp == thatp;
 #endif
 
     }
@@ -516,8 +516,8 @@
 SRE_COUNT(SRE_STATE* state, SRE_CODE* pattern, int maxcount)
 {
     SRE_CODE chr;
-    SRE_CHAR* ptr = state->ptr;
-    SRE_CHAR* end = state->end;
+    SRE_CHAR* ptr = (SRE_CHAR *)state->ptr;
+    SRE_CHAR* end = (SRE_CHAR *)state->end;
     int i;
 
     /* adjust end */
@@ -803,7 +803,7 @@
 LOCAL(int)
 SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern)
 {
-    SRE_CHAR* end = state->end;
+    SRE_CHAR* end = (SRE_CHAR *)state->end;
     int alloc_pos, ctx_pos = -1;
     int i, ret = 0;
     int jump;
@@ -821,7 +821,7 @@
 
 entrance:
 
-    ctx->ptr = state->ptr;
+    ctx->ptr = (SRE_CHAR *)state->ptr;
 
     if (ctx->pattern[0] == SRE_OP_INFO) {
         /* optimization info block */
@@ -1477,8 +1477,8 @@
 LOCAL(int)
 SRE_SEARCH(SRE_STATE* state, SRE_CODE* pattern)
 {
-    SRE_CHAR* ptr = state->start;
-    SRE_CHAR* end = state->end;
+    SRE_CHAR* ptr = (SRE_CHAR *)state->start;
+    SRE_CHAR* end = (SRE_CHAR *)state->end;
     int status = 0;
     int prefix_len = 0;
     int prefix_skip = 0;
@@ -1524,7 +1524,7 @@
         /* pattern starts with a known prefix.  use the overlap
            table to skip forward as fast as we possibly can */
         int i = 0;
-        end = state->end;
+        end = (SRE_CHAR *)state->end;
         while (ptr < end) {
             for (;;) {
                 if ((SRE_CODE) ptr[0] != prefix[i]) {
@@ -1559,7 +1559,7 @@
         /* pattern starts with a literal character.  this is used
            for short prefixes, and if fast search is disabled */
         SRE_CODE chr = pattern[1];
-        end = state->end;
+        end = (SRE_CHAR *)state->end;
         for (;;) {
             while (ptr < end && (SRE_CODE) ptr[0] != chr)
                 ptr++;
@@ -1576,7 +1576,7 @@
         }
     } else if (charset) {
         /* pattern starts with a character from a known set */
-        end = state->end;
+        end = (SRE_CHAR *)state->end;
         for (;;) {
             while (ptr < end && !SRE_CHARSET(charset, ptr[0]))
                 ptr++;
@@ -1619,72 +1619,8 @@
 /* factories and destructors */
 
 /* see sre.h for object declarations */
-
-static PyTypeObject Pattern_Type;
-static PyTypeObject Match_Type;
-static PyTypeObject Scanner_Type;
-
-static PyObject *
-_compile(PyObject* self_, PyObject* args)
-{
-    /* "compile" pattern descriptor to pattern object */
-
-    PatternObject* self;
-    int i, n;
-
-    PyObject* pattern;
-    int flags = 0;
-    PyObject* code;
-    int groups = 0;
-    PyObject* groupindex = NULL;
-    PyObject* indexgroup = NULL;
-    if (!PyArg_ParseTuple(args, "OiO!|iOO", &pattern, &flags,
-                          &PyList_Type, &code, &groups,
-                          &groupindex, &indexgroup))
-        return NULL;
-
-    n = PyList_GET_SIZE(code);
-
-    self = PyObject_NEW_VAR(PatternObject, &Pattern_Type, n);
-    if (!self)
-        return NULL;
-
-    self->codesize = n;
-
-    for (i = 0; i < n; i++) {
-        PyObject *o = PyList_GET_ITEM(code, i);
-        unsigned long value = PyInt_Check(o) ? (unsigned long)PyInt_AsLong(o)
-                                              : PyLong_AsUnsignedLong(o);
-        self->code[i] = (SRE_CODE) value;
-        if ((unsigned long) self->code[i] != value) {
-            PyErr_SetString(PyExc_OverflowError,
-                            "regular expression code size limit exceeded");
-            break;
-        }
-    }
-
-    if (PyErr_Occurred()) {
-        PyObject_DEL(self);
-        return NULL;
-    }
-
-    Py_INCREF(pattern);
-    self->pattern = pattern;
-
-    self->flags = flags;
-
-    self->groups = groups;
-
-    Py_XINCREF(groupindex);
-    self->groupindex = groupindex;
-
-    Py_XINCREF(indexgroup);
-    self->indexgroup = indexgroup;
-
-    self->weakreflist = NULL;
-
-    return (PyObject*) self;
-}
+static PyObject*pattern_new_match(PatternObject*, SRE_STATE*, int);
+static PyObject*pattern_scanner(PatternObject*, PyObject*);
 
 static PyObject *
 sre_codesize(PyObject* self, PyObject* args)
@@ -1900,98 +1836,6 @@
     }
 }
 
-static PyObject*
-pattern_new_match(PatternObject* pattern, SRE_STATE* state, int status)
-{
-    /* create match object (from state object) */
-
-    MatchObject* match;
-    int i, j;
-    char* base;
-    int n;
-
-    if (status > 0) {
-
-        /* create match object (with room for extra group marks) */
-        match = PyObject_NEW_VAR(MatchObject, &Match_Type,
-                                 2*(pattern->groups+1));
-        if (!match)
-            return NULL;
-
-        Py_INCREF(pattern);
-        match->pattern = pattern;
-
-        Py_INCREF(state->string);
-        match->string = state->string;
-
-        match->regs = NULL;
-        match->groups = pattern->groups+1;
-
-        /* fill in group slices */
-
-        base = (char*) state->beginning;
-        n = state->charsize;
-
-        match->mark[0] = ((char*) state->start - base) / n;
-        match->mark[1] = ((char*) state->ptr - base) / n;
-
-        for (i = j = 0; i < pattern->groups; i++, j+=2)
-            if (j+1 <= state->lastmark && state->mark[j] && state->mark[j+1]) {
-                match->mark[j+2] = ((char*) state->mark[j] - base) / n;
-                match->mark[j+3] = ((char*) state->mark[j+1] - base) / n;
-            } else
-                match->mark[j+2] = match->mark[j+3] = -1; /* undefined */
-
-        match->pos = state->pos;
-        match->endpos = state->endpos;
-
-        match->lastindex = state->lastindex;
-
-        return (PyObject*) match;
-
-    } else if (status == 0) {
-
-        /* no match */
-        Py_INCREF(Py_None);
-        return Py_None;
-
-    }
-
-    /* internal error */
-    pattern_error(status);
-    return NULL;
-}
-
-static PyObject*
-pattern_scanner(PatternObject* pattern, PyObject* args)
-{
-    /* create search state object */
-
-    ScannerObject* self;
-
-    PyObject* string;
-    int start = 0;
-    int end = INT_MAX;
-    if (!PyArg_ParseTuple(args, "O|ii:scanner", &string, &start, &end))
-        return NULL;
-
-    /* create scanner object */
-    self = PyObject_NEW(ScannerObject, &Scanner_Type);
-    if (!self)
-        return NULL;
-
-    string = state_init(&self->state, pattern, string, start, end);
-    if (!string) {
-        PyObject_DEL(self);
-        return NULL;
-    }
-
-    Py_INCREF(pattern);
-    self->pattern = (PyObject*) pattern;
-
-    return (PyObject*) self;
-}
-
 static void
 pattern_dealloc(PatternObject* self)
 {
@@ -2414,7 +2258,7 @@
 }
 
 static PyObject*
-pattern_subx(PatternObject* self, PyObject* template, PyObject* string,
+pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string,
              int count, int subn)
 {
     SRE_STATE state;
@@ -2429,21 +2273,21 @@
     int i, b, e;
     int filter_is_callable;
 
-    if (PyCallable_Check(template)) {
+    if (PyCallable_Check(ptemplate)) {
         /* sub/subn takes either a function or a template */
-        filter = template;
+        filter = ptemplate;
         Py_INCREF(filter);
         filter_is_callable = 1;
     } else {
         /* if not callable, check if it's a literal string */
         int literal;
-        ptr = getstring(template, &n, &b);
+        ptr = getstring(ptemplate, &n, &b);
         if (ptr) {
             if (b == 1) {
-                literal = sre_literal_template(ptr, n);
+		    literal = sre_literal_template((unsigned char *)ptr, n);
             } else {
 #if defined(HAVE_UNICODE)
-                literal = sre_uliteral_template(ptr, n);
+		    literal = sre_uliteral_template((Py_UNICODE *)ptr, n);
 #endif
             }
         } else {
@@ -2451,14 +2295,14 @@
             literal = 0;
         }
         if (literal) {
-            filter = template;
+            filter = ptemplate;
             Py_INCREF(filter);
             filter_is_callable = 0;
         } else {
             /* not a literal; hand it over to the template compiler */
             filter = call(
                 SRE_PY_MODULE, "_subx",
-                PyTuple_Pack(2, self, template)
+                PyTuple_Pack(2, self, ptemplate)
                 );
             if (!filter)
                 return NULL;
@@ -2597,29 +2441,29 @@
 static PyObject*
 pattern_sub(PatternObject* self, PyObject* args, PyObject* kw)
 {
-    PyObject* template;
+    PyObject* ptemplate;
     PyObject* string;
     int count = 0;
     static char* kwlist[] = { "repl", "string", "count", NULL };
     if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|i:sub", kwlist,
-                                     &template, &string, &count))
+                                     &ptemplate, &string, &count))
         return NULL;
 
-    return pattern_subx(self, template, string, count, 0);
+    return pattern_subx(self, ptemplate, string, count, 0);
 }
 
 static PyObject*
 pattern_subn(PatternObject* self, PyObject* args, PyObject* kw)
 {
-    PyObject* template;
+    PyObject* ptemplate;
     PyObject* string;
     int count = 0;
     static char* kwlist[] = { "repl", "string", "count", NULL };
     if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|i:subn", kwlist,
-                                     &template, &string, &count))
+                                     &ptemplate, &string, &count))
         return NULL;
 
-    return pattern_subx(self, template, string, count, 1);
+    return pattern_subx(self, ptemplate, string, count, 1);
 }
 
 static PyObject*
@@ -2799,6 +2643,68 @@
     offsetof(PatternObject, weakreflist),	/* tp_weaklistoffset */
 };
 
+static PyObject *
+_compile(PyObject* self_, PyObject* args)
+{
+    /* "compile" pattern descriptor to pattern object */
+
+    PatternObject* self;
+    int i, n;
+
+    PyObject* pattern;
+    int flags = 0;
+    PyObject* code;
+    int groups = 0;
+    PyObject* groupindex = NULL;
+    PyObject* indexgroup = NULL;
+    if (!PyArg_ParseTuple(args, "OiO!|iOO", &pattern, &flags,
+                          &PyList_Type, &code, &groups,
+                          &groupindex, &indexgroup))
+        return NULL;
+
+    n = PyList_GET_SIZE(code);
+
+    self = PyObject_NEW_VAR(PatternObject, &Pattern_Type, n);
+    if (!self)
+        return NULL;
+
+    self->codesize = n;
+
+    for (i = 0; i < n; i++) {
+        PyObject *o = PyList_GET_ITEM(code, i);
+        unsigned long value = PyInt_Check(o) ? (unsigned long)PyInt_AsLong(o)
+                                              : PyLong_AsUnsignedLong(o);
+        self->code[i] = (SRE_CODE) value;
+        if ((unsigned long) self->code[i] != value) {
+            PyErr_SetString(PyExc_OverflowError,
+                            "regular expression code size limit exceeded");
+            break;
+        }
+    }
+
+    if (PyErr_Occurred()) {
+        PyObject_DEL(self);
+        return NULL;
+    }
+
+    Py_INCREF(pattern);
+    self->pattern = pattern;
+
+    self->flags = flags;
+
+    self->groups = groups;
+
+    Py_XINCREF(groupindex);
+    self->groupindex = groupindex;
+
+    Py_XINCREF(indexgroup);
+    self->indexgroup = indexgroup;
+
+    self->weakreflist = NULL;
+
+    return (PyObject*) self;
+}
+
 /* -------------------------------------------------------------------- */
 /* match methods */
 
@@ -2868,14 +2774,14 @@
 static PyObject*
 match_expand(MatchObject* self, PyObject* args)
 {
-    PyObject* template;
-    if (!PyArg_ParseTuple(args, "O:expand", &template))
+    PyObject* ptemplate;
+    if (!PyArg_ParseTuple(args, "O:expand", &ptemplate))
         return NULL;
 
     /* delegate to Python code */
     return call(
         SRE_PY_MODULE, "_expand",
-        PyTuple_Pack(3, self->pattern, self, template)
+        PyTuple_Pack(3, self->pattern, self, ptemplate)
         );
 }
 
@@ -3262,6 +3168,69 @@
     (getattrfunc)match_getattr /*tp_getattr*/
 };
 
+static PyObject*
+pattern_new_match(PatternObject* pattern, SRE_STATE* state, int status)
+{
+    /* create match object (from state object) */
+
+    MatchObject* match;
+    int i, j;
+    char* base;
+    int n;
+
+    if (status > 0) {
+
+        /* create match object (with room for extra group marks) */
+        match = PyObject_NEW_VAR(MatchObject, &Match_Type,
+                                 2*(pattern->groups+1));
+        if (!match)
+            return NULL;
+
+        Py_INCREF(pattern);
+        match->pattern = pattern;
+
+        Py_INCREF(state->string);
+        match->string = state->string;
+
+        match->regs = NULL;
+        match->groups = pattern->groups+1;
+
+        /* fill in group slices */
+
+        base = (char*) state->beginning;
+        n = state->charsize;
+
+        match->mark[0] = ((char*) state->start - base) / n;
+        match->mark[1] = ((char*) state->ptr - base) / n;
+
+        for (i = j = 0; i < pattern->groups; i++, j+=2)
+            if (j+1 <= state->lastmark && state->mark[j] && state->mark[j+1]) {
+                match->mark[j+2] = ((char*) state->mark[j] - base) / n;
+                match->mark[j+3] = ((char*) state->mark[j+1] - base) / n;
+            } else
+                match->mark[j+2] = match->mark[j+3] = -1; /* undefined */
+
+        match->pos = state->pos;
+        match->endpos = state->endpos;
+
+        match->lastindex = state->lastindex;
+
+        return (PyObject*) match;
+
+    } else if (status == 0) {
+
+        /* no match */
+        Py_INCREF(Py_None);
+        return Py_None;
+
+    }
+
+    /* internal error */
+    pattern_error(status);
+    return NULL;
+}
+
+
 /* -------------------------------------------------------------------- */
 /* scanner methods (experimental) */
 
@@ -3372,6 +3341,36 @@
     (getattrfunc)scanner_getattr, /*tp_getattr*/
 };
 
+static PyObject*
+pattern_scanner(PatternObject* pattern, PyObject* args)
+{
+    /* create search state object */
+
+    ScannerObject* self;
+
+    PyObject* string;
+    int start = 0;
+    int end = INT_MAX;
+    if (!PyArg_ParseTuple(args, "O|ii:scanner", &string, &start, &end))
+        return NULL;
+
+    /* create scanner object */
+    self = PyObject_NEW(ScannerObject, &Scanner_Type);
+    if (!self)
+        return NULL;
+
+    string = state_init(&self->state, pattern, string, start, end);
+    if (!string) {
+        PyObject_DEL(self);
+        return NULL;
+    }
+
+    Py_INCREF(pattern);
+    self->pattern = (PyObject*) pattern;
+
+    return (PyObject*) self;
+}
+
 static PyMethodDef _functions[] = {
     {"compile", _compile, METH_VARARGS},
     {"getcodesize", sre_codesize, METH_VARARGS},
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 5f541f5..4c0da6f 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -55,7 +55,6 @@
 	SSL_CTX* 	ctx;
 	SSL*     	ssl;
 	X509*    	server_cert;
-	BIO*		sbio;
 	char    	server[X509_NAME_MAXLEN];
 	char		issuer[X509_NAME_MAXLEN];
 
@@ -474,15 +473,22 @@
 
 	if (!(buf = PyString_FromStringAndSize((char *) 0, len)))
 		return NULL;
+	
+	/* first check if there are bytes ready to be read */
+	Py_BEGIN_ALLOW_THREADS
+	count = SSL_pending(self->ssl);
+	Py_END_ALLOW_THREADS
 
-	sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
-	if (sockstate == SOCKET_HAS_TIMED_OUT) {
-		PyErr_SetString(PySSLErrorObject, "The read operation timed out");
-		Py_DECREF(buf);
-		return NULL;
-	} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
-		PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
-		return NULL;
+	if (!count) {
+		sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
+		if (sockstate == SOCKET_HAS_TIMED_OUT) {
+			PyErr_SetString(PySSLErrorObject, "The read operation timed out");
+			Py_DECREF(buf);
+			return NULL;
+		} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
+			PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
+			return NULL;
+		}
 	}
 	do {
 		err = 0;
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 6d8ea3c..e8881dc 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -10,7 +10,6 @@
 #ifdef WITH_THREAD
 #include "pythread.h"
 #endif /* WITH_THREAD */
-
 static PyObject *TestError;	/* set to exception object in init */
 
 /* Raise TestError with test_name + ": " + msg, and return NULL. */
@@ -235,7 +234,7 @@
 #include "testcapi_long.h"
 
 static PyObject *
-test_longlong_api(PyObject* self)
+test_longlong_api(PyObject* self, PyObject *args)
 {
 	return TESTNAME(raise_test_longlong_error);
 }
@@ -361,6 +360,15 @@
 	return PyLong_FromLong(value);
 }
 
+static PyObject *
+getargs_n(PyObject *self, PyObject *args)
+{
+	Py_ssize_t value;
+	if (!PyArg_ParseTuple(args, "n", &value))
+	return NULL;
+	return PyInt_FromSsize_t(value);
+}
+
 #ifdef HAVE_LONG_LONG
 static PyObject *
 getargs_L(PyObject *self, PyObject *args)
@@ -405,7 +413,7 @@
 
         PyTuple_SET_ITEM(tuple, 0, num);
 
-        value = -1;
+        value = 0;
         if (PyArg_ParseTuple(tuple, "k:test_k_code", &value) < 0)
         	return NULL;
         if (value != ULONG_MAX)
@@ -424,7 +432,7 @@
 
         PyTuple_SET_ITEM(tuple, 0, num);
 
-	value = -1;
+	value = 0;
         if (PyArg_ParseTuple(tuple, "k:test_k_code", &value) < 0)
         	return NULL;
         if (value != (unsigned long)-0x42)
@@ -478,6 +486,26 @@
 	return Py_None;
 }
 
+static
+PyObject *codec_incrementalencoder(PyObject *self, PyObject *args)
+{
+	const char *encoding, *errors = NULL;
+	if (!PyArg_ParseTuple(args, "s|s:test_incrementalencoder",
+			      &encoding, &errors))
+		return NULL;
+	return PyCodec_IncrementalEncoder(encoding, errors);
+}
+
+static
+PyObject *codec_incrementaldecoder(PyObject *self, PyObject *args)
+{
+	const char *encoding, *errors = NULL;
+	if (!PyArg_ParseTuple(args, "s|s:test_incrementaldecoder",
+			      &encoding, &errors))
+		return NULL;
+	return PyCodec_IncrementalDecoder(encoding, errors);
+}
+
 #endif
 
 /* Simple test of _PyLong_NumBits and _PyLong_Sign. */
@@ -563,7 +591,17 @@
 
 #ifdef WITH_THREAD
 
-void _make_call(void *callable)
+/* test_thread_state spawns a thread of its own, and that thread releases
+ * `thread_done` when it's finished.  The driver code has to know when the
+ * thread finishes, because the thread uses a PyObject (the callable) that
+ * may go away when the driver finishes.  The former lack of this explicit
+ * synchronization caused rare segfaults, so rare that they were seen only
+ * on a Mac buildbot (although they were possible on any box).
+ */
+static PyThread_type_lock thread_done = NULL;
+
+static void
+_make_call(void *callable)
 {
 	PyObject *rc;
 	PyGILState_STATE s = PyGILState_Ensure();
@@ -572,32 +610,53 @@
 	PyGILState_Release(s);
 }
 
+/* Same thing, but releases `thread_done` when it returns.  This variant
+ * should be called only from threads spawned by test_thread_state().
+ */
+static void
+_make_call_from_thread(void *callable)
+{
+	_make_call(callable);
+	PyThread_release_lock(thread_done);
+}
+
 static PyObject *
 test_thread_state(PyObject *self, PyObject *args)
 {
 	PyObject *fn;
+
 	if (!PyArg_ParseTuple(args, "O:test_thread_state", &fn))
 		return NULL;
-	/* Ensure Python is setup for threading */
+
+	/* Ensure Python is set up for threading */
 	PyEval_InitThreads();
-	/* Start a new thread for our callback. */
-	PyThread_start_new_thread( _make_call, fn);
+	thread_done = PyThread_allocate_lock();
+	if (thread_done == NULL)
+		return PyErr_NoMemory();
+	PyThread_acquire_lock(thread_done, 1);
+
+	/* Start a new thread with our callback. */
+	PyThread_start_new_thread(_make_call_from_thread, fn);
 	/* Make the callback with the thread lock held by this thread */
 	_make_call(fn);
 	/* Do it all again, but this time with the thread-lock released */
 	Py_BEGIN_ALLOW_THREADS
 	_make_call(fn);
+	PyThread_acquire_lock(thread_done, 1);  /* wait for thread to finish */
 	Py_END_ALLOW_THREADS
+
 	/* And once more with and without a thread
-	   XXX - should use a lock and work out exactly what we are trying 
-	   to test <wink> 
+	   XXX - should use a lock and work out exactly what we are trying
+	   to test <wink>
 	*/
 	Py_BEGIN_ALLOW_THREADS
-	PyThread_start_new_thread( _make_call, fn);
+	PyThread_start_new_thread(_make_call_from_thread, fn);
 	_make_call(fn);
+	PyThread_acquire_lock(thread_done, 1);  /* wait for thread to finish */
 	Py_END_ALLOW_THREADS
-	Py_INCREF(Py_None);
-	return Py_None;
+
+	PyThread_free_lock(thread_done);
+	Py_RETURN_NONE;
 }
 #endif
 
@@ -611,24 +670,29 @@
 	{"test_k_code",		(PyCFunction)test_k_code,	 METH_NOARGS},
 	{"test_null_strings",	(PyCFunction)test_null_strings,	 METH_NOARGS},
 
-	{"getargs_b",		(PyCFunction)getargs_b,		 METH_VARARGS},
-	{"getargs_B",		(PyCFunction)getargs_B,		 METH_VARARGS},
-	{"getargs_H",		(PyCFunction)getargs_H,		 METH_VARARGS},
-	{"getargs_I",		(PyCFunction)getargs_I,		 METH_VARARGS},
-	{"getargs_k",		(PyCFunction)getargs_k,		 METH_VARARGS},
-	{"getargs_i",		(PyCFunction)getargs_i,		 METH_VARARGS},
-	{"getargs_l",		(PyCFunction)getargs_l,		 METH_VARARGS},
+	{"getargs_b",		getargs_b,			 METH_VARARGS},
+	{"getargs_B",		getargs_B,			 METH_VARARGS},
+	{"getargs_H",		getargs_H,			 METH_VARARGS},
+	{"getargs_I",		getargs_I,			 METH_VARARGS},
+	{"getargs_k",		getargs_k,			 METH_VARARGS},
+	{"getargs_i",		getargs_i,			 METH_VARARGS},
+	{"getargs_l",		getargs_l,			 METH_VARARGS},
+	{"getargs_n",		getargs_n, 			 METH_VARARGS},
 #ifdef HAVE_LONG_LONG
-	{"getargs_L",		(PyCFunction)getargs_L,		 METH_VARARGS},
-	{"getargs_K",		(PyCFunction)getargs_K,		 METH_VARARGS},
-	{"test_longlong_api",	(PyCFunction)test_longlong_api,	 METH_NOARGS},
+	{"getargs_L",		getargs_L,			 METH_VARARGS},
+	{"getargs_K",		getargs_K,			 METH_VARARGS},
+	{"test_longlong_api",	test_longlong_api,		 METH_NOARGS},
 	{"test_L_code",		(PyCFunction)test_L_code,	 METH_NOARGS},
+	{"codec_incrementalencoder",
+	 (PyCFunction)codec_incrementalencoder,	 METH_VARARGS},
+	{"codec_incrementaldecoder",
+	 (PyCFunction)codec_incrementaldecoder,	 METH_VARARGS},
 #endif
 #ifdef Py_USING_UNICODE
 	{"test_u_code",		(PyCFunction)test_u_code,	 METH_NOARGS},
 #endif
 #ifdef WITH_THREAD
-	{"_test_thread_state", (PyCFunction)test_thread_state, METH_VARARGS},
+	{"_test_thread_state",  test_thread_state, 		 METH_VARARGS},
 #endif
 	{NULL, NULL} /* sentinel */
 };
@@ -650,8 +714,10 @@
 	PyModule_AddObject(m, "ULONG_MAX", PyLong_FromUnsignedLong(ULONG_MAX));
 	PyModule_AddObject(m, "INT_MIN", PyInt_FromLong(INT_MIN));
 	PyModule_AddObject(m, "LONG_MIN", PyInt_FromLong(LONG_MIN));
+	PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyInt_FromSsize_t(PY_SSIZE_T_MIN));
 	PyModule_AddObject(m, "INT_MAX", PyInt_FromLong(INT_MAX));
 	PyModule_AddObject(m, "LONG_MAX", PyInt_FromLong(LONG_MAX));
+	PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyInt_FromSsize_t(PY_SSIZE_T_MAX));
 
 	TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
 	Py_INCREF(TestError);
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index e8efaa7..c17b6c6 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -647,7 +647,7 @@
 
 	strcpy(argv0, className);
 	if (isupper(Py_CHARMASK(argv0[0])))
-		argv0[0] = tolower(argv0[0]);
+		argv0[0] = tolower(Py_CHARMASK(argv0[0]));
 	Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
 	ckfree(argv0);
 
diff --git a/Modules/almodule.c b/Modules/almodule.c
index 5254fca..fbeb13a 100644
--- a/Modules/almodule.c
+++ b/Modules/almodule.c
@@ -1482,7 +1482,8 @@
 	}
 	if (alGetParams(resource, pvs, npvs) < 0)
 		goto error;
-	v = PyList_New(npvs);
+	if (!(v = PyList_New(npvs)))
+		goto error;
 	for (i = 0; i < npvs; i++) {
 		if (pvs[i].sizeOut < 0) {
 			char buf[32];
@@ -1692,6 +1693,7 @@
 	if (alGetParamInfo(res, param, &pinfo) < 0)
 		return NULL;
 	v = PyDict_New();
+	if (!v) return NULL;
 
 	item = PyInt_FromLong((long) pinfo.resource);
 	PyDict_SetItemString(v, "resource", item);
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 1650ff2..52a7f5e 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -186,7 +186,8 @@
 	if (!PyArg_Parse(v, "u#;array item must be unicode character", &p, &len))
 		return -1;
 	if (len != 1) {
-		PyErr_SetString(PyExc_TypeError, "array item must be unicode character");
+		PyErr_SetString(PyExc_TypeError,
+				"array item must be unicode character");
 		return -1;
 	}
 	if (i >= 0)
@@ -1163,7 +1164,7 @@
 	register char *p, *q;
 	/* little buffer to hold items while swapping */
 	char tmp[256];	/* 8 is probably enough -- but why skimp */
-	assert(itemsize <= sizeof(tmp));
+	assert((size_t)itemsize <= sizeof(tmp));
 
 	if (self->ob_size > 1) {
 		for (p = self->ob_item,
@@ -1673,7 +1674,8 @@
 			}
 
 			self->ob_size -= slicelength;
-			self->ob_item = PyMem_REALLOC(self->ob_item, itemsize*self->ob_size);
+			self->ob_item = (char *)PyMem_REALLOC(self->ob_item,
+							      itemsize*self->ob_size);
 			self->allocated = self->ob_size;
 
 			return 0;
@@ -1865,7 +1867,7 @@
 				if (n > 0) {
 					arrayobject *self = (arrayobject *)a;
 					char *item = self->ob_item;
-					item = PyMem_Realloc(item, n);
+					item = (char *)PyMem_Realloc(item, n);
 					if (item == NULL) {
 						PyErr_NoMemory();
 						Py_DECREF(a);
@@ -2060,8 +2062,7 @@
 static int
 arrayiter_traverse(arrayiterobject *it, visitproc visit, void *arg)
 {
-	if (it->ao != NULL)
-		return visit((PyObject *)(it->ao), arg);
+	Py_VISIT(it->ao);
 	return 0;
 }
 
diff --git a/Modules/audioop.c b/Modules/audioop.c
index beeacd3..ed70cdf 100644
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -15,6 +15,8 @@
 #endif
 #endif
 
+typedef short PyInt16;
+
 #if defined(__CHAR_UNSIGNED__)
 #if defined(signed)
 /* This module currently does not work on systems where only unsigned
@@ -22,122 +24,267 @@
 #endif
 #endif
 
-/* Code shamelessly stolen from sox,
+/* Code shamelessly stolen from sox, 12.17.7, g711.c
 ** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
 
-#define MINLIN -32768
-#define MAXLIN 32767
-#define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; \
-                        else if ( x > MAXLIN ) x = MAXLIN; \
-                      } while ( 0 )
-
-static unsigned char st_linear_to_ulaw(int sample);
-
-/*
-** This macro converts from ulaw to 16 bit linear, faster.
-**
-** Jef Poskanzer
-** 23 October 1989
-**
-** Input: 8 bit ulaw sample
-** Output: signed 16 bit linear sample
-*/
-#define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
-
-static int ulaw_table[256] = {
-	-32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
-	-23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
-	-15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
-	-11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
-	-7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
-	-5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
-	-3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
-	-2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
-	-1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
-	-1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
-	-876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
-	-620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
-	-372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
-	-244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
-	-120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
-	-56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
-	32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
-	23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
-	15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
-	11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
-	7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
-	5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
-	3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
-	2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
-	1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
-	1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
-	876,    844,    812,    780,    748,    716,    684,    652,
-	620,    588,    556,    524,    492,    460,    428,    396,
-	372,    356,    340,    324,    308,    292,    276,    260,
-	244,    228,    212,    196,    180,    164,    148,    132,
-	120,    112,    104,     96,     88,     80,     72,     64,
-	56,     48,     40,     32,     24,     16,      8,      0 };
-
-/* #define ZEROTRAP */   /* turn on the trap as per the MIL-STD */
+/* From g711.c:
+ *
+ * December 30, 1994:
+ * Functions linear2alaw, linear2ulaw have been updated to correctly
+ * convert unquantized 16 bit values.
+ * Tables for direct u- to A-law and A- to u-law conversions have been
+ * corrected.
+ * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
+ * bli@cpk.auc.dk
+ *
+ */
 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
 #define CLIP 32635
+#define SIGN_BIT        (0x80)          /* Sign bit for a A-law byte. */
+#define QUANT_MASK      (0xf)           /* Quantization field mask. */
+#define SEG_SHIFT       (4)             /* Left shift for segment number. */
+#define SEG_MASK        (0x70)          /* Segment field mask. */
 
-static unsigned char
-st_linear_to_ulaw(int sample)
+static PyInt16 seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
+                              0x1FF, 0x3FF, 0x7FF, 0xFFF};
+static PyInt16 seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
+                              0x3FF, 0x7FF, 0xFFF, 0x1FFF};
+
+static PyInt16
+search(PyInt16 val, PyInt16 *table, int size)
 {
-	static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
-				   4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-				   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-				   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-				   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-				   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-				   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-				   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-				   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-				   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-				   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-				   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-				   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-				   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-				   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-				   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
-	int sign, exponent, mantissa;
-	unsigned char ulawbyte;
+        int i;
 
-	/* Get the sample into sign-magnitude. */
-	sign = (sample >> 8) & 0x80;		/* set aside the sign */
-	if ( sign != 0 ) sample = -sample;	/* get magnitude */
-	if ( sample > CLIP ) sample = CLIP;	/* clip the magnitude */
+        for (i = 0; i < size; i++) {
+                if (val <= *table++)
+                        return (i);
+        }
+        return (size);
+}
+#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
+#define st_alaw2linear16(uc) (_st_alaw2linear16[uc])
 
-	/* Convert from 16 bit linear to ulaw. */
-	sample = sample + BIAS;
-	exponent = exp_lut[( sample >> 7 ) & 0xFF];
-	mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
-	ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
-#ifdef ZEROTRAP
-	if ( ulawbyte == 0 ) ulawbyte = 0x02;	/* optional CCITT trap */
-#endif
+static PyInt16 _st_ulaw2linear16[256] = {
+    -32124,  -31100,  -30076,  -29052,  -28028,  -27004,  -25980,
+    -24956,  -23932,  -22908,  -21884,  -20860,  -19836,  -18812,
+    -17788,  -16764,  -15996,  -15484,  -14972,  -14460,  -13948,
+    -13436,  -12924,  -12412,  -11900,  -11388,  -10876,  -10364,
+     -9852,   -9340,   -8828,   -8316,   -7932,   -7676,   -7420,
+     -7164,   -6908,   -6652,   -6396,   -6140,   -5884,   -5628,
+     -5372,   -5116,   -4860,   -4604,   -4348,   -4092,   -3900,
+     -3772,   -3644,   -3516,   -3388,   -3260,   -3132,   -3004,
+     -2876,   -2748,   -2620,   -2492,   -2364,   -2236,   -2108,
+     -1980,   -1884,   -1820,   -1756,   -1692,   -1628,   -1564,
+     -1500,   -1436,   -1372,   -1308,   -1244,   -1180,   -1116,
+     -1052,    -988,    -924,    -876,    -844,    -812,    -780,
+      -748,    -716,    -684,    -652,    -620,    -588,    -556,
+      -524,    -492,    -460,    -428,    -396,    -372,    -356,
+      -340,    -324,    -308,    -292,    -276,    -260,    -244,
+      -228,    -212,    -196,    -180,    -164,    -148,    -132,
+      -120,    -112,    -104,     -96,     -88,     -80,     -72,
+       -64,     -56,     -48,     -40,     -32,     -24,     -16,
+        -8,       0,   32124,   31100,   30076,   29052,   28028,
+     27004,   25980,   24956,   23932,   22908,   21884,   20860,
+     19836,   18812,   17788,   16764,   15996,   15484,   14972,
+     14460,   13948,   13436,   12924,   12412,   11900,   11388,
+     10876,   10364,    9852,    9340,    8828,    8316,    7932,
+      7676,    7420,    7164,    6908,    6652,    6396,    6140,
+      5884,    5628,    5372,    5116,    4860,    4604,    4348,
+      4092,    3900,    3772,    3644,    3516,    3388,    3260,
+      3132,    3004,    2876,    2748,    2620,    2492,    2364,
+      2236,    2108,    1980,    1884,    1820,    1756,    1692,
+      1628,    1564,    1500,    1436,    1372,    1308,    1244,
+      1180,    1116,    1052,     988,     924,     876,     844,
+       812,     780,     748,     716,     684,     652,     620,
+       588,     556,     524,     492,     460,     428,     396,
+       372,     356,     340,     324,     308,     292,     276,
+       260,     244,     228,     212,     196,     180,     164,
+       148,     132,     120,     112,     104,      96,      88,
+        80,      72,      64,      56,      48,      40,      32,
+        24,      16,       8,       0
+};
 
-	return ulawbyte;
+/*
+ * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
+ * stored in a unsigned char.  This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 14-bits.
+ *
+ * In order to simplify the encoding process, the original linear magnitude
+ * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
+ * (33 - 8191). The result can be seen in the following encoding table:
+ *
+ *      Biased Linear Input Code        Compressed Code
+ *      ------------------------        ---------------
+ *      00000001wxyza                   000wxyz
+ *      0000001wxyzab                   001wxyz
+ *      000001wxyzabc                   010wxyz
+ *      00001wxyzabcd                   011wxyz
+ *      0001wxyzabcde                   100wxyz
+ *      001wxyzabcdef                   101wxyz
+ *      01wxyzabcdefg                   110wxyz
+ *      1wxyzabcdefgh                   111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz.  * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+static unsigned char
+st_14linear2ulaw(PyInt16 pcm_val)	/* 2's complement (14-bit range) */
+{
+        PyInt16         mask;
+        PyInt16         seg;
+        unsigned char   uval;
+
+        /* The original sox code does this in the calling function, not here */
+        pcm_val = pcm_val >> 2;
+
+        /* u-law inverts all bits */
+        /* Get the sign and the magnitude of the value. */
+        if (pcm_val < 0) {
+                pcm_val = -pcm_val;
+                mask = 0x7F;
+        } else {
+                mask = 0xFF;
+        }
+        if ( pcm_val > CLIP ) pcm_val = CLIP;           /* clip the magnitude */
+        pcm_val += (BIAS >> 2);
+
+        /* Convert the scaled magnitude to segment number. */
+        seg = search(pcm_val, seg_uend, 8);
+
+        /*
+         * Combine the sign, segment, quantization bits;
+         * and complement the code word.
+         */
+        if (seg >= 8)           /* out of range, return maximum value. */
+                return (unsigned char) (0x7F ^ mask);
+        else {
+                uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
+                return (uval ^ mask);
+        }
+
+}
+
+static PyInt16 _st_alaw2linear16[256] = {
+     -5504,   -5248,   -6016,   -5760,   -4480,   -4224,   -4992,
+     -4736,   -7552,   -7296,   -8064,   -7808,   -6528,   -6272,
+     -7040,   -6784,   -2752,   -2624,   -3008,   -2880,   -2240,
+     -2112,   -2496,   -2368,   -3776,   -3648,   -4032,   -3904,
+     -3264,   -3136,   -3520,   -3392,  -22016,  -20992,  -24064,
+    -23040,  -17920,  -16896,  -19968,  -18944,  -30208,  -29184,
+    -32256,  -31232,  -26112,  -25088,  -28160,  -27136,  -11008,
+    -10496,  -12032,  -11520,   -8960,   -8448,   -9984,   -9472,
+    -15104,  -14592,  -16128,  -15616,  -13056,  -12544,  -14080,
+    -13568,    -344,    -328,    -376,    -360,    -280,    -264,
+      -312,    -296,    -472,    -456,    -504,    -488,    -408,
+      -392,    -440,    -424,     -88,     -72,    -120,    -104,
+       -24,      -8,     -56,     -40,    -216,    -200,    -248,
+      -232,    -152,    -136,    -184,    -168,   -1376,   -1312,
+     -1504,   -1440,   -1120,   -1056,   -1248,   -1184,   -1888,
+     -1824,   -2016,   -1952,   -1632,   -1568,   -1760,   -1696,
+      -688,    -656,    -752,    -720,    -560,    -528,    -624,
+      -592,    -944,    -912,   -1008,    -976,    -816,    -784,
+      -880,    -848,    5504,    5248,    6016,    5760,    4480,
+      4224,    4992,    4736,    7552,    7296,    8064,    7808,
+      6528,    6272,    7040,    6784,    2752,    2624,    3008,
+      2880,    2240,    2112,    2496,    2368,    3776,    3648,
+      4032,    3904,    3264,    3136,    3520,    3392,   22016,
+     20992,   24064,   23040,   17920,   16896,   19968,   18944,
+     30208,   29184,   32256,   31232,   26112,   25088,   28160,
+     27136,   11008,   10496,   12032,   11520,    8960,    8448,
+      9984,    9472,   15104,   14592,   16128,   15616,   13056,
+     12544,   14080,   13568,     344,     328,     376,     360,
+       280,     264,     312,     296,     472,     456,     504,
+       488,     408,     392,     440,     424,      88,      72,
+       120,     104,      24,       8,      56,      40,     216,
+       200,     248,     232,     152,     136,     184,     168,
+      1376,    1312,    1504,    1440,    1120,    1056,    1248,
+      1184,    1888,    1824,    2016,    1952,    1632,    1568,
+      1760,    1696,     688,     656,     752,     720,     560,
+       528,     624,     592,     944,     912,    1008,     976,
+       816,     784,     880,     848
+};
+
+/*
+ * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data
+ * stored in a unsigned char.  This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 13-bits.
+ *
+ *              Linear Input Code       Compressed Code
+ *      ------------------------        ---------------
+ *      0000000wxyza                    000wxyz
+ *      0000001wxyza                    001wxyz
+ *      000001wxyzab                    010wxyz
+ *      00001wxyzabc                    011wxyz
+ *      0001wxyzabcd                    100wxyz
+ *      001wxyzabcde                    101wxyz
+ *      01wxyzabcdef                    110wxyz
+ *      1wxyzabcdefg                    111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+static unsigned char
+st_linear2alaw(PyInt16 pcm_val)	/* 2's complement (13-bit range) */
+{
+        PyInt16         mask;
+        short           seg;
+        unsigned char   aval;
+
+        /* The original sox code does this in the calling function, not here */
+        pcm_val = pcm_val >> 3;
+
+        /* A-law using even bit inversion */
+        if (pcm_val >= 0) {
+                mask = 0xD5;            /* sign (7th) bit = 1 */
+        } else {
+                mask = 0x55;            /* sign bit = 0 */
+                pcm_val = -pcm_val - 1;
+        }
+
+        /* Convert the scaled magnitude to segment number. */
+        seg = search(pcm_val, seg_aend, 8);
+
+        /* Combine the sign, segment, and quantization bits. */
+
+        if (seg >= 8)           /* out of range, return maximum value. */
+                return (unsigned char) (0x7F ^ mask);
+        else {
+                aval = (unsigned char) seg << SEG_SHIFT;
+                if (seg < 2)
+                        aval |= (pcm_val >> 1) & QUANT_MASK;
+                else
+                        aval |= (pcm_val >> seg) & QUANT_MASK;
+                return (aval ^ mask);
+        }
 }
 /* End of code taken from sox */
 
 /* Intel ADPCM step variation table */
 static int indexTable[16] = {
-	-1, -1, -1, -1, 2, 4, 6, 8,
-	-1, -1, -1, -1, 2, 4, 6, 8,
+        -1, -1, -1, -1, 2, 4, 6, 8,
+        -1, -1, -1, -1, 2, 4, 6, 8,
 };
 
 static int stepsizeTable[89] = {
-	7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
-	19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
-	50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
-	130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
-	337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
-	876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
-	2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
-	5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
-	15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+        7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+        19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+        50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+        130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+        337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+        876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+        2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+        5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+        15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
 };
     
 #define CHARP(cp, i) ((signed char *)(cp+i))
@@ -151,137 +298,137 @@
 static PyObject *
 audioop_getsample(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	int len, size, val = 0;
-	int i;
+        signed char *cp;
+        int len, size, val = 0;
+        int i;
 
-	if ( !PyArg_Parse(args, "(s#ii)", &cp, &len, &size, &i) )
-		return 0;
-	if ( size != 1 && size != 2 && size != 4 ) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
-	if ( i < 0 || i >= len/size ) {
-		PyErr_SetString(AudioopError, "Index out of range");
-		return 0;
-	}
-	if ( size == 1 )      val = (int)*CHARP(cp, i);
-	else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
-	else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
-	return PyInt_FromLong(val);
+        if ( !PyArg_Parse(args, "(s#ii)", &cp, &len, &size, &i) )
+                return 0;
+        if ( size != 1 && size != 2 && size != 4 ) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+        if ( i < 0 || i >= len/size ) {
+                PyErr_SetString(AudioopError, "Index out of range");
+                return 0;
+        }
+        if ( size == 1 )      val = (int)*CHARP(cp, i);
+        else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
+        else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
+        return PyInt_FromLong(val);
 }
 
 static PyObject *
 audioop_max(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	int len, size, val = 0;
-	int i;
-	int max = 0;
+        signed char *cp;
+        int len, size, val = 0;
+        int i;
+        int max = 0;
 
-	if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
-		return 0;
-	if ( size != 1 && size != 2 && size != 4 ) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
-	for ( i=0; i<len; i+= size) {
-		if ( size == 1 )      val = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = (int)*LONGP(cp, i);
-		if ( val < 0 ) val = (-val);
-		if ( val > max ) max = val;
-	}
-	return PyInt_FromLong(max);
+        if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
+                return 0;
+        if ( size != 1 && size != 2 && size != 4 ) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+        for ( i=0; i<len; i+= size) {
+                if ( size == 1 )      val = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = (int)*LONGP(cp, i);
+                if ( val < 0 ) val = (-val);
+                if ( val > max ) max = val;
+        }
+        return PyInt_FromLong(max);
 }
 
 static PyObject *
 audioop_minmax(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	int len, size, val = 0;
-	int i;
-	int min = 0x7fffffff, max = -0x7fffffff;
+        signed char *cp;
+        int len, size, val = 0;
+        int i;
+        int min = 0x7fffffff, max = -0x7fffffff;
 
-	if (!PyArg_Parse(args, "(s#i)", &cp, &len, &size))
-		return NULL;
-	if (size != 1 && size != 2 && size != 4) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return NULL;
-	}
-	for (i = 0; i < len; i += size) {
-		if (size == 1) val = (int) *CHARP(cp, i);
-		else if (size == 2) val = (int) *SHORTP(cp, i);
-		else if (size == 4) val = (int) *LONGP(cp, i);
-		if (val > max) max = val;
-		if (val < min) min = val;
-	}
-	return Py_BuildValue("(ii)", min, max);
+        if (!PyArg_Parse(args, "(s#i)", &cp, &len, &size))
+                return NULL;
+        if (size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return NULL;
+        }
+        for (i = 0; i < len; i += size) {
+                if (size == 1) val = (int) *CHARP(cp, i);
+                else if (size == 2) val = (int) *SHORTP(cp, i);
+                else if (size == 4) val = (int) *LONGP(cp, i);
+                if (val > max) max = val;
+                if (val < min) min = val;
+        }
+        return Py_BuildValue("(ii)", min, max);
 }
 
 static PyObject *
 audioop_avg(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	int len, size, val = 0;
-	int i;
-	double avg = 0.0;
+        signed char *cp;
+        int len, size, val = 0;
+        int i;
+        double avg = 0.0;
 
-	if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
-		return 0;
-	if ( size != 1 && size != 2 && size != 4 ) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
-	for ( i=0; i<len; i+= size) {
-		if ( size == 1 )      val = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = (int)*LONGP(cp, i);
-		avg += val;
-	}
-	if ( len == 0 )
-		val = 0;
-	else
-		val = (int)(avg / (double)(len/size));
-	return PyInt_FromLong(val);
+        if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
+                return 0;
+        if ( size != 1 && size != 2 && size != 4 ) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+        for ( i=0; i<len; i+= size) {
+                if ( size == 1 )      val = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = (int)*LONGP(cp, i);
+                avg += val;
+        }
+        if ( len == 0 )
+                val = 0;
+        else
+                val = (int)(avg / (double)(len/size));
+        return PyInt_FromLong(val);
 }
 
 static PyObject *
 audioop_rms(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	int len, size, val = 0;
-	int i;
-	double sum_squares = 0.0;
+        signed char *cp;
+        int len, size, val = 0;
+        int i;
+        double sum_squares = 0.0;
 
-	if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
-		return 0;
-	if ( size != 1 && size != 2 && size != 4 ) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
-	for ( i=0; i<len; i+= size) {
-		if ( size == 1 )      val = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = (int)*LONGP(cp, i);
-		sum_squares += (double)val*(double)val;
-	}
-	if ( len == 0 )
-		val = 0;
-	else
-		val = (int)sqrt(sum_squares / (double)(len/size));
-	return PyInt_FromLong(val);
+        if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
+                return 0;
+        if ( size != 1 && size != 2 && size != 4 ) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+        for ( i=0; i<len; i+= size) {
+                if ( size == 1 )      val = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = (int)*LONGP(cp, i);
+                sum_squares += (double)val*(double)val;
+        }
+        if ( len == 0 )
+                val = 0;
+        else
+                val = (int)sqrt(sum_squares / (double)(len/size));
+        return PyInt_FromLong(val);
 }
 
 static double _sum2(short *a, short *b, int len)
 {
-	int i;
-	double sum = 0.0;
+        int i;
+        double sum = 0.0;
 
-	for( i=0; i<len; i++) {
-		sum = sum + (double)a[i]*(double)b[i];
-	}
-	return sum;
+        for( i=0; i<len; i++) {
+                sum = sum + (double)a[i]*(double)b[i];
+        }
+        return sum;
 }
 
 /*
@@ -303,15 +450,15 @@
 ** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
 **
 ** In the code variables correspond as follows:
-** cp1		A
-** cp2		R
-** len1		N
-** len2		n
-** aj_m1	A[j-1]
-** aj_lm1	A[j+n-1]
-** sum_ri_2	sum(R[i]^2)
-** sum_aij_2	sum(A[i+j]^2)
-** sum_aij_ri	sum(A[i+j]R[i])
+** cp1          A
+** cp2          R
+** len1         N
+** len2         n
+** aj_m1        A[j-1]
+** aj_lm1       A[j+n-1]
+** sum_ri_2     sum(R[i]^2)
+** sum_aij_2    sum(A[i+j]^2)
+** sum_aij_ri   sum(A[i+j]R[i])
 **
 ** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
 ** is completely recalculated each step.
@@ -319,55 +466,55 @@
 static PyObject *
 audioop_findfit(PyObject *self, PyObject *args)
 {
-	short *cp1, *cp2;
-	int len1, len2;
-	int j, best_j;
-	double aj_m1, aj_lm1;
-	double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
+        short *cp1, *cp2;
+        int len1, len2;
+        int j, best_j;
+        double aj_m1, aj_lm1;
+        double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
 
-	if ( !PyArg_Parse(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
-		return 0;
-	if ( len1 & 1 || len2 & 1 ) {
-		PyErr_SetString(AudioopError, "Strings should be even-sized");
-		return 0;
-	}
-	len1 >>= 1;
-	len2 >>= 1;
+        if ( !PyArg_Parse(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
+                return 0;
+        if ( len1 & 1 || len2 & 1 ) {
+                PyErr_SetString(AudioopError, "Strings should be even-sized");
+                return 0;
+        }
+        len1 >>= 1;
+        len2 >>= 1;
     
-	if ( len1 < len2 ) {
-		PyErr_SetString(AudioopError, "First sample should be longer");
-		return 0;
-	}
-	sum_ri_2 = _sum2(cp2, cp2, len2);
-	sum_aij_2 = _sum2(cp1, cp1, len2);
-	sum_aij_ri = _sum2(cp1, cp2, len2);
+        if ( len1 < len2 ) {
+                PyErr_SetString(AudioopError, "First sample should be longer");
+                return 0;
+        }
+        sum_ri_2 = _sum2(cp2, cp2, len2);
+        sum_aij_2 = _sum2(cp1, cp1, len2);
+        sum_aij_ri = _sum2(cp1, cp2, len2);
 
-	result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
+        result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
 
-	best_result = result;
-	best_j = 0;
-	j = 0;
+        best_result = result;
+        best_j = 0;
+        j = 0;
 
-	for ( j=1; j<=len1-len2; j++) {
-		aj_m1 = (double)cp1[j-1];
-		aj_lm1 = (double)cp1[j+len2-1];
+        for ( j=1; j<=len1-len2; j++) {
+                aj_m1 = (double)cp1[j-1];
+                aj_lm1 = (double)cp1[j+len2-1];
 
-		sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
-		sum_aij_ri = _sum2(cp1+j, cp2, len2);
+                sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
+                sum_aij_ri = _sum2(cp1+j, cp2, len2);
 
-		result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri)
-			/ sum_aij_2;
+                result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri)
+                        / sum_aij_2;
 
-		if ( result < best_result ) {
-			best_result = result;
-			best_j = j;
-		}
-	
-	}
+                if ( result < best_result ) {
+                        best_result = result;
+                        best_j = j;
+                }
+        
+        }
 
-	factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
+        factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
     
-	return Py_BuildValue("(if)", best_j, factor);
+        return Py_BuildValue("(if)", best_j, factor);
 }
 
 /*
@@ -377,27 +524,27 @@
 static PyObject *
 audioop_findfactor(PyObject *self, PyObject *args)
 {
-	short *cp1, *cp2;
-	int len1, len2;
-	double sum_ri_2, sum_aij_ri, result;
+        short *cp1, *cp2;
+        int len1, len2;
+        double sum_ri_2, sum_aij_ri, result;
 
-	if ( !PyArg_Parse(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
-		return 0;
-	if ( len1 & 1 || len2 & 1 ) {
-		PyErr_SetString(AudioopError, "Strings should be even-sized");
-		return 0;
-	}
-	if ( len1 != len2 ) {
-		PyErr_SetString(AudioopError, "Samples should be same size");
-		return 0;
-	}
-	len2 >>= 1;
-	sum_ri_2 = _sum2(cp2, cp2, len2);
-	sum_aij_ri = _sum2(cp1, cp2, len2);
+        if ( !PyArg_Parse(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
+                return 0;
+        if ( len1 & 1 || len2 & 1 ) {
+                PyErr_SetString(AudioopError, "Strings should be even-sized");
+                return 0;
+        }
+        if ( len1 != len2 ) {
+                PyErr_SetString(AudioopError, "Samples should be same size");
+                return 0;
+        }
+        len2 >>= 1;
+        sum_ri_2 = _sum2(cp2, cp2, len2);
+        sum_aij_ri = _sum2(cp1, cp2, len2);
 
-	result = sum_aij_ri / sum_ri_2;
+        result = sum_aij_ri / sum_ri_2;
 
-	return PyFloat_FromDouble(result);
+        return PyFloat_FromDouble(result);
 }
 
 /*
@@ -407,981 +554,1053 @@
 static PyObject *
 audioop_findmax(PyObject *self, PyObject *args)
 {
-	short *cp1;
-	int len1, len2;
-	int j, best_j;
-	double aj_m1, aj_lm1;
-	double result, best_result;
+        short *cp1;
+        int len1, len2;
+        int j, best_j;
+        double aj_m1, aj_lm1;
+        double result, best_result;
 
-	if ( !PyArg_Parse(args, "(s#i)", &cp1, &len1, &len2) )
-		return 0;
-	if ( len1 & 1 ) {
-		PyErr_SetString(AudioopError, "Strings should be even-sized");
-		return 0;
-	}
-	len1 >>= 1;
+        if ( !PyArg_Parse(args, "(s#i)", &cp1, &len1, &len2) )
+                return 0;
+        if ( len1 & 1 ) {
+                PyErr_SetString(AudioopError, "Strings should be even-sized");
+                return 0;
+        }
+        len1 >>= 1;
     
-	if ( len1 < len2 ) {
-		PyErr_SetString(AudioopError, "Input sample should be longer");
-		return 0;
-	}
+        if ( len1 < len2 ) {
+                PyErr_SetString(AudioopError, "Input sample should be longer");
+                return 0;
+        }
 
-	result = _sum2(cp1, cp1, len2);
+        result = _sum2(cp1, cp1, len2);
 
-	best_result = result;
-	best_j = 0;
-	j = 0;
+        best_result = result;
+        best_j = 0;
+        j = 0;
 
-	for ( j=1; j<=len1-len2; j++) {
-		aj_m1 = (double)cp1[j-1];
-		aj_lm1 = (double)cp1[j+len2-1];
+        for ( j=1; j<=len1-len2; j++) {
+                aj_m1 = (double)cp1[j-1];
+                aj_lm1 = (double)cp1[j+len2-1];
 
-		result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
+                result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
 
-		if ( result > best_result ) {
-			best_result = result;
-			best_j = j;
-		}
-	
-	}
+                if ( result > best_result ) {
+                        best_result = result;
+                        best_j = j;
+                }
+        
+        }
 
-	return PyInt_FromLong(best_j);
+        return PyInt_FromLong(best_j);
 }
 
 static PyObject *
 audioop_avgpp(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	int len, size, val = 0, prevval = 0, prevextremevalid = 0,
-		prevextreme = 0;
-	int i;
-	double avg = 0.0;
-	int diff, prevdiff, extremediff, nextreme = 0;
+        signed char *cp;
+        int len, size, val = 0, prevval = 0, prevextremevalid = 0,
+                prevextreme = 0;
+        int i;
+        double avg = 0.0;
+        int diff, prevdiff, extremediff, nextreme = 0;
 
-	if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
-		return 0;
-	if ( size != 1 && size != 2 && size != 4 ) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
-	/* Compute first delta value ahead. Also automatically makes us
-	** skip the first extreme value
-	*/
-	if ( size == 1 )      prevval = (int)*CHARP(cp, 0);
-	else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
-	else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
-	if ( size == 1 )      val = (int)*CHARP(cp, size);
-	else if ( size == 2 ) val = (int)*SHORTP(cp, size);
-	else if ( size == 4 ) val = (int)*LONGP(cp, size);
-	prevdiff = val - prevval;
+        if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
+                return 0;
+        if ( size != 1 && size != 2 && size != 4 ) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+        /* Compute first delta value ahead. Also automatically makes us
+        ** skip the first extreme value
+        */
+        if ( size == 1 )      prevval = (int)*CHARP(cp, 0);
+        else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
+        else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
+        if ( size == 1 )      val = (int)*CHARP(cp, size);
+        else if ( size == 2 ) val = (int)*SHORTP(cp, size);
+        else if ( size == 4 ) val = (int)*LONGP(cp, size);
+        prevdiff = val - prevval;
     
-	for ( i=size; i<len; i+= size) {
-		if ( size == 1 )      val = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = (int)*LONGP(cp, i);
-		diff = val - prevval;
-		if ( diff*prevdiff < 0 ) {
-			/* Derivative changed sign. Compute difference to last
-			** extreme value and remember.
-			*/
-			if ( prevextremevalid ) {
-				extremediff = prevval - prevextreme;
-				if ( extremediff < 0 )
-					extremediff = -extremediff;
-				avg += extremediff;
-				nextreme++;
-			}
-			prevextremevalid = 1;
-			prevextreme = prevval;
-		}
-		prevval = val;
-		if ( diff != 0 )
-			prevdiff = diff;	
-	}
-	if ( nextreme == 0 )
-		val = 0;
-	else
-		val = (int)(avg / (double)nextreme);
-	return PyInt_FromLong(val);
+        for ( i=size; i<len; i+= size) {
+                if ( size == 1 )      val = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = (int)*LONGP(cp, i);
+                diff = val - prevval;
+                if ( diff*prevdiff < 0 ) {
+                        /* Derivative changed sign. Compute difference to last
+                        ** extreme value and remember.
+                        */
+                        if ( prevextremevalid ) {
+                                extremediff = prevval - prevextreme;
+                                if ( extremediff < 0 )
+                                        extremediff = -extremediff;
+                                avg += extremediff;
+                                nextreme++;
+                        }
+                        prevextremevalid = 1;
+                        prevextreme = prevval;
+                }
+                prevval = val;
+                if ( diff != 0 )
+                        prevdiff = diff;        
+        }
+        if ( nextreme == 0 )
+                val = 0;
+        else
+                val = (int)(avg / (double)nextreme);
+        return PyInt_FromLong(val);
 }
 
 static PyObject *
 audioop_maxpp(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	int len, size, val = 0, prevval = 0, prevextremevalid = 0,
-		prevextreme = 0;
-	int i;
-	int max = 0;
-	int diff, prevdiff, extremediff;
+        signed char *cp;
+        int len, size, val = 0, prevval = 0, prevextremevalid = 0,
+                prevextreme = 0;
+        int i;
+        int max = 0;
+        int diff, prevdiff, extremediff;
 
-	if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
-		return 0;
-	if ( size != 1 && size != 2 && size != 4 ) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
-	/* Compute first delta value ahead. Also automatically makes us
-	** skip the first extreme value
-	*/
-	if ( size == 1 )      prevval = (int)*CHARP(cp, 0);
-	else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
-	else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
-	if ( size == 1 )      val = (int)*CHARP(cp, size);
-	else if ( size == 2 ) val = (int)*SHORTP(cp, size);
-	else if ( size == 4 ) val = (int)*LONGP(cp, size);
-	prevdiff = val - prevval;
+        if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
+                return 0;
+        if ( size != 1 && size != 2 && size != 4 ) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+        /* Compute first delta value ahead. Also automatically makes us
+        ** skip the first extreme value
+        */
+        if ( size == 1 )      prevval = (int)*CHARP(cp, 0);
+        else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
+        else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
+        if ( size == 1 )      val = (int)*CHARP(cp, size);
+        else if ( size == 2 ) val = (int)*SHORTP(cp, size);
+        else if ( size == 4 ) val = (int)*LONGP(cp, size);
+        prevdiff = val - prevval;
 
-	for ( i=size; i<len; i+= size) {
-		if ( size == 1 )      val = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = (int)*LONGP(cp, i);
-		diff = val - prevval;
-		if ( diff*prevdiff < 0 ) {
-			/* Derivative changed sign. Compute difference to
-			** last extreme value and remember.
-			*/
-			if ( prevextremevalid ) {
-				extremediff = prevval - prevextreme;
-				if ( extremediff < 0 )
-					extremediff = -extremediff;
-				if ( extremediff > max )
-					max = extremediff;
-			}
-			prevextremevalid = 1;
-			prevextreme = prevval;
-		}
-		prevval = val;
-		if ( diff != 0 )
-			prevdiff = diff;
-	}
-	return PyInt_FromLong(max);
+        for ( i=size; i<len; i+= size) {
+                if ( size == 1 )      val = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = (int)*LONGP(cp, i);
+                diff = val - prevval;
+                if ( diff*prevdiff < 0 ) {
+                        /* Derivative changed sign. Compute difference to
+                        ** last extreme value and remember.
+                        */
+                        if ( prevextremevalid ) {
+                                extremediff = prevval - prevextreme;
+                                if ( extremediff < 0 )
+                                        extremediff = -extremediff;
+                                if ( extremediff > max )
+                                        max = extremediff;
+                        }
+                        prevextremevalid = 1;
+                        prevextreme = prevval;
+                }
+                prevval = val;
+                if ( diff != 0 )
+                        prevdiff = diff;
+        }
+        return PyInt_FromLong(max);
 }
 
 static PyObject *
 audioop_cross(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	int len, size, val = 0;
-	int i;
-	int prevval, ncross;
+        signed char *cp;
+        int len, size, val = 0;
+        int i;
+        int prevval, ncross;
 
-	if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
-		return 0;
-	if ( size != 1 && size != 2 && size != 4 ) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
-	ncross = -1;
-	prevval = 17; /* Anything <> 0,1 */
-	for ( i=0; i<len; i+= size) {
-		if ( size == 1 )      val = ((int)*CHARP(cp, i)) >> 7;
-		else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
-		else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
-		val = val & 1;
-		if ( val != prevval ) ncross++;
-		prevval = val;
-	}
-	return PyInt_FromLong(ncross);
+        if ( !PyArg_Parse(args, "(s#i)", &cp, &len, &size) )
+                return 0;
+        if ( size != 1 && size != 2 && size != 4 ) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+        ncross = -1;
+        prevval = 17; /* Anything <> 0,1 */
+        for ( i=0; i<len; i+= size) {
+                if ( size == 1 )      val = ((int)*CHARP(cp, i)) >> 7;
+                else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
+                else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
+                val = val & 1;
+                if ( val != prevval ) ncross++;
+                prevval = val;
+        }
+        return PyInt_FromLong(ncross);
 }
 
 static PyObject *
 audioop_mul(PyObject *self, PyObject *args)
 {
-	signed char *cp, *ncp;
-	int len, size, val = 0;
-	double factor, fval, maxval;
-	PyObject *rv;
-	int i;
+        signed char *cp, *ncp;
+        int len, size, val = 0;
+        double factor, fval, maxval;
+        PyObject *rv;
+        int i;
 
-	if ( !PyArg_Parse(args, "(s#id)", &cp, &len, &size, &factor ) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#id)", &cp, &len, &size, &factor ) )
+                return 0;
     
-	if ( size == 1 ) maxval = (double) 0x7f;
-	else if ( size == 2 ) maxval = (double) 0x7fff;
-	else if ( size == 4 ) maxval = (double) 0x7fffffff;
-	else {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size == 1 ) maxval = (double) 0x7f;
+        else if ( size == 2 ) maxval = (double) 0x7fff;
+        else if ( size == 4 ) maxval = (double) 0x7fffffff;
+        else {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	rv = PyString_FromStringAndSize(NULL, len);
-	if ( rv == 0 )
-		return 0;
-	ncp = (signed char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, len);
+        if ( rv == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(rv);
     
     
-	for ( i=0; i < len; i += size ) {
-		if ( size == 1 )      val = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = (int)*LONGP(cp, i);
-		fval = (double)val*factor;
-		if ( fval > maxval ) fval = maxval;
-		else if ( fval < -maxval ) fval = -maxval;
-		val = (int)fval;
-		if ( size == 1 )      *CHARP(ncp, i) = (signed char)val;
-		else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
-		else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)val;
-	}
-	return rv;
+        for ( i=0; i < len; i += size ) {
+                if ( size == 1 )      val = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = (int)*LONGP(cp, i);
+                fval = (double)val*factor;
+                if ( fval > maxval ) fval = maxval;
+                else if ( fval < -maxval ) fval = -maxval;
+                val = (int)fval;
+                if ( size == 1 )      *CHARP(ncp, i) = (signed char)val;
+                else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
+                else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)val;
+        }
+        return rv;
 }
 
 static PyObject *
 audioop_tomono(PyObject *self, PyObject *args)
 {
-	signed char *cp, *ncp;
-	int len, size, val1 = 0, val2 = 0;
-	double fac1, fac2, fval, maxval;
-	PyObject *rv;
-	int i;
+        signed char *cp, *ncp;
+        int len, size, val1 = 0, val2 = 0;
+        double fac1, fac2, fval, maxval;
+        PyObject *rv;
+        int i;
 
-	if ( !PyArg_Parse(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
+                return 0;
     
-	if ( size == 1 ) maxval = (double) 0x7f;
-	else if ( size == 2 ) maxval = (double) 0x7fff;
-	else if ( size == 4 ) maxval = (double) 0x7fffffff;
-	else {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size == 1 ) maxval = (double) 0x7f;
+        else if ( size == 2 ) maxval = (double) 0x7fff;
+        else if ( size == 4 ) maxval = (double) 0x7fffffff;
+        else {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	rv = PyString_FromStringAndSize(NULL, len/2);
-	if ( rv == 0 )
-		return 0;
-	ncp = (signed char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, len/2);
+        if ( rv == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(rv);
     
     
-	for ( i=0; i < len; i += size*2 ) {
-		if ( size == 1 )      val1 = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
-		if ( size == 1 )      val2 = (int)*CHARP(cp, i+1);
-		else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
-		else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
-		fval = (double)val1*fac1 + (double)val2*fac2;
-		if ( fval > maxval ) fval = maxval;
-		else if ( fval < -maxval ) fval = -maxval;
-		val1 = (int)fval;
-		if ( size == 1 )      *CHARP(ncp, i/2) = (signed char)val1;
-		else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
-		else if ( size == 4 ) *LONGP(ncp, i/2)= (Py_Int32)val1;
-	}
-	return rv;
+        for ( i=0; i < len; i += size*2 ) {
+                if ( size == 1 )      val1 = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
+                if ( size == 1 )      val2 = (int)*CHARP(cp, i+1);
+                else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
+                else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
+                fval = (double)val1*fac1 + (double)val2*fac2;
+                if ( fval > maxval ) fval = maxval;
+                else if ( fval < -maxval ) fval = -maxval;
+                val1 = (int)fval;
+                if ( size == 1 )      *CHARP(ncp, i/2) = (signed char)val1;
+                else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
+                else if ( size == 4 ) *LONGP(ncp, i/2)= (Py_Int32)val1;
+        }
+        return rv;
 }
 
 static PyObject *
 audioop_tostereo(PyObject *self, PyObject *args)
 {
-	signed char *cp, *ncp;
-	int len, size, val1, val2, val = 0;
-	double fac1, fac2, fval, maxval;
-	PyObject *rv;
-	int i;
+        signed char *cp, *ncp;
+        int len, size, val1, val2, val = 0;
+        double fac1, fac2, fval, maxval;
+        PyObject *rv;
+        int i;
 
-	if ( !PyArg_Parse(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
+                return 0;
     
-	if ( size == 1 ) maxval = (double) 0x7f;
-	else if ( size == 2 ) maxval = (double) 0x7fff;
-	else if ( size == 4 ) maxval = (double) 0x7fffffff;
-	else {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size == 1 ) maxval = (double) 0x7f;
+        else if ( size == 2 ) maxval = (double) 0x7fff;
+        else if ( size == 4 ) maxval = (double) 0x7fffffff;
+        else {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	rv = PyString_FromStringAndSize(NULL, len*2);
-	if ( rv == 0 )
-		return 0;
-	ncp = (signed char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, len*2);
+        if ( rv == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(rv);
     
     
-	for ( i=0; i < len; i += size ) {
-		if ( size == 1 )      val = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = (int)*LONGP(cp, i);
+        for ( i=0; i < len; i += size ) {
+                if ( size == 1 )      val = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = (int)*LONGP(cp, i);
 
-		fval = (double)val*fac1;
-		if ( fval > maxval ) fval = maxval;
-		else if ( fval < -maxval ) fval = -maxval;
-		val1 = (int)fval;
+                fval = (double)val*fac1;
+                if ( fval > maxval ) fval = maxval;
+                else if ( fval < -maxval ) fval = -maxval;
+                val1 = (int)fval;
 
-		fval = (double)val*fac2;
-		if ( fval > maxval ) fval = maxval;
-		else if ( fval < -maxval ) fval = -maxval;
-		val2 = (int)fval;
+                fval = (double)val*fac2;
+                if ( fval > maxval ) fval = maxval;
+                else if ( fval < -maxval ) fval = -maxval;
+                val2 = (int)fval;
 
-		if ( size == 1 )      *CHARP(ncp, i*2) = (signed char)val1;
-		else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
-		else if ( size == 4 ) *LONGP(ncp, i*2) = (Py_Int32)val1;
+                if ( size == 1 )      *CHARP(ncp, i*2) = (signed char)val1;
+                else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
+                else if ( size == 4 ) *LONGP(ncp, i*2) = (Py_Int32)val1;
 
-		if ( size == 1 )      *CHARP(ncp, i*2+1) = (signed char)val2;
-		else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
-		else if ( size == 4 ) *LONGP(ncp, i*2+4) = (Py_Int32)val2;
-	}
-	return rv;
+                if ( size == 1 )      *CHARP(ncp, i*2+1) = (signed char)val2;
+                else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
+                else if ( size == 4 ) *LONGP(ncp, i*2+4) = (Py_Int32)val2;
+        }
+        return rv;
 }
 
 static PyObject *
 audioop_add(PyObject *self, PyObject *args)
 {
-	signed char *cp1, *cp2, *ncp;
-	int len1, len2, size, val1 = 0, val2 = 0, maxval, newval;
-	PyObject *rv;
-	int i;
+        signed char *cp1, *cp2, *ncp;
+        int len1, len2, size, val1 = 0, val2 = 0, maxval, newval;
+        PyObject *rv;
+        int i;
 
-	if ( !PyArg_Parse(args, "(s#s#i)",
-			  &cp1, &len1, &cp2, &len2, &size ) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#s#i)",
+                          &cp1, &len1, &cp2, &len2, &size ) )
+                return 0;
 
-	if ( len1 != len2 ) {
-		PyErr_SetString(AudioopError, "Lengths should be the same");
-		return 0;
-	}
+        if ( len1 != len2 ) {
+                PyErr_SetString(AudioopError, "Lengths should be the same");
+                return 0;
+        }
     
-	if ( size == 1 ) maxval = 0x7f;
-	else if ( size == 2 ) maxval = 0x7fff;
-	else if ( size == 4 ) maxval = 0x7fffffff;
-	else {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size == 1 ) maxval = 0x7f;
+        else if ( size == 2 ) maxval = 0x7fff;
+        else if ( size == 4 ) maxval = 0x7fffffff;
+        else {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
 
-	rv = PyString_FromStringAndSize(NULL, len1);
-	if ( rv == 0 )
-		return 0;
-	ncp = (signed char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, len1);
+        if ( rv == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(rv);
 
-	for ( i=0; i < len1; i += size ) {
-		if ( size == 1 )      val1 = (int)*CHARP(cp1, i);
-		else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
-		else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
-	
-		if ( size == 1 )      val2 = (int)*CHARP(cp2, i);
-		else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
-		else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
+        for ( i=0; i < len1; i += size ) {
+                if ( size == 1 )      val1 = (int)*CHARP(cp1, i);
+                else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
+                else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
+        
+                if ( size == 1 )      val2 = (int)*CHARP(cp2, i);
+                else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
+                else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
 
-		newval = val1 + val2;
-		/* truncate in case of overflow */
-		if (newval > maxval) newval = maxval;
-		else if (newval < -maxval) newval = -maxval;
-		else if (size == 4 && (newval^val1) < 0 && (newval^val2) < 0)
-			newval = val1 > 0 ? maxval : - maxval;
+                newval = val1 + val2;
+                /* truncate in case of overflow */
+                if (newval > maxval) newval = maxval;
+                else if (newval < -maxval) newval = -maxval;
+                else if (size == 4 && (newval^val1) < 0 && (newval^val2) < 0)
+                        newval = val1 > 0 ? maxval : - maxval;
 
-		if ( size == 1 )      *CHARP(ncp, i) = (signed char)newval;
-		else if ( size == 2 ) *SHORTP(ncp, i) = (short)newval;
-		else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)newval;
-	}
-	return rv;
+                if ( size == 1 )      *CHARP(ncp, i) = (signed char)newval;
+                else if ( size == 2 ) *SHORTP(ncp, i) = (short)newval;
+                else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)newval;
+        }
+        return rv;
 }
 
 static PyObject *
 audioop_bias(PyObject *self, PyObject *args)
 {
-	signed char *cp, *ncp;
-	int len, size, val = 0;
-	PyObject *rv;
-	int i;
-	int bias;
+        signed char *cp, *ncp;
+        int len, size, val = 0;
+        PyObject *rv;
+        int i;
+        int bias;
 
-	if ( !PyArg_Parse(args, "(s#ii)",
-			  &cp, &len, &size , &bias) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#ii)",
+                          &cp, &len, &size , &bias) )
+                return 0;
 
-	if ( size != 1 && size != 2 && size != 4) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	rv = PyString_FromStringAndSize(NULL, len);
-	if ( rv == 0 )
-		return 0;
-	ncp = (signed char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, len);
+        if ( rv == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(rv);
     
     
-	for ( i=0; i < len; i += size ) {
-		if ( size == 1 )      val = (int)*CHARP(cp, i);
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = (int)*LONGP(cp, i);
-	
-		if ( size == 1 )      *CHARP(ncp, i) = (signed char)(val+bias);
-		else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
-		else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val+bias);
-	}
-	return rv;
+        for ( i=0; i < len; i += size ) {
+                if ( size == 1 )      val = (int)*CHARP(cp, i);
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = (int)*LONGP(cp, i);
+        
+                if ( size == 1 )      *CHARP(ncp, i) = (signed char)(val+bias);
+                else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
+                else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val+bias);
+        }
+        return rv;
 }
 
 static PyObject *
 audioop_reverse(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	unsigned char *ncp;
-	int len, size, val = 0;
-	PyObject *rv;
-	int i, j;
+        signed char *cp;
+        unsigned char *ncp;
+        int len, size, val = 0;
+        PyObject *rv;
+        int i, j;
 
-	if ( !PyArg_Parse(args, "(s#i)",
-			  &cp, &len, &size) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#i)",
+                          &cp, &len, &size) )
+                return 0;
 
-	if ( size != 1 && size != 2 && size != 4 ) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size != 1 && size != 2 && size != 4 ) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	rv = PyString_FromStringAndSize(NULL, len);
-	if ( rv == 0 )
-		return 0;
-	ncp = (unsigned char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, len);
+        if ( rv == 0 )
+                return 0;
+        ncp = (unsigned char *)PyString_AsString(rv);
     
-	for ( i=0; i < len; i += size ) {
-		if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
+        for ( i=0; i < len; i += size ) {
+                if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
 
-		j = len - i - size;
-	
-		if ( size == 1 )      *CHARP(ncp, j) = (signed char)(val >> 8);
-		else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
-		else if ( size == 4 ) *LONGP(ncp, j) = (Py_Int32)(val<<16);
-	}
-	return rv;
+                j = len - i - size;
+        
+                if ( size == 1 )      *CHARP(ncp, j) = (signed char)(val >> 8);
+                else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
+                else if ( size == 4 ) *LONGP(ncp, j) = (Py_Int32)(val<<16);
+        }
+        return rv;
 }
 
 static PyObject *
 audioop_lin2lin(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	unsigned char *ncp;
-	int len, size, size2, val = 0;
-	PyObject *rv;
-	int i, j;
+        signed char *cp;
+        unsigned char *ncp;
+        int len, size, size2, val = 0;
+        PyObject *rv;
+        int i, j;
 
-	if ( !PyArg_Parse(args, "(s#ii)",
-			  &cp, &len, &size, &size2) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#ii)",
+                          &cp, &len, &size, &size2) )
+                return 0;
 
-	if ( (size != 1 && size != 2 && size != 4) ||
-	     (size2 != 1 && size2 != 2 && size2 != 4)) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( (size != 1 && size != 2 && size != 4) ||
+             (size2 != 1 && size2 != 2 && size2 != 4)) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	rv = PyString_FromStringAndSize(NULL, (len/size)*size2);
-	if ( rv == 0 )
-		return 0;
-	ncp = (unsigned char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, (len/size)*size2);
+        if ( rv == 0 )
+                return 0;
+        ncp = (unsigned char *)PyString_AsString(rv);
     
-	for ( i=0, j=0; i < len; i += size, j += size2 ) {
-		if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
+        for ( i=0, j=0; i < len; i += size, j += size2 ) {
+                if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
 
-		if ( size2 == 1 )  *CHARP(ncp, j) = (signed char)(val >> 8);
-		else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
-		else if ( size2 == 4 ) *LONGP(ncp, j) = (Py_Int32)(val<<16);
-	}
-	return rv;
+                if ( size2 == 1 )  *CHARP(ncp, j) = (signed char)(val >> 8);
+                else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
+                else if ( size2 == 4 ) *LONGP(ncp, j) = (Py_Int32)(val<<16);
+        }
+        return rv;
 }
 
 static int
 gcd(int a, int b)
 {
-	while (b > 0) {
-		int tmp = a % b;
-		a = b;
-		b = tmp;
-	}
-	return a;
+        while (b > 0) {
+                int tmp = a % b;
+                a = b;
+                b = tmp;
+        }
+        return a;
 }
 
 static PyObject *
 audioop_ratecv(PyObject *self, PyObject *args)
 {
-	char *cp, *ncp;
-	int len, size, nchannels, inrate, outrate, weightA, weightB;
-	int chan, d, *prev_i, *cur_i, cur_o;
-	PyObject *state, *samps, *str, *rv = NULL;
-	int bytes_per_frame;
+        char *cp, *ncp;
+        int len, size, nchannels, inrate, outrate, weightA, weightB;
+        int chan, d, *prev_i, *cur_i, cur_o;
+        PyObject *state, *samps, *str, *rv = NULL;
+        int bytes_per_frame;
 
-	weightA = 1;
-	weightB = 0;
-	if (!PyArg_ParseTuple(args, "s#iiiiO|ii:ratecv", &cp, &len, &size, &nchannels,
-			      &inrate, &outrate, &state, &weightA, &weightB))
-		return NULL;
-	if (size != 1 && size != 2 && size != 4) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return NULL;
-	}
-	if (nchannels < 1) {
-		PyErr_SetString(AudioopError, "# of channels should be >= 1");
-		return NULL;
-	}
-	bytes_per_frame = size * nchannels;
-	if (bytes_per_frame / nchannels != size) {
-		/* This overflow test is rigorously correct because
-		   both multiplicands are >= 1.  Use the argument names
-		   from the docs for the error msg. */
-		PyErr_SetString(PyExc_OverflowError,
-		                "width * nchannels too big for a C int");
-		return NULL;
-	}
-	if (weightA < 1 || weightB < 0) {
-		PyErr_SetString(AudioopError,
-			"weightA should be >= 1, weightB should be >= 0");
-		return NULL;
-	}
-	if (len % bytes_per_frame != 0) {
-		PyErr_SetString(AudioopError, "not a whole number of frames");
-		return NULL;
-	}
-	if (inrate <= 0 || outrate <= 0) {
-		PyErr_SetString(AudioopError, "sampling rate not > 0");
-		return NULL;
-	}
-	/* divide inrate and outrate by their greatest common divisor */
-	d = gcd(inrate, outrate);
-	inrate /= d;
-	outrate /= d;
+        weightA = 1;
+        weightB = 0;
+        if (!PyArg_ParseTuple(args, "s#iiiiO|ii:ratecv", &cp, &len, &size, &nchannels,
+                              &inrate, &outrate, &state, &weightA, &weightB))
+                return NULL;
+        if (size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return NULL;
+        }
+        if (nchannels < 1) {
+                PyErr_SetString(AudioopError, "# of channels should be >= 1");
+                return NULL;
+        }
+        bytes_per_frame = size * nchannels;
+        if (bytes_per_frame / nchannels != size) {
+                /* This overflow test is rigorously correct because
+                   both multiplicands are >= 1.  Use the argument names
+                   from the docs for the error msg. */
+                PyErr_SetString(PyExc_OverflowError,
+                                "width * nchannels too big for a C int");
+                return NULL;
+        }
+        if (weightA < 1 || weightB < 0) {
+                PyErr_SetString(AudioopError,
+                        "weightA should be >= 1, weightB should be >= 0");
+                return NULL;
+        }
+        if (len % bytes_per_frame != 0) {
+                PyErr_SetString(AudioopError, "not a whole number of frames");
+                return NULL;
+        }
+        if (inrate <= 0 || outrate <= 0) {
+                PyErr_SetString(AudioopError, "sampling rate not > 0");
+                return NULL;
+        }
+        /* divide inrate and outrate by their greatest common divisor */
+        d = gcd(inrate, outrate);
+        inrate /= d;
+        outrate /= d;
 
-	prev_i = (int *) malloc(nchannels * sizeof(int));
-	cur_i = (int *) malloc(nchannels * sizeof(int));
-	if (prev_i == NULL || cur_i == NULL) {
-		(void) PyErr_NoMemory();
-		goto exit;
-	}
+        prev_i = (int *) malloc(nchannels * sizeof(int));
+        cur_i = (int *) malloc(nchannels * sizeof(int));
+        if (prev_i == NULL || cur_i == NULL) {
+                (void) PyErr_NoMemory();
+                goto exit;
+        }
 
-	len /= bytes_per_frame;	/* # of frames */
+        len /= bytes_per_frame; /* # of frames */
 
-	if (state == Py_None) {
-		d = -outrate;
-		for (chan = 0; chan < nchannels; chan++)
-			prev_i[chan] = cur_i[chan] = 0;
-	}
-	else {
-		if (!PyArg_ParseTuple(state,
-				"iO!;audioop.ratecv: illegal state argument",
-				&d, &PyTuple_Type, &samps))
-			goto exit;
-		if (PyTuple_Size(samps) != nchannels) {
-			PyErr_SetString(AudioopError,
-					"illegal state argument");
-			goto exit;
-		}
-		for (chan = 0; chan < nchannels; chan++) {
-			if (!PyArg_ParseTuple(PyTuple_GetItem(samps, chan),
-					      "ii:ratecv",&prev_i[chan],&cur_i[chan]))
-				goto exit;
-		}
-	}
+        if (state == Py_None) {
+                d = -outrate;
+                for (chan = 0; chan < nchannels; chan++)
+                        prev_i[chan] = cur_i[chan] = 0;
+        }
+        else {
+                if (!PyArg_ParseTuple(state,
+                                "iO!;audioop.ratecv: illegal state argument",
+                                &d, &PyTuple_Type, &samps))
+                        goto exit;
+                if (PyTuple_Size(samps) != nchannels) {
+                        PyErr_SetString(AudioopError,
+                                        "illegal state argument");
+                        goto exit;
+                }
+                for (chan = 0; chan < nchannels; chan++) {
+                        if (!PyArg_ParseTuple(PyTuple_GetItem(samps, chan),
+                                              "ii:ratecv",&prev_i[chan],&cur_i[chan]))
+                                goto exit;
+                }
+        }
 
-	/* str <- Space for the output buffer. */
-	{
-		/* There are len input frames, so we need (mathematically)
-		   ceiling(len*outrate/inrate) output frames, and each frame
-		   requires bytes_per_frame bytes.  Computing this
-		   without spurious overflow is the challenge; we can
-		   settle for a reasonable upper bound, though. */
-		int ceiling;   /* the number of output frames */
-		int nbytes;    /* the number of output bytes needed */
-		int q = len / inrate;
-		/* Now len = q * inrate + r exactly (with r = len % inrate),
-		   and this is less than q * inrate + inrate = (q+1)*inrate.
-		   So a reasonable upper bound on len*outrate/inrate is
-		   ((q+1)*inrate)*outrate/inrate =
-		   (q+1)*outrate.
-		*/
-		ceiling = (q+1) * outrate;
-		nbytes = ceiling * bytes_per_frame;
-		/* See whether anything overflowed; if not, get the space. */
-		if (q+1 < 0 ||
-		    ceiling / outrate != q+1 ||
-		    nbytes / bytes_per_frame != ceiling)
-			str = NULL;
-		else
-			str = PyString_FromStringAndSize(NULL, nbytes);
+        /* str <- Space for the output buffer. */
+        {
+                /* There are len input frames, so we need (mathematically)
+                   ceiling(len*outrate/inrate) output frames, and each frame
+                   requires bytes_per_frame bytes.  Computing this
+                   without spurious overflow is the challenge; we can
+                   settle for a reasonable upper bound, though. */
+                int ceiling;   /* the number of output frames */
+                int nbytes;    /* the number of output bytes needed */
+                int q = len / inrate;
+                /* Now len = q * inrate + r exactly (with r = len % inrate),
+                   and this is less than q * inrate + inrate = (q+1)*inrate.
+                   So a reasonable upper bound on len*outrate/inrate is
+                   ((q+1)*inrate)*outrate/inrate =
+                   (q+1)*outrate.
+                */
+                ceiling = (q+1) * outrate;
+                nbytes = ceiling * bytes_per_frame;
+                /* See whether anything overflowed; if not, get the space. */
+                if (q+1 < 0 ||
+                    ceiling / outrate != q+1 ||
+                    nbytes / bytes_per_frame != ceiling)
+                        str = NULL;
+                else
+                        str = PyString_FromStringAndSize(NULL, nbytes);
 
-		if (str == NULL) {
-			PyErr_SetString(PyExc_MemoryError,
-				"not enough memory for output buffer");
-			goto exit;
-		}
-	}
-	ncp = PyString_AsString(str);
+                if (str == NULL) {
+                        PyErr_SetString(PyExc_MemoryError,
+                                "not enough memory for output buffer");
+                        goto exit;
+                }
+        }
+        ncp = PyString_AsString(str);
 
-	for (;;) {
-		while (d < 0) {
-			if (len == 0) {
-				samps = PyTuple_New(nchannels);
-				if (samps == NULL)
-					goto exit;
-				for (chan = 0; chan < nchannels; chan++)
-					PyTuple_SetItem(samps, chan,
-						Py_BuildValue("(ii)",
-							      prev_i[chan],
-							      cur_i[chan]));
-				if (PyErr_Occurred())
-					goto exit;
-				/* We have checked before that the length
-				 * of the string fits into int. */
-				len = (int)(ncp - PyString_AsString(str));
-				if (len == 0) {
-					/*don't want to resize to zero length*/
-					rv = PyString_FromStringAndSize("", 0);
-					Py_DECREF(str);
-					str = rv;
-				} else if (_PyString_Resize(&str, len) < 0)
-					goto exit;
-				rv = Py_BuildValue("(O(iO))", str, d, samps);
-				Py_DECREF(samps);
-				Py_DECREF(str);
-				goto exit; /* return rv */
-			}
-			for (chan = 0; chan < nchannels; chan++) {
-				prev_i[chan] = cur_i[chan];
-				if (size == 1)
-				    cur_i[chan] = ((int)*CHARP(cp, 0)) << 8;
-				else if (size == 2)
-				    cur_i[chan] = (int)*SHORTP(cp, 0);
-				else if (size == 4)
-				    cur_i[chan] = ((int)*LONGP(cp, 0)) >> 16;
-				cp += size;
-				/* implements a simple digital filter */
-				cur_i[chan] =
-					(weightA * cur_i[chan] +
-					 weightB * prev_i[chan]) /
-					(weightA + weightB);
-			}
-			len--;
-			d += outrate;
-		}
-		while (d >= 0) {
-			for (chan = 0; chan < nchannels; chan++) {
-				cur_o = (prev_i[chan] * d +
-					 cur_i[chan] * (outrate - d)) /
-					outrate;
-				if (size == 1)
-				    *CHARP(ncp, 0) = (signed char)(cur_o >> 8);
-				else if (size == 2)
-				    *SHORTP(ncp, 0) = (short)(cur_o);
-				else if (size == 4)
-				    *LONGP(ncp, 0) = (Py_Int32)(cur_o<<16);
-				ncp += size;
-			}
-			d -= inrate;
-		}
-	}
+        for (;;) {
+                while (d < 0) {
+                        if (len == 0) {
+                                samps = PyTuple_New(nchannels);
+                                if (samps == NULL)
+                                        goto exit;
+                                for (chan = 0; chan < nchannels; chan++)
+                                        PyTuple_SetItem(samps, chan,
+                                                Py_BuildValue("(ii)",
+                                                              prev_i[chan],
+                                                              cur_i[chan]));
+                                if (PyErr_Occurred())
+                                        goto exit;
+                                /* We have checked before that the length
+                                 * of the string fits into int. */
+                                len = (int)(ncp - PyString_AsString(str));
+                                if (len == 0) {
+                                        /*don't want to resize to zero length*/
+                                        rv = PyString_FromStringAndSize("", 0);
+                                        Py_DECREF(str);
+                                        str = rv;
+                                } else if (_PyString_Resize(&str, len) < 0)
+                                        goto exit;
+                                rv = Py_BuildValue("(O(iO))", str, d, samps);
+                                Py_DECREF(samps);
+                                Py_DECREF(str);
+                                goto exit; /* return rv */
+                        }
+                        for (chan = 0; chan < nchannels; chan++) {
+                                prev_i[chan] = cur_i[chan];
+                                if (size == 1)
+                                    cur_i[chan] = ((int)*CHARP(cp, 0)) << 8;
+                                else if (size == 2)
+                                    cur_i[chan] = (int)*SHORTP(cp, 0);
+                                else if (size == 4)
+                                    cur_i[chan] = ((int)*LONGP(cp, 0)) >> 16;
+                                cp += size;
+                                /* implements a simple digital filter */
+                                cur_i[chan] =
+                                        (weightA * cur_i[chan] +
+                                         weightB * prev_i[chan]) /
+                                        (weightA + weightB);
+                        }
+                        len--;
+                        d += outrate;
+                }
+                while (d >= 0) {
+                        for (chan = 0; chan < nchannels; chan++) {
+                                cur_o = (prev_i[chan] * d +
+                                         cur_i[chan] * (outrate - d)) /
+                                        outrate;
+                                if (size == 1)
+                                    *CHARP(ncp, 0) = (signed char)(cur_o >> 8);
+                                else if (size == 2)
+                                    *SHORTP(ncp, 0) = (short)(cur_o);
+                                else if (size == 4)
+                                    *LONGP(ncp, 0) = (Py_Int32)(cur_o<<16);
+                                ncp += size;
+                        }
+                        d -= inrate;
+                }
+        }
   exit:
-	if (prev_i != NULL)
-		free(prev_i);
-	if (cur_i != NULL)
-		free(cur_i);
-	return rv;
+        if (prev_i != NULL)
+                free(prev_i);
+        if (cur_i != NULL)
+                free(cur_i);
+        return rv;
 }
 
 static PyObject *
 audioop_lin2ulaw(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	unsigned char *ncp;
-	int len, size, val = 0;
-	PyObject *rv;
-	int i;
+        signed char *cp;
+        unsigned char *ncp;
+        int len, size, val = 0;
+        PyObject *rv;
+        int i;
 
-	if ( !PyArg_Parse(args, "(s#i)",
-			  &cp, &len, &size) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#i)",
+                          &cp, &len, &size) )
+                return 0;
 
-	if ( size != 1 && size != 2 && size != 4) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	rv = PyString_FromStringAndSize(NULL, len/size);
-	if ( rv == 0 )
-		return 0;
-	ncp = (unsigned char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, len/size);
+        if ( rv == 0 )
+                return 0;
+        ncp = (unsigned char *)PyString_AsString(rv);
     
-	for ( i=0; i < len; i += size ) {
-		if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
+        for ( i=0; i < len; i += size ) {
+                if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
 
-		*ncp++ = st_linear_to_ulaw(val);
-	}
-	return rv;
+                *ncp++ = st_14linear2ulaw(val);
+        }
+        return rv;
 }
 
 static PyObject *
 audioop_ulaw2lin(PyObject *self, PyObject *args)
 {
-	unsigned char *cp;
-	unsigned char cval;
-	signed char *ncp;
-	int len, size, val;
-	PyObject *rv;
-	int i;
+        unsigned char *cp;
+        unsigned char cval;
+        signed char *ncp;
+        int len, size, val;
+        PyObject *rv;
+        int i;
 
-	if ( !PyArg_Parse(args, "(s#i)",
-			  &cp, &len, &size) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#i)",
+                          &cp, &len, &size) )
+                return 0;
 
-	if ( size != 1 && size != 2 && size != 4) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	rv = PyString_FromStringAndSize(NULL, len*size);
-	if ( rv == 0 )
-		return 0;
-	ncp = (signed char *)PyString_AsString(rv);
+        rv = PyString_FromStringAndSize(NULL, len*size);
+        if ( rv == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(rv);
     
-	for ( i=0; i < len*size; i += size ) {
-		cval = *cp++;
-		val = st_ulaw_to_linear(cval);
-	
-		if ( size == 1 )      *CHARP(ncp, i) = (signed char)(val >> 8);
-		else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
-		else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val<<16);
-	}
-	return rv;
+        for ( i=0; i < len*size; i += size ) {
+                cval = *cp++;
+                val = st_ulaw2linear16(cval);
+        
+                if ( size == 1 )      *CHARP(ncp, i) = (signed char)(val >> 8);
+                else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
+                else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val<<16);
+        }
+        return rv;
+}
+
+static PyObject *
+audioop_lin2alaw(PyObject *self, PyObject *args)
+{
+        signed char *cp;
+        unsigned char *ncp;
+        int len, size, val = 0;
+        PyObject *rv;
+        int i;
+
+        if ( !PyArg_Parse(args, "(s#i)",
+                          &cp, &len, &size) )
+                return 0;
+
+        if ( size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+    
+        rv = PyString_FromStringAndSize(NULL, len/size);
+        if ( rv == 0 )
+                return 0;
+        ncp = (unsigned char *)PyString_AsString(rv);
+    
+        for ( i=0; i < len; i += size ) {
+                if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
+
+                *ncp++ = st_linear2alaw(val);
+        }
+        return rv;
+}
+
+static PyObject *
+audioop_alaw2lin(PyObject *self, PyObject *args)
+{
+        unsigned char *cp;
+        unsigned char cval;
+        signed char *ncp;
+        int len, size, val;
+        PyObject *rv;
+        int i;
+
+        if ( !PyArg_Parse(args, "(s#i)",
+                          &cp, &len, &size) )
+                return 0;
+
+        if ( size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
+    
+        rv = PyString_FromStringAndSize(NULL, len*size);
+        if ( rv == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(rv);
+    
+        for ( i=0; i < len*size; i += size ) {
+                cval = *cp++;
+                val = st_alaw2linear16(cval);
+        
+                if ( size == 1 )      *CHARP(ncp, i) = (signed char)(val >> 8);
+                else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
+                else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val<<16);
+        }
+        return rv;
 }
 
 static PyObject *
 audioop_lin2adpcm(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	signed char *ncp;
-	int len, size, val = 0, step, valpred, delta,
-		index, sign, vpdiff, diff;
-	PyObject *rv, *state, *str;
-	int i, outputbuffer = 0, bufferstep;
+        signed char *cp;
+        signed char *ncp;
+        int len, size, val = 0, step, valpred, delta,
+                index, sign, vpdiff, diff;
+        PyObject *rv, *state, *str;
+        int i, outputbuffer = 0, bufferstep;
 
-	if ( !PyArg_Parse(args, "(s#iO)",
-			  &cp, &len, &size, &state) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#iO)",
+                          &cp, &len, &size, &state) )
+                return 0;
     
 
-	if ( size != 1 && size != 2 && size != 4) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	str = PyString_FromStringAndSize(NULL, len/(size*2));
-	if ( str == 0 )
-		return 0;
-	ncp = (signed char *)PyString_AsString(str);
+        str = PyString_FromStringAndSize(NULL, len/(size*2));
+        if ( str == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(str);
 
-	/* Decode state, should have (value, step) */
-	if ( state == Py_None ) {
-		/* First time, it seems. Set defaults */
-		valpred = 0;
-		step = 7;
-		index = 0;
-	} else if ( !PyArg_Parse(state, "(ii)", &valpred, &index) )
-		return 0;
+        /* Decode state, should have (value, step) */
+        if ( state == Py_None ) {
+                /* First time, it seems. Set defaults */
+                valpred = 0;
+                step = 7;
+                index = 0;
+        } else if ( !PyArg_Parse(state, "(ii)", &valpred, &index) )
+                return 0;
 
-	step = stepsizeTable[index];
-	bufferstep = 1;
+        step = stepsizeTable[index];
+        bufferstep = 1;
 
-	for ( i=0; i < len; i += size ) {
-		if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
-		else if ( size == 2 ) val = (int)*SHORTP(cp, i);
-		else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
+        for ( i=0; i < len; i += size ) {
+                if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
+                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+                else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
 
-		/* Step 1 - compute difference with previous value */
-		diff = val - valpred;
-		sign = (diff < 0) ? 8 : 0;
-		if ( sign ) diff = (-diff);
+                /* Step 1 - compute difference with previous value */
+                diff = val - valpred;
+                sign = (diff < 0) ? 8 : 0;
+                if ( sign ) diff = (-diff);
 
-		/* Step 2 - Divide and clamp */
-		/* Note:
-		** This code *approximately* computes:
-		**    delta = diff*4/step;
-		**    vpdiff = (delta+0.5)*step/4;
-		** but in shift step bits are dropped. The net result of this
-		** is that even if you have fast mul/div hardware you cannot
-		** put it to good use since the fixup would be too expensive.
-		*/
-		delta = 0;
-		vpdiff = (step >> 3);
-	
-		if ( diff >= step ) {
-			delta = 4;
-			diff -= step;
-			vpdiff += step;
-		}
-		step >>= 1;
-		if ( diff >= step  ) {
-			delta |= 2;
-			diff -= step;
-			vpdiff += step;
-		}
-		step >>= 1;
-		if ( diff >= step ) {
-			delta |= 1;
-			vpdiff += step;
-		}
+                /* Step 2 - Divide and clamp */
+                /* Note:
+                ** This code *approximately* computes:
+                **    delta = diff*4/step;
+                **    vpdiff = (delta+0.5)*step/4;
+                ** but in shift step bits are dropped. The net result of this
+                ** is that even if you have fast mul/div hardware you cannot
+                ** put it to good use since the fixup would be too expensive.
+                */
+                delta = 0;
+                vpdiff = (step >> 3);
+        
+                if ( diff >= step ) {
+                        delta = 4;
+                        diff -= step;
+                        vpdiff += step;
+                }
+                step >>= 1;
+                if ( diff >= step  ) {
+                        delta |= 2;
+                        diff -= step;
+                        vpdiff += step;
+                }
+                step >>= 1;
+                if ( diff >= step ) {
+                        delta |= 1;
+                        vpdiff += step;
+                }
 
-		/* Step 3 - Update previous value */
-		if ( sign )
-			valpred -= vpdiff;
-		else
-			valpred += vpdiff;
+                /* Step 3 - Update previous value */
+                if ( sign )
+                        valpred -= vpdiff;
+                else
+                        valpred += vpdiff;
 
-		/* Step 4 - Clamp previous value to 16 bits */
-		if ( valpred > 32767 )
-			valpred = 32767;
-		else if ( valpred < -32768 )
-			valpred = -32768;
+                /* Step 4 - Clamp previous value to 16 bits */
+                if ( valpred > 32767 )
+                        valpred = 32767;
+                else if ( valpred < -32768 )
+                        valpred = -32768;
 
-		/* Step 5 - Assemble value, update index and step values */
-		delta |= sign;
-	
-		index += indexTable[delta];
-		if ( index < 0 ) index = 0;
-		if ( index > 88 ) index = 88;
-		step = stepsizeTable[index];
+                /* Step 5 - Assemble value, update index and step values */
+                delta |= sign;
+        
+                index += indexTable[delta];
+                if ( index < 0 ) index = 0;
+                if ( index > 88 ) index = 88;
+                step = stepsizeTable[index];
 
-		/* Step 6 - Output value */
-		if ( bufferstep ) {
-			outputbuffer = (delta << 4) & 0xf0;
-		} else {
-			*ncp++ = (delta & 0x0f) | outputbuffer;
-		}
-		bufferstep = !bufferstep;
-	}
-	rv = Py_BuildValue("(O(ii))", str, valpred, index);
-	Py_DECREF(str);
-	return rv;
+                /* Step 6 - Output value */
+                if ( bufferstep ) {
+                        outputbuffer = (delta << 4) & 0xf0;
+                } else {
+                        *ncp++ = (delta & 0x0f) | outputbuffer;
+                }
+                bufferstep = !bufferstep;
+        }
+        rv = Py_BuildValue("(O(ii))", str, valpred, index);
+        Py_DECREF(str);
+        return rv;
 }
 
 static PyObject *
 audioop_adpcm2lin(PyObject *self, PyObject *args)
 {
-	signed char *cp;
-	signed char *ncp;
-	int len, size, valpred, step, delta, index, sign, vpdiff;
-	PyObject *rv, *str, *state;
-	int i, inputbuffer = 0, bufferstep;
+        signed char *cp;
+        signed char *ncp;
+        int len, size, valpred, step, delta, index, sign, vpdiff;
+        PyObject *rv, *str, *state;
+        int i, inputbuffer = 0, bufferstep;
 
-	if ( !PyArg_Parse(args, "(s#iO)",
-			  &cp, &len, &size, &state) )
-		return 0;
+        if ( !PyArg_Parse(args, "(s#iO)",
+                          &cp, &len, &size, &state) )
+                return 0;
 
-	if ( size != 1 && size != 2 && size != 4) {
-		PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
-		return 0;
-	}
+        if ( size != 1 && size != 2 && size != 4) {
+                PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+                return 0;
+        }
     
-	/* Decode state, should have (value, step) */
-	if ( state == Py_None ) {
-		/* First time, it seems. Set defaults */
-		valpred = 0;
-		step = 7;
-		index = 0;
-	} else if ( !PyArg_Parse(state, "(ii)", &valpred, &index) )
-		return 0;
+        /* Decode state, should have (value, step) */
+        if ( state == Py_None ) {
+                /* First time, it seems. Set defaults */
+                valpred = 0;
+                step = 7;
+                index = 0;
+        } else if ( !PyArg_Parse(state, "(ii)", &valpred, &index) )
+                return 0;
     
-	str = PyString_FromStringAndSize(NULL, len*size*2);
-	if ( str == 0 )
-		return 0;
-	ncp = (signed char *)PyString_AsString(str);
+        str = PyString_FromStringAndSize(NULL, len*size*2);
+        if ( str == 0 )
+                return 0;
+        ncp = (signed char *)PyString_AsString(str);
 
-	step = stepsizeTable[index];
-	bufferstep = 0;
+        step = stepsizeTable[index];
+        bufferstep = 0;
     
-	for ( i=0; i < len*size*2; i += size ) {
-		/* Step 1 - get the delta value and compute next index */
-		if ( bufferstep ) {
-			delta = inputbuffer & 0xf;
-		} else {
-			inputbuffer = *cp++;
-			delta = (inputbuffer >> 4) & 0xf;
-		}
+        for ( i=0; i < len*size*2; i += size ) {
+                /* Step 1 - get the delta value and compute next index */
+                if ( bufferstep ) {
+                        delta = inputbuffer & 0xf;
+                } else {
+                        inputbuffer = *cp++;
+                        delta = (inputbuffer >> 4) & 0xf;
+                }
 
-		bufferstep = !bufferstep;
+                bufferstep = !bufferstep;
 
-		/* Step 2 - Find new index value (for later) */
-		index += indexTable[delta];
-		if ( index < 0 ) index = 0;
-		if ( index > 88 ) index = 88;
+                /* Step 2 - Find new index value (for later) */
+                index += indexTable[delta];
+                if ( index < 0 ) index = 0;
+                if ( index > 88 ) index = 88;
 
-		/* Step 3 - Separate sign and magnitude */
-		sign = delta & 8;
-		delta = delta & 7;
+                /* Step 3 - Separate sign and magnitude */
+                sign = delta & 8;
+                delta = delta & 7;
 
-		/* Step 4 - Compute difference and new predicted value */
-		/*
-		** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
-		** in adpcm_coder.
-		*/
-		vpdiff = step >> 3;
-		if ( delta & 4 ) vpdiff += step;
-		if ( delta & 2 ) vpdiff += step>>1;
-		if ( delta & 1 ) vpdiff += step>>2;
+                /* Step 4 - Compute difference and new predicted value */
+                /*
+                ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
+                ** in adpcm_coder.
+                */
+                vpdiff = step >> 3;
+                if ( delta & 4 ) vpdiff += step;
+                if ( delta & 2 ) vpdiff += step>>1;
+                if ( delta & 1 ) vpdiff += step>>2;
 
-		if ( sign )
-			valpred -= vpdiff;
-		else
-			valpred += vpdiff;
+                if ( sign )
+                        valpred -= vpdiff;
+                else
+                        valpred += vpdiff;
 
-		/* Step 5 - clamp output value */
-		if ( valpred > 32767 )
-			valpred = 32767;
-		else if ( valpred < -32768 )
-			valpred = -32768;
+                /* Step 5 - clamp output value */
+                if ( valpred > 32767 )
+                        valpred = 32767;
+                else if ( valpred < -32768 )
+                        valpred = -32768;
 
-		/* Step 6 - Update step value */
-		step = stepsizeTable[index];
+                /* Step 6 - Update step value */
+                step = stepsizeTable[index];
 
-		/* Step 6 - Output value */
-		if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
-		else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
-		else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(valpred<<16);
-	}
+                /* Step 6 - Output value */
+                if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
+                else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
+                else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(valpred<<16);
+        }
 
-	rv = Py_BuildValue("(O(ii))", str, valpred, index);
-	Py_DECREF(str);
-	return rv;
+        rv = Py_BuildValue("(O(ii))", str, valpred, index);
+        Py_DECREF(str);
+        return rv;
 }
 
 static PyMethodDef audioop_methods[] = {
-	{ "max", audioop_max, METH_OLDARGS },
-	{ "minmax", audioop_minmax, METH_OLDARGS },
-	{ "avg", audioop_avg, METH_OLDARGS },
-	{ "maxpp", audioop_maxpp, METH_OLDARGS },
-	{ "avgpp", audioop_avgpp, METH_OLDARGS },
-	{ "rms", audioop_rms, METH_OLDARGS },
-	{ "findfit", audioop_findfit, METH_OLDARGS },
-	{ "findmax", audioop_findmax, METH_OLDARGS },
-	{ "findfactor", audioop_findfactor, METH_OLDARGS },
-	{ "cross", audioop_cross, METH_OLDARGS },
-	{ "mul", audioop_mul, METH_OLDARGS },
-	{ "add", audioop_add, METH_OLDARGS },
-	{ "bias", audioop_bias, METH_OLDARGS },
-	{ "ulaw2lin", audioop_ulaw2lin, METH_OLDARGS },
-	{ "lin2ulaw", audioop_lin2ulaw, METH_OLDARGS },
-	{ "lin2lin", audioop_lin2lin, METH_OLDARGS },
-	{ "adpcm2lin", audioop_adpcm2lin, METH_OLDARGS },
-	{ "lin2adpcm", audioop_lin2adpcm, METH_OLDARGS },
-	{ "tomono", audioop_tomono, METH_OLDARGS },
-	{ "tostereo", audioop_tostereo, METH_OLDARGS },
-	{ "getsample", audioop_getsample, METH_OLDARGS },
-	{ "reverse", audioop_reverse, METH_OLDARGS },
-	{ "ratecv", audioop_ratecv, METH_VARARGS },
-	{ 0,          0 }
+        { "max", audioop_max, METH_OLDARGS },
+        { "minmax", audioop_minmax, METH_OLDARGS },
+        { "avg", audioop_avg, METH_OLDARGS },
+        { "maxpp", audioop_maxpp, METH_OLDARGS },
+        { "avgpp", audioop_avgpp, METH_OLDARGS },
+        { "rms", audioop_rms, METH_OLDARGS },
+        { "findfit", audioop_findfit, METH_OLDARGS },
+        { "findmax", audioop_findmax, METH_OLDARGS },
+        { "findfactor", audioop_findfactor, METH_OLDARGS },
+        { "cross", audioop_cross, METH_OLDARGS },
+        { "mul", audioop_mul, METH_OLDARGS },
+        { "add", audioop_add, METH_OLDARGS },
+        { "bias", audioop_bias, METH_OLDARGS },
+        { "ulaw2lin", audioop_ulaw2lin, METH_OLDARGS },
+        { "lin2ulaw", audioop_lin2ulaw, METH_OLDARGS },
+        { "alaw2lin", audioop_alaw2lin, METH_OLDARGS },
+        { "lin2alaw", audioop_lin2alaw, METH_OLDARGS },
+        { "lin2lin", audioop_lin2lin, METH_OLDARGS },
+        { "adpcm2lin", audioop_adpcm2lin, METH_OLDARGS },
+        { "lin2adpcm", audioop_lin2adpcm, METH_OLDARGS },
+        { "tomono", audioop_tomono, METH_OLDARGS },
+        { "tostereo", audioop_tostereo, METH_OLDARGS },
+        { "getsample", audioop_getsample, METH_OLDARGS },
+        { "reverse", audioop_reverse, METH_OLDARGS },
+        { "ratecv", audioop_ratecv, METH_VARARGS },
+        { 0,          0 }
 };
 
 PyMODINIT_FUNC
 initaudioop(void)
 {
-	PyObject *m, *d;
-	m = Py_InitModule("audioop", audioop_methods);
-	if (m == NULL)
-		return;
-	d = PyModule_GetDict(m);
-	AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
-	if (AudioopError != NULL)
-	     PyDict_SetItemString(d,"error",AudioopError);
+        PyObject *m, *d;
+        m = Py_InitModule("audioop", audioop_methods);
+        if (m == NULL)
+                return;
+        d = PyModule_GetDict(m);
+        if (d == NULL)
+                return;
+        AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
+        if (AudioopError != NULL)
+             PyDict_SetItemString(d,"error",AudioopError);
 }
diff --git a/Modules/cPickle.c b/Modules/cPickle.c
index 727dcc9..18df599 100644
--- a/Modules/cPickle.c
+++ b/Modules/cPickle.c
@@ -123,7 +123,7 @@
   *__getstate___str, *__setstate___str, *__name___str, *__reduce___str,
   *__reduce_ex___str,
   *write_str, *append_str,
-  *read_str, *readline_str, *__main___str, *__basicnew___str,
+  *read_str, *readline_str, *__main___str, 
   *copy_reg_str, *dispatch_table_str;
 
 /*************************************************************************
@@ -2909,38 +2909,28 @@
 static int
 Pickler_traverse(Picklerobject *self, visitproc visit, void *arg)
 {
-	int err;
-#define VISIT(SLOT) \
-	if (SLOT) { \
-		err = visit((PyObject *)(SLOT), arg); \
-		if (err) \
-			return err; \
-	}
-	VISIT(self->write);
-	VISIT(self->memo);
-	VISIT(self->fast_memo);
-	VISIT(self->arg);
-	VISIT(self->file);
-	VISIT(self->pers_func);
-	VISIT(self->inst_pers_func);
-	VISIT(self->dispatch_table);
-#undef VISIT
+	Py_VISIT(self->write);
+	Py_VISIT(self->memo);
+	Py_VISIT(self->fast_memo);
+	Py_VISIT(self->arg);
+	Py_VISIT(self->file);
+	Py_VISIT(self->pers_func);
+	Py_VISIT(self->inst_pers_func);
+	Py_VISIT(self->dispatch_table);
 	return 0;
 }
 
 static int
 Pickler_clear(Picklerobject *self)
 {
-#define CLEAR(SLOT) Py_XDECREF(SLOT); SLOT = NULL;
-	CLEAR(self->write);
-	CLEAR(self->memo);
-	CLEAR(self->fast_memo);
-	CLEAR(self->arg);
-	CLEAR(self->file);
-	CLEAR(self->pers_func);
-	CLEAR(self->inst_pers_func);
-	CLEAR(self->dispatch_table);
-#undef CLEAR
+	Py_CLEAR(self->write);
+	Py_CLEAR(self->memo);
+	Py_CLEAR(self->fast_memo);
+	Py_CLEAR(self->arg);
+	Py_CLEAR(self->file);
+	Py_CLEAR(self->pers_func);
+	Py_CLEAR(self->inst_pers_func);
+	Py_CLEAR(self->dispatch_table);
 	return 0;
 }
 
@@ -5260,41 +5250,30 @@
 static int
 Unpickler_traverse(Unpicklerobject *self, visitproc visit, void *arg)
 {
-	int err;
-
-#define VISIT(SLOT) \
-	if (SLOT) { \
-		err = visit((PyObject *)(SLOT), arg); \
-		if (err) \
-			return err; \
-	}
-	VISIT(self->readline);
-	VISIT(self->read);
-	VISIT(self->file);
-	VISIT(self->memo);
-	VISIT(self->stack);
-	VISIT(self->pers_func);
-	VISIT(self->arg);
-	VISIT(self->last_string);
-	VISIT(self->find_class);
-#undef VISIT
+	Py_VISIT(self->readline);
+	Py_VISIT(self->read);
+	Py_VISIT(self->file);
+	Py_VISIT(self->memo);
+	Py_VISIT(self->stack);
+	Py_VISIT(self->pers_func);
+	Py_VISIT(self->arg);
+	Py_VISIT(self->last_string);
+	Py_VISIT(self->find_class);
 	return 0;
 }
 
 static int
 Unpickler_clear(Unpicklerobject *self)
 {
-#define CLEAR(SLOT) Py_XDECREF(SLOT); SLOT = NULL
-	CLEAR(self->readline);
-	CLEAR(self->read);
-	CLEAR(self->file);
-	CLEAR(self->memo);
-	CLEAR(self->stack);
-	CLEAR(self->pers_func);
-	CLEAR(self->arg);
-	CLEAR(self->last_string);
-	CLEAR(self->find_class);
-#undef CLEAR
+	Py_CLEAR(self->readline);
+	Py_CLEAR(self->read);
+	Py_CLEAR(self->file);
+	Py_CLEAR(self->memo);
+	Py_CLEAR(self->stack);
+	Py_CLEAR(self->pers_func);
+	Py_CLEAR(self->arg);
+	Py_CLEAR(self->last_string);
+	Py_CLEAR(self->find_class);
 	return 0;
 }
 
@@ -5602,7 +5581,6 @@
 	INIT_STR(readline);
 	INIT_STR(copy_reg);
 	INIT_STR(dispatch_table);
-	INIT_STR(__basicnew__);
 
 	if (!( copy_reg = PyImport_ImportModule("copy_reg")))
 		return -1;
diff --git a/Modules/cStringIO.c b/Modules/cStringIO.c
index bdc9f00..4debb72 100644
--- a/Modules/cStringIO.c
+++ b/Modules/cStringIO.c
@@ -503,17 +503,17 @@
   0,	       			/*tp_itemsize*/
   /* methods */
   (destructor)O_dealloc,	/*tp_dealloc*/
-  (printfunc)0,			/*tp_print*/
+  0,				/*tp_print*/
   0,		 		/*tp_getattr */
   0,		 		/*tp_setattr */
-  (cmpfunc)0,			/*tp_compare*/
-  (reprfunc)0,			/*tp_repr*/
+  0,				/*tp_compare*/
+  0,				/*tp_repr*/
   0,				/*tp_as_number*/
   0,				/*tp_as_sequence*/
   0,				/*tp_as_mapping*/
-  (hashfunc)0,			/*tp_hash*/
-  (ternaryfunc)0,		/*tp_call*/
-  (reprfunc)0,			/*tp_str*/
+  0,				/*tp_hash*/
+  0	,			/*tp_call*/
+  0,				/*tp_str*/
   0,				/*tp_getattro */
   0,				/*tp_setattro */
   0,				/*tp_as_buffer */
@@ -624,17 +624,17 @@
   0,					/*tp_itemsize*/
   /* methods */
   (destructor)I_dealloc,		/*tp_dealloc*/
-  (printfunc)0,				/*tp_print*/
+  0,					/*tp_print*/
   0,		 			/* tp_getattr */
-  (setattrfunc)0,			/*tp_setattr*/
-  (cmpfunc)0,				/*tp_compare*/
-  (reprfunc)0,				/*tp_repr*/
+  0,					/*tp_setattr*/
+  0,					/*tp_compare*/
+  0,					/*tp_repr*/
   0,					/*tp_as_number*/
   0,					/*tp_as_sequence*/
   0,					/*tp_as_mapping*/
-  (hashfunc)0,				/*tp_hash*/
-  (ternaryfunc)0,			/*tp_call*/
-  (reprfunc)0,				/*tp_str*/
+  0,					/*tp_hash*/
+  0,					/*tp_call*/
+  0,					/*tp_str*/
   0,					/* tp_getattro */
   0,					/* tp_setattro */
   0,					/* tp_as_buffer */
diff --git a/Modules/ccpython.cc b/Modules/ccpython.cc
deleted file mode 100644
index a6e97ff..0000000
--- a/Modules/ccpython.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Minimal main program -- everything is loaded from the library */
-
-#include "Python.h"
-
-extern "C"
-DL_EXPORT(int) Py_Main( int argc, char *argv[] );
-
-int main( int argc, char *argv[] )
-{
-	return Py_Main(argc, argv);
-}
diff --git a/Modules/cjkcodecs/_codecs_cn.c b/Modules/cjkcodecs/_codecs_cn.c
index fd048d9..fb51297 100644
--- a/Modules/cjkcodecs/_codecs_cn.c
+++ b/Modules/cjkcodecs/_codecs_cn.c
@@ -217,11 +217,8 @@
 					break;
 				}
 
-			if (utrrange->first == 0) {
-				PyErr_SetString(PyExc_RuntimeError,
-						"unicode mapping invalid");
+			if (utrrange->first == 0)
 				return 1;
-			}
 			continue;
 		}
 
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index f51b6f2..340de18 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -6,6 +6,7 @@
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
+#include "structmember.h"
 #include "multibytecodec.h"
 
 typedef struct {
@@ -38,22 +39,14 @@
 are 'ignore' and 'replace' as well as any other name registerd with\n\
 codecs.register_error that is able to handle UnicodeDecodeErrors.");
 
-PyDoc_STRVAR(MultibyteCodec_StreamReader__doc__,
-"I.StreamReader(stream[, errors]) -> StreamReader instance");
-
-PyDoc_STRVAR(MultibyteCodec_StreamWriter__doc__,
-"I.StreamWriter(stream[, errors]) -> StreamWriter instance");
-
 static char *codeckwarglist[] = {"input", "errors", NULL};
+static char *incnewkwarglist[] = {"errors", NULL};
+static char *incrementalkwarglist[] = {"input", "final", NULL};
 static char *streamkwarglist[] = {"stream", "errors", NULL};
 
 static PyObject *multibytecodec_encode(MultibyteCodec *,
 		MultibyteCodec_State *, const Py_UNICODE **, Py_ssize_t,
 		PyObject *, int);
-static PyObject *mbstreamreader_create(MultibyteCodec *,
-		PyObject *, const char *);
-static PyObject *mbstreamwriter_create(MultibyteCodec *,
-		PyObject *, const char *);
 
 #define MBENC_RESET	MBENC_MAX<<1 /* reset after an encoding session */
 
@@ -83,7 +76,7 @@
 }
 
 static PyObject *
-get_errorcallback(const char *errors)
+internal_error_callback(const char *errors)
 {
 	if (errors == NULL || strcmp(errors, "strict") == 0)
 		return ERROR_STRICT;
@@ -91,17 +84,88 @@
 		return ERROR_IGNORE;
 	else if (strcmp(errors, "replace") == 0)
 		return ERROR_REPLACE;
-	else {
-		return PyCodec_LookupError(errors);
-	}
+	else
+		return PyString_FromString(errors);
 }
 
+static PyObject *
+call_error_callback(PyObject *errors, PyObject *exc)
+{
+	PyObject *args, *cb, *r;
+
+	assert(PyString_Check(errors));
+	cb = PyCodec_LookupError(PyString_AS_STRING(errors));
+	if (cb == NULL)
+		return NULL;
+
+	args = PyTuple_New(1);
+	if (args == NULL) {
+		Py_DECREF(cb);
+		return NULL;
+	}
+
+	PyTuple_SET_ITEM(args, 0, exc);
+	Py_INCREF(exc);
+
+	r = PyObject_CallObject(cb, args);
+	Py_DECREF(args);
+	Py_DECREF(cb);
+	return r;
+}
+
+static PyObject *
+codecctx_errors_get(MultibyteStatefulCodecContext *self)
+{
+	const char *errors;
+
+	if (self->errors == ERROR_STRICT)
+		errors = "strict";
+	else if (self->errors == ERROR_IGNORE)
+		errors = "ignore";
+	else if (self->errors == ERROR_REPLACE)
+		errors = "replace";
+	else {
+		Py_INCREF(self->errors);
+		return self->errors;
+	}
+
+	return PyString_FromString(errors);
+}
+
+static int
+codecctx_errors_set(MultibyteStatefulCodecContext *self, PyObject *value,
+		    void *closure)
+{
+	PyObject *cb;
+
+	if (!PyString_Check(value)) {
+		PyErr_SetString(PyExc_TypeError, "errors must be a string");
+		return -1;
+	}
+
+	cb = internal_error_callback(PyString_AS_STRING(value));
+	if (cb == NULL)
+		return -1;
+
+	ERROR_DECREF(self->errors);
+	self->errors = cb;
+	return 0;
+}
+
+/* This getset handlers list is used by all the stateful codec objects */
+static PyGetSetDef codecctx_getsets[] = {
+	{"errors",	(getter)codecctx_errors_get,
+			(setter)codecctx_errors_set,
+			PyDoc_STR("how to treat errors")},
+	{NULL,}
+};
+
 static int
 expand_encodebuffer(MultibyteEncodeBuffer *buf, Py_ssize_t esize)
 {
 	Py_ssize_t orgpos, orgsize;
 
-	orgpos = (Py_ssize_t)((char*)buf->outbuf -
+	orgpos = (Py_ssize_t)((char *)buf->outbuf -
 				PyString_AS_STRING(buf->outobj));
 	orgsize = PyString_GET_SIZE(buf->outobj);
 	if (_PyString_Resize(&buf->outobj, orgsize + (
@@ -125,8 +189,7 @@
 {
 	Py_ssize_t orgpos, orgsize;
 
-	orgpos = (Py_ssize_t)(buf->outbuf -
-				PyUnicode_AS_UNICODE(buf->outobj));
+	orgpos = (Py_ssize_t)(buf->outbuf - PyUnicode_AS_UNICODE(buf->outobj));
 	orgsize = PyUnicode_GET_SIZE(buf->outobj);
 	if (PyUnicode_Resize(&buf->outobj, orgsize + (
 	    esize < (orgsize >> 1) ? (orgsize >> 1) | 1 : esize)) == -1)
@@ -144,16 +207,21 @@
 			goto errorexit;					\
 }
 
+
+/**
+ * MultibyteCodec object
+ */
+
 static int
 multibytecodec_encerror(MultibyteCodec *codec,
 			MultibyteCodec_State *state,
 			MultibyteEncodeBuffer *buf,
 			PyObject *errors, Py_ssize_t e)
 {
-	PyObject *retobj = NULL, *retstr = NULL, *argsobj, *tobj;
+	PyObject *retobj = NULL, *retstr = NULL, *tobj;
 	Py_ssize_t retstrsize, newpos;
-	const char *reason;
 	Py_ssize_t esize, start, end;
+	const char *reason;
 
 	if (e > 0) {
 		reason = "illegal multibyte sequence";
@@ -166,7 +234,7 @@
 			return 0; /* retry it */
 		case MBERR_TOOFEW:
 			reason = "incomplete multibyte sequence";
-			esize = (size_t)(buf->inbuf_end - buf->inbuf);
+			esize = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
 			break;
 		case MBERR_INTERNAL:
 			PyErr_SetString(PyExc_RuntimeError,
@@ -230,21 +298,15 @@
 		goto errorexit;
 	}
 
-	argsobj = PyTuple_New(1);
-	if (argsobj == NULL)
-		goto errorexit;
-
-	PyTuple_SET_ITEM(argsobj, 0, buf->excobj);
-	Py_INCREF(buf->excobj);
-	retobj = PyObject_CallObject(errors, argsobj);
-	Py_DECREF(argsobj);
+	retobj = call_error_callback(errors, buf->excobj);
 	if (retobj == NULL)
 		goto errorexit;
 
 	if (!PyTuple_Check(retobj) || PyTuple_GET_SIZE(retobj) != 2 ||
 	    !PyUnicode_Check((tobj = PyTuple_GET_ITEM(retobj, 0))) ||
-	    !PyInt_Check(PyTuple_GET_ITEM(retobj, 1))) {
-		PyErr_SetString(PyExc_ValueError,
+	    !(PyInt_Check(PyTuple_GET_ITEM(retobj, 1)) ||
+	      PyLong_Check(PyTuple_GET_ITEM(retobj, 1)))) {
+		PyErr_SetString(PyExc_TypeError,
 				"encoding error handler must return "
 				"(unicode, int) tuple");
 		goto errorexit;
@@ -267,12 +329,13 @@
 	buf->outbuf += retstrsize;
 
 	newpos = PyInt_AsSsize_t(PyTuple_GET_ITEM(retobj, 1));
-	if (newpos < 0)
+	if (newpos < 0 && !PyErr_Occurred())
 		newpos += (Py_ssize_t)(buf->inbuf_end - buf->inbuf_top);
 	if (newpos < 0 || buf->inbuf_top + newpos > buf->inbuf_end) {
+		PyErr_Clear();
 		PyErr_Format(PyExc_IndexError,
-			     "position %d from error handler out of bounds",
-			     (int)newpos);
+			     "position %zd from error handler out of bounds",
+			     newpos);
 		goto errorexit;
 	}
 	buf->inbuf = buf->inbuf_top + newpos;
@@ -293,7 +356,7 @@
 			MultibyteDecodeBuffer *buf,
 			PyObject *errors, Py_ssize_t e)
 {
-	PyObject *argsobj, *retobj = NULL, *retuni = NULL;
+	PyObject *retobj = NULL, *retuni = NULL;
 	Py_ssize_t retunisize, newpos;
 	const char *reason;
 	Py_ssize_t esize, start, end;
@@ -309,7 +372,7 @@
 			return 0; /* retry it */
 		case MBERR_TOOFEW:
 			reason = "incomplete multibyte sequence";
-			esize = (size_t)(buf->inbuf_end - buf->inbuf);
+			esize = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
 			break;
 		case MBERR_INTERNAL:
 			PyErr_SetString(PyExc_RuntimeError,
@@ -354,21 +417,15 @@
 		goto errorexit;
 	}
 
-	argsobj = PyTuple_New(1);
-	if (argsobj == NULL)
-		goto errorexit;
-
-	PyTuple_SET_ITEM(argsobj, 0, buf->excobj);
-	Py_INCREF(buf->excobj);
-	retobj = PyObject_CallObject(errors, argsobj);
-	Py_DECREF(argsobj);
+	retobj = call_error_callback(errors, buf->excobj);
 	if (retobj == NULL)
 		goto errorexit;
 
 	if (!PyTuple_Check(retobj) || PyTuple_GET_SIZE(retobj) != 2 ||
 	    !PyUnicode_Check((retuni = PyTuple_GET_ITEM(retobj, 0))) ||
-	    !PyInt_Check(PyTuple_GET_ITEM(retobj, 1))) {
-		PyErr_SetString(PyExc_ValueError,
+	    !(PyInt_Check(PyTuple_GET_ITEM(retobj, 1)) ||
+	      PyLong_Check(PyTuple_GET_ITEM(retobj, 1)))) {
+		PyErr_SetString(PyExc_TypeError,
 				"decoding error handler must return "
 				"(unicode, int) tuple");
 		goto errorexit;
@@ -383,12 +440,13 @@
 	}
 
 	newpos = PyInt_AsSsize_t(PyTuple_GET_ITEM(retobj, 1));
-	if (newpos < 0)
+	if (newpos < 0 && !PyErr_Occurred())
 		newpos += (Py_ssize_t)(buf->inbuf_end - buf->inbuf_top);
 	if (newpos < 0 || buf->inbuf_top + newpos > buf->inbuf_end) {
+		PyErr_Clear();
 		PyErr_Format(PyExc_IndexError,
-				"position %d from error handler out of bounds",
-				(int)newpos);
+			     "position %zd from error handler out of bounds",
+			     newpos);
 		goto errorexit;
 	}
 	buf->inbuf = buf->inbuf_top + newpos;
@@ -453,7 +511,7 @@
 				goto errorexit;
 		}
 
-	finalsize = (Py_ssize_t)((char*)buf.outbuf -
+	finalsize = (Py_ssize_t)((char *)buf.outbuf -
 				 PyString_AS_STRING(buf.outobj));
 
 	if (finalsize != PyString_GET_SIZE(buf.outobj))
@@ -500,7 +558,7 @@
 	data = PyUnicode_AS_UNICODE(arg);
 	datalen = PyUnicode_GET_SIZE(arg);
 
-	errorcb = get_errorcallback(errors);
+	errorcb = internal_error_callback(errors);
 	if (errorcb == NULL) {
 		Py_XDECREF(ucvt);
 		return NULL;
@@ -515,16 +573,12 @@
 	if (r == NULL)
 		goto errorexit;
 
-	if (errorcb > ERROR_MAX) {
-		Py_DECREF(errorcb);
-	}
+	ERROR_DECREF(errorcb);
 	Py_XDECREF(ucvt);
 	return make_tuple(r, datalen);
 
 errorexit:
-	if (errorcb > ERROR_MAX) {
-		Py_DECREF(errorcb);
-	}
+	ERROR_DECREF(errorcb);
 	Py_XDECREF(ucvt);
 	return NULL;
 }
@@ -543,18 +597,16 @@
 				codeckwarglist, &data, &datalen, &errors))
 		return NULL;
 
-	errorcb = get_errorcallback(errors);
+	errorcb = internal_error_callback(errors);
 	if (errorcb == NULL)
 		return NULL;
 
 	if (datalen == 0) {
-		if (errorcb > ERROR_MAX) {
-			Py_DECREF(errorcb);
-		}
+		ERROR_DECREF(errorcb);
 		return make_tuple(PyUnicode_FromUnicode(NULL, 0), 0);
 	}
 
-	buf.outobj = buf.excobj = NULL;
+	buf.excobj = NULL;
 	buf.inbuf = buf.inbuf_top = (unsigned char *)data;
 	buf.inbuf_end = buf.inbuf_top + datalen;
 	buf.outobj = PyUnicode_FromUnicode(NULL, datalen);
@@ -590,49 +642,17 @@
 			goto errorexit;
 
 	Py_XDECREF(buf.excobj);
-	if (errorcb > ERROR_MAX) {
-		Py_DECREF(errorcb);
-	}
+	ERROR_DECREF(errorcb);
 	return make_tuple(buf.outobj, datalen);
 
 errorexit:
-	if (errorcb > ERROR_MAX) {
-		Py_DECREF(errorcb);
-	}
+	ERROR_DECREF(errorcb);
 	Py_XDECREF(buf.excobj);
 	Py_XDECREF(buf.outobj);
 
 	return NULL;
 }
 
-static PyObject *
-MultibyteCodec_StreamReader(MultibyteCodecObject *self,
-			    PyObject *args, PyObject *kwargs)
-{
-	PyObject *stream;
-	char *errors = NULL;
-
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|s:StreamReader",
-				streamkwarglist, &stream, &errors))
-		return NULL;
-
-	return mbstreamreader_create(self->codec, stream, errors);
-}
-
-static PyObject *
-MultibyteCodec_StreamWriter(MultibyteCodecObject *self,
-			    PyObject *args, PyObject *kwargs)
-{
-	PyObject *stream;
-	char *errors = NULL;
-
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|s:StreamWriter",
-				streamkwarglist, &stream, &errors))
-		return NULL;
-
-	return mbstreamwriter_create(self->codec, stream, errors);
-}
-
 static struct PyMethodDef multibytecodec_methods[] = {
 	{"encode",	(PyCFunction)MultibyteCodec_Encode,
 			METH_VARARGS | METH_KEYWORDS,
@@ -640,12 +660,6 @@
 	{"decode",	(PyCFunction)MultibyteCodec_Decode,
 			METH_VARARGS | METH_KEYWORDS,
 			MultibyteCodec_Decode__doc__},
-	{"StreamReader",(PyCFunction)MultibyteCodec_StreamReader,
-			METH_VARARGS | METH_KEYWORDS,
-			MultibyteCodec_StreamReader__doc__},
-	{"StreamWriter",(PyCFunction)MultibyteCodec_StreamWriter,
-			METH_VARARGS | METH_KEYWORDS,
-			MultibyteCodec_StreamWriter__doc__},
 	{NULL,		NULL},
 };
 
@@ -655,8 +669,6 @@
 	PyObject_Del(self);
 }
 
-
-
 static PyTypeObject MultibyteCodec_Type = {
 	PyObject_HEAD_INIT(NULL)
 	0,				/* ob_size */
@@ -690,13 +702,498 @@
 	multibytecodec_methods,		/* tp_methods */
 };
 
+
+/**
+ * Utility functions for stateful codec mechanism
+ */
+
+#define STATEFUL_DCTX(o)	((MultibyteStatefulDecoderContext *)(o))
+#define STATEFUL_ECTX(o)	((MultibyteStatefulEncoderContext *)(o))
+
+static PyObject *
+encoder_encode_stateful(MultibyteStatefulEncoderContext *ctx,
+			PyObject *unistr, int final)
+{
+	PyObject *ucvt, *r = NULL;
+	Py_UNICODE *inbuf, *inbuf_end, *inbuf_tmp = NULL;
+	Py_ssize_t datalen, origpending;
+
+	if (PyUnicode_Check(unistr))
+		ucvt = NULL;
+	else {
+		unistr = ucvt = PyObject_Unicode(unistr);
+		if (unistr == NULL)
+			return NULL;
+		else if (!PyUnicode_Check(unistr)) {
+			PyErr_SetString(PyExc_TypeError,
+				"couldn't convert the object to unicode.");
+			Py_DECREF(ucvt);
+			return NULL;
+		}
+	}
+
+	datalen = PyUnicode_GET_SIZE(unistr);
+	origpending = ctx->pendingsize;
+
+	if (origpending > 0) {
+		inbuf_tmp = PyMem_New(Py_UNICODE, datalen + ctx->pendingsize);
+		if (inbuf_tmp == NULL)
+			goto errorexit;
+		memcpy(inbuf_tmp, ctx->pending,
+			Py_UNICODE_SIZE * ctx->pendingsize);
+		memcpy(inbuf_tmp + ctx->pendingsize,
+			PyUnicode_AS_UNICODE(unistr),
+			Py_UNICODE_SIZE * datalen);
+		datalen += ctx->pendingsize;
+		ctx->pendingsize = 0;
+		inbuf = inbuf_tmp;
+	}
+	else
+		inbuf = (Py_UNICODE *)PyUnicode_AS_UNICODE(unistr);
+
+	inbuf_end = inbuf + datalen;
+
+	r = multibytecodec_encode(ctx->codec, &ctx->state,
+			(const Py_UNICODE **)&inbuf,
+			datalen, ctx->errors, final ? MBENC_FLUSH : 0);
+	if (r == NULL) {
+		/* recover the original pending buffer */
+		if (origpending > 0)
+			memcpy(ctx->pending, inbuf_tmp,
+				Py_UNICODE_SIZE * origpending);
+		ctx->pendingsize = origpending;
+		goto errorexit;
+	}
+
+	if (inbuf < inbuf_end) {
+		ctx->pendingsize = (Py_ssize_t)(inbuf_end - inbuf);
+		if (ctx->pendingsize > MAXENCPENDING) {
+			/* normal codecs can't reach here */
+			ctx->pendingsize = 0;
+			PyErr_SetString(PyExc_UnicodeError,
+					"pending buffer overflow");
+			goto errorexit;
+		}
+		memcpy(ctx->pending, inbuf,
+			ctx->pendingsize * Py_UNICODE_SIZE);
+	}
+
+	if (inbuf_tmp != NULL)
+		PyMem_Del(inbuf_tmp);
+	Py_XDECREF(ucvt);
+	return r;
+
+errorexit:
+	if (inbuf_tmp != NULL)
+		PyMem_Del(inbuf_tmp);
+	Py_XDECREF(r);
+	Py_XDECREF(ucvt);
+	return NULL;
+}
+
+static int
+decoder_append_pending(MultibyteStatefulDecoderContext *ctx,
+		       MultibyteDecodeBuffer *buf)
+{
+	Py_ssize_t npendings;
+
+	npendings = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
+	if (npendings + ctx->pendingsize > MAXDECPENDING) {
+		PyErr_SetString(PyExc_UnicodeError, "pending buffer overflow");
+		return -1;
+	}
+	memcpy(ctx->pending + ctx->pendingsize, buf->inbuf, npendings);
+	ctx->pendingsize += npendings;
+	return 0;
+}
+
+static int
+decoder_prepare_buffer(MultibyteDecodeBuffer *buf, const char *data,
+		       Py_ssize_t size)
+{
+	buf->inbuf = buf->inbuf_top = (const unsigned char *)data;
+	buf->inbuf_end = buf->inbuf_top + size;
+	if (buf->outobj == NULL) { /* only if outobj is not allocated yet */
+		buf->outobj = PyUnicode_FromUnicode(NULL, size);
+		if (buf->outobj == NULL)
+			return -1;
+		buf->outbuf = PyUnicode_AS_UNICODE(buf->outobj);
+		buf->outbuf_end = buf->outbuf +
+				  PyUnicode_GET_SIZE(buf->outobj);
+	}
+
+	return 0;
+}
+
+static int
+decoder_feed_buffer(MultibyteStatefulDecoderContext *ctx,
+		    MultibyteDecodeBuffer *buf)
+{
+	while (buf->inbuf < buf->inbuf_end) {
+		Py_ssize_t inleft, outleft;
+		int r;
+
+		inleft = (Py_ssize_t)(buf->inbuf_end - buf->inbuf);
+		outleft = (Py_ssize_t)(buf->outbuf_end - buf->outbuf);
+
+		r = ctx->codec->decode(&ctx->state, ctx->codec->config,
+			&buf->inbuf, inleft, &buf->outbuf, outleft);
+		if (r == 0 || r == MBERR_TOOFEW)
+			break;
+		else if (multibytecodec_decerror(ctx->codec, &ctx->state,
+						 buf, ctx->errors, r))
+			return -1;
+	}
+	return 0;
+}
+
+
+/**
+ * MultibyteIncrementalEncoder object
+ */
+
+static PyObject *
+mbiencoder_encode(MultibyteIncrementalEncoderObject *self,
+		  PyObject *args, PyObject *kwargs)
+{
+	PyObject *data;
+	int final = 0;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:encode",
+			incrementalkwarglist, &data, &final))
+		return NULL;
+
+	return encoder_encode_stateful(STATEFUL_ECTX(self), data, final);
+}
+
+static PyObject *
+mbiencoder_reset(MultibyteIncrementalEncoderObject *self)
+{
+	if (self->codec->decreset != NULL &&
+	    self->codec->decreset(&self->state, self->codec->config) != 0)
+		return NULL;
+	self->pendingsize = 0;
+
+	Py_RETURN_NONE;
+}
+
+static struct PyMethodDef mbiencoder_methods[] = {
+	{"encode",	(PyCFunction)mbiencoder_encode,
+			METH_VARARGS | METH_KEYWORDS, NULL},
+	{"reset",	(PyCFunction)mbiencoder_reset,
+			METH_NOARGS, NULL},
+	{NULL,		NULL},
+};
+
+static PyObject *
+mbiencoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	MultibyteIncrementalEncoderObject *self;
+	PyObject *codec = NULL;
+	char *errors = NULL;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s:IncrementalEncoder",
+					 incnewkwarglist, &errors))
+		return NULL;
+
+	self = (MultibyteIncrementalEncoderObject *)type->tp_alloc(type, 0);
+	if (self == NULL)
+		return NULL;
+
+	codec = PyObject_GetAttrString((PyObject *)type, "codec");
+	if (codec == NULL)
+		goto errorexit;
+	if (!MultibyteCodec_Check(codec)) {
+		PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
+		goto errorexit;
+	}
+
+	self->codec = ((MultibyteCodecObject *)codec)->codec;
+	self->pendingsize = 0;
+	self->errors = internal_error_callback(errors);
+	if (self->errors == NULL)
+		goto errorexit;
+	if (self->codec->encinit != NULL &&
+	    self->codec->encinit(&self->state, self->codec->config) != 0)
+		goto errorexit;
+
+	Py_DECREF(codec);
+	return (PyObject *)self;
+
+errorexit:
+	Py_XDECREF(self);
+	Py_XDECREF(codec);
+	return NULL;
+}
+
+static int
+mbiencoder_traverse(MultibyteIncrementalEncoderObject *self,
+		    visitproc visit, void *arg)
+{
+	if (ERROR_ISCUSTOM(self->errors))
+		Py_VISIT(self->errors);
+	return 0;
+}
+
+static void
+mbiencoder_dealloc(MultibyteIncrementalEncoderObject *self)
+{
+	PyObject_GC_UnTrack(self);
+	ERROR_DECREF(self->errors);
+	self->ob_type->tp_free(self);
+}
+
+static PyTypeObject MultibyteIncrementalEncoder_Type = {
+	PyObject_HEAD_INIT(NULL)
+	0,				/* ob_size */
+	"MultibyteIncrementalEncoder",	/* tp_name */
+	sizeof(MultibyteIncrementalEncoderObject), /* tp_basicsize */
+	0,				/* tp_itemsize */
+	/*  methods  */
+	(destructor)mbiencoder_dealloc, /* tp_dealloc */
+	0,				/* tp_print */
+	0,				/* tp_getattr */
+	0,				/* tp_setattr */
+	0,				/* tp_compare */
+	0,				/* tp_repr */
+	0,				/* tp_as_number */
+	0,				/* tp_as_sequence */
+	0,				/* tp_as_mapping */
+	0,				/* tp_hash */
+	0,				/* tp_call */
+	0,				/* tp_str */
+	PyObject_GenericGetAttr,	/* tp_getattro */
+	0,				/* tp_setattro */
+	0,				/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
+		| Py_TPFLAGS_BASETYPE,	/* tp_flags */
+	0,				/* tp_doc */
+	(traverseproc)mbiencoder_traverse,	/* tp_traverse */
+	0,				/* tp_clear */
+	0,				/* tp_richcompare */
+	0,				/* tp_weaklistoffset */
+	0,				/* tp_iter */
+	0,				/* tp_iterext */
+	mbiencoder_methods,		/* tp_methods */
+	0,				/* tp_members */
+	codecctx_getsets,		/* tp_getset */
+	0,				/* tp_base */
+	0,				/* tp_dict */
+	0,				/* tp_descr_get */
+	0,				/* tp_descr_set */
+	0,				/* tp_dictoffset */
+	0,				/* tp_init */
+	0,				/* tp_alloc */
+	mbiencoder_new,			/* tp_new */
+};
+
+
+/**
+ * MultibyteIncrementalDecoder object
+ */
+
+static PyObject *
+mbidecoder_decode(MultibyteIncrementalDecoderObject *self,
+		  PyObject *args, PyObject *kwargs)
+{
+	MultibyteDecodeBuffer buf;
+	char *data, *wdata;
+	Py_ssize_t wsize, finalsize = 0, size, origpending;
+	int final = 0;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "t#|i:decode",
+			incrementalkwarglist, &data, &size, &final))
+		return NULL;
+
+	buf.outobj = buf.excobj = NULL;
+	origpending = self->pendingsize;
+
+	if (self->pendingsize == 0) {
+		wsize = size;
+		wdata = data;
+	}
+	else {
+		wsize = size + self->pendingsize;
+		wdata = PyMem_Malloc(wsize);
+		if (wdata == NULL)
+			goto errorexit;
+		memcpy(wdata, self->pending, self->pendingsize);
+		memcpy(wdata + self->pendingsize, data, size);
+		self->pendingsize = 0;
+	}
+
+	if (decoder_prepare_buffer(&buf, wdata, wsize) != 0)
+		goto errorexit;
+
+	if (decoder_feed_buffer(STATEFUL_DCTX(self), &buf))
+		goto errorexit;
+
+	if (final && buf.inbuf < buf.inbuf_end) {
+		if (multibytecodec_decerror(self->codec, &self->state,
+				&buf, self->errors, MBERR_TOOFEW)) {
+			/* recover the original pending buffer */
+			memcpy(self->pending, wdata, origpending);
+			self->pendingsize = origpending;
+			goto errorexit;
+		}
+	}
+
+	if (buf.inbuf < buf.inbuf_end) { /* pending sequence still exists */
+		if (decoder_append_pending(STATEFUL_DCTX(self), &buf) != 0)
+			goto errorexit;
+	}
+
+	finalsize = (Py_ssize_t)(buf.outbuf - PyUnicode_AS_UNICODE(buf.outobj));
+	if (finalsize != PyUnicode_GET_SIZE(buf.outobj))
+		if (PyUnicode_Resize(&buf.outobj, finalsize) == -1)
+			goto errorexit;
+
+	if (wdata != data)
+		PyMem_Del(wdata);
+	Py_XDECREF(buf.excobj);
+	return buf.outobj;
+
+errorexit:
+	if (wdata != NULL && wdata != data)
+		PyMem_Del(wdata);
+	Py_XDECREF(buf.excobj);
+	Py_XDECREF(buf.outobj);
+	return NULL;
+}
+
+static PyObject *
+mbidecoder_reset(MultibyteIncrementalDecoderObject *self)
+{
+	if (self->codec->decreset != NULL &&
+	    self->codec->decreset(&self->state, self->codec->config) != 0)
+		return NULL;
+	self->pendingsize = 0;
+
+	Py_RETURN_NONE;
+}
+
+static struct PyMethodDef mbidecoder_methods[] = {
+	{"decode",	(PyCFunction)mbidecoder_decode,
+			METH_VARARGS | METH_KEYWORDS, NULL},
+	{"reset",	(PyCFunction)mbidecoder_reset,
+			METH_NOARGS, NULL},
+	{NULL,		NULL},
+};
+
+static PyObject *
+mbidecoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	MultibyteIncrementalDecoderObject *self;
+	PyObject *codec = NULL;
+	char *errors = NULL;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s:IncrementalDecoder",
+					 incnewkwarglist, &errors))
+		return NULL;
+
+	self = (MultibyteIncrementalDecoderObject *)type->tp_alloc(type, 0);
+	if (self == NULL)
+		return NULL;
+
+	codec = PyObject_GetAttrString((PyObject *)type, "codec");
+	if (codec == NULL)
+		goto errorexit;
+	if (!MultibyteCodec_Check(codec)) {
+		PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
+		goto errorexit;
+	}
+
+	self->codec = ((MultibyteCodecObject *)codec)->codec;
+	self->pendingsize = 0;
+	self->errors = internal_error_callback(errors);
+	if (self->errors == NULL)
+		goto errorexit;
+	if (self->codec->decinit != NULL &&
+	    self->codec->decinit(&self->state, self->codec->config) != 0)
+		goto errorexit;
+
+	Py_DECREF(codec);
+	return (PyObject *)self;
+
+errorexit:
+	Py_XDECREF(self);
+	Py_XDECREF(codec);
+	return NULL;
+}
+
+static int
+mbidecoder_traverse(MultibyteIncrementalDecoderObject *self,
+		    visitproc visit, void *arg)
+{
+	if (ERROR_ISCUSTOM(self->errors))
+		Py_VISIT(self->errors);
+	return 0;
+}
+
+static void
+mbidecoder_dealloc(MultibyteIncrementalDecoderObject *self)
+{
+	PyObject_GC_UnTrack(self);
+	ERROR_DECREF(self->errors);
+	self->ob_type->tp_free(self);
+}
+
+static PyTypeObject MultibyteIncrementalDecoder_Type = {
+	PyObject_HEAD_INIT(NULL)
+	0,				/* ob_size */
+	"MultibyteIncrementalDecoder",	/* tp_name */
+	sizeof(MultibyteIncrementalDecoderObject), /* tp_basicsize */
+	0,				/* tp_itemsize */
+	/*  methods  */
+	(destructor)mbidecoder_dealloc, /* tp_dealloc */
+	0,				/* tp_print */
+	0,				/* tp_getattr */
+	0,				/* tp_setattr */
+	0,				/* tp_compare */
+	0,				/* tp_repr */
+	0,				/* tp_as_number */
+	0,				/* tp_as_sequence */
+	0,				/* tp_as_mapping */
+	0,				/* tp_hash */
+	0,				/* tp_call */
+	0,				/* tp_str */
+	PyObject_GenericGetAttr,	/* tp_getattro */
+	0,				/* tp_setattro */
+	0,				/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
+		| Py_TPFLAGS_BASETYPE,	/* tp_flags */
+	0,				/* tp_doc */
+	(traverseproc)mbidecoder_traverse,	/* tp_traverse */
+	0,				/* tp_clear */
+	0,				/* tp_richcompare */
+	0,				/* tp_weaklistoffset */
+	0,				/* tp_iter */
+	0,				/* tp_iterext */
+	mbidecoder_methods,		/* tp_methods */
+	0,				/* tp_members */
+	codecctx_getsets,		/* tp_getset */
+	0,				/* tp_base */
+	0,				/* tp_dict */
+	0,				/* tp_descr_get */
+	0,				/* tp_descr_set */
+	0,				/* tp_dictoffset */
+	0,				/* tp_init */
+	0,				/* tp_alloc */
+	mbidecoder_new,			/* tp_new */
+};
+
+
+/**
+ * MultibyteStreamReader object
+ */
+
 static PyObject *
 mbstreamreader_iread(MultibyteStreamReaderObject *self,
 		     const char *method, Py_ssize_t sizehint)
 {
 	MultibyteDecodeBuffer buf;
 	PyObject *cres;
-	Py_ssize_t rsize, r, finalsize = 0;
+	Py_ssize_t rsize, finalsize = 0;
 
 	if (sizehint == 0)
 		return PyUnicode_FromUnicode(NULL, 0);
@@ -740,39 +1237,13 @@
 		}
 
 		rsize = PyString_GET_SIZE(cres);
-		buf.inbuf = buf.inbuf_top =
-			(unsigned char *)PyString_AS_STRING(cres);
-		buf.inbuf_end = buf.inbuf_top + rsize;
-		if (buf.outobj == NULL) {
-			buf.outobj = PyUnicode_FromUnicode(NULL, rsize);
-			if (buf.outobj == NULL)
-				goto errorexit;
-			buf.outbuf = PyUnicode_AS_UNICODE(buf.outobj);
-			buf.outbuf_end = buf.outbuf +
-					PyUnicode_GET_SIZE(buf.outobj);
-		}
+		if (decoder_prepare_buffer(&buf, PyString_AS_STRING(cres),
+					   rsize) != 0)
+			goto errorexit;
 
-		r = 0;
-		if (rsize > 0)
-			while (buf.inbuf < buf.inbuf_end) {
-				Py_ssize_t inleft, outleft;
-
-				inleft = (Py_ssize_t)(buf.inbuf_end -
-						      buf.inbuf);
-				outleft = (Py_ssize_t)(buf.outbuf_end -
-						       buf.outbuf);
-
-				r = self->codec->decode(&self->state,
-							self->codec->config,
-							&buf.inbuf, inleft,
-							&buf.outbuf, outleft);
-				if (r == 0 || r == MBERR_TOOFEW)
-					break;
-				else if (multibytecodec_decerror(self->codec,
-						&self->state, &buf,
-						self->errors, r))
-					goto errorexit;
-			}
+		if (rsize > 0 && decoder_feed_buffer(
+				(MultibyteStatefulDecoderContext *)self, &buf))
+			goto errorexit;
 
 		if (rsize == 0 || sizehint < 0) { /* end of file */
 			if (buf.inbuf < buf.inbuf_end &&
@@ -782,20 +1253,9 @@
 		}
 
 		if (buf.inbuf < buf.inbuf_end) { /* pending sequence exists */
-			Py_ssize_t npendings;
-
-			/* we can't assume that pendingsize is still 0 here.
-			 * because this function can be called recursively
-			 * from error callback */
-			npendings = (Py_ssize_t)(buf.inbuf_end - buf.inbuf);
-			if (npendings + self->pendingsize > MAXDECPENDING) {
-				PyErr_SetString(PyExc_RuntimeError,
-						"pending buffer overflow");
+			if (decoder_append_pending(STATEFUL_DCTX(self),
+						   &buf) != 0)
 				goto errorexit;
-			}
-			memcpy(self->pending + self->pendingsize, buf.inbuf,
-				npendings);
-			self->pendingsize += npendings;
 		}
 
 		finalsize = (Py_ssize_t)(buf.outbuf -
@@ -901,8 +1361,7 @@
 		return NULL;
 	self->pendingsize = 0;
 
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static struct PyMethodDef mbstreamreader_methods[] = {
@@ -917,18 +1376,75 @@
 	{NULL,		NULL},
 };
 
+static PyMemberDef mbstreamreader_members[] = {
+	{"stream",	T_OBJECT,
+			offsetof(MultibyteStreamReaderObject, stream),
+			READONLY, NULL},
+	{NULL,}
+};
+
+static PyObject *
+mbstreamreader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	MultibyteStreamReaderObject *self;
+	PyObject *stream, *codec = NULL;
+	char *errors = NULL;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:StreamReader",
+				streamkwarglist, &stream, &errors))
+		return NULL;
+
+	self = (MultibyteStreamReaderObject *)type->tp_alloc(type, 0);
+	if (self == NULL)
+		return NULL;
+
+	codec = PyObject_GetAttrString((PyObject *)type, "codec");
+	if (codec == NULL)
+		goto errorexit;
+	if (!MultibyteCodec_Check(codec)) {
+		PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
+		goto errorexit;
+	}
+
+	self->codec = ((MultibyteCodecObject *)codec)->codec;
+	self->stream = stream;
+	Py_INCREF(stream);
+	self->pendingsize = 0;
+	self->errors = internal_error_callback(errors);
+	if (self->errors == NULL)
+		goto errorexit;
+	if (self->codec->decinit != NULL &&
+	    self->codec->decinit(&self->state, self->codec->config) != 0)
+		goto errorexit;
+
+	Py_DECREF(codec);
+	return (PyObject *)self;
+
+errorexit:
+	Py_XDECREF(self);
+	Py_XDECREF(codec);
+	return NULL;
+}
+
+static int
+mbstreamreader_traverse(MultibyteStreamReaderObject *self,
+			visitproc visit, void *arg)
+{
+	if (ERROR_ISCUSTOM(self->errors))
+		Py_VISIT(self->errors);
+	Py_VISIT(self->stream);
+	return 0;
+}
+
 static void
 mbstreamreader_dealloc(MultibyteStreamReaderObject *self)
 {
-	if (self->errors > ERROR_MAX) {
-		Py_DECREF(self->errors);
-	}
+	PyObject_GC_UnTrack(self);
+	ERROR_DECREF(self->errors);
 	Py_DECREF(self->stream);
-	PyObject_Del(self);
+	self->ob_type->tp_free(self);
 }
 
-
-
 static PyTypeObject MultibyteStreamReader_Type = {
 	PyObject_HEAD_INIT(NULL)
 	0,				/* ob_size */
@@ -951,97 +1467,50 @@
 	PyObject_GenericGetAttr,	/* tp_getattro */
 	0,				/* tp_setattro */
 	0,				/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,		/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
+		| Py_TPFLAGS_BASETYPE,	/* tp_flags */
 	0,				/* tp_doc */
-	0,				/* tp_traverse */
+	(traverseproc)mbstreamreader_traverse,	/* tp_traverse */
 	0,				/* tp_clear */
 	0,				/* tp_richcompare */
 	0,				/* tp_weaklistoffset */
 	0,				/* tp_iter */
 	0,				/* tp_iterext */
 	mbstreamreader_methods,		/* tp_methods */
+	mbstreamreader_members,		/* tp_members */
+	codecctx_getsets,		/* tp_getset */
+	0,				/* tp_base */
+	0,				/* tp_dict */
+	0,				/* tp_descr_get */
+	0,				/* tp_descr_set */
+	0,				/* tp_dictoffset */
+	0,				/* tp_init */
+	0,				/* tp_alloc */
+	mbstreamreader_new,		/* tp_new */
 };
 
+
+/**
+ * MultibyteStreamWriter object
+ */
+
 static int
 mbstreamwriter_iwrite(MultibyteStreamWriterObject *self,
 		      PyObject *unistr)
 {
-	PyObject *wr, *ucvt, *r = NULL;
-	Py_UNICODE *inbuf, *inbuf_end, *inbuf_tmp = NULL;
-	Py_ssize_t datalen;
+	PyObject *str, *wr;
 
-	if (PyUnicode_Check(unistr))
-		ucvt = NULL;
-	else {
-		unistr = ucvt = PyObject_Unicode(unistr);
-		if (unistr == NULL)
-			return -1;
-		else if (!PyUnicode_Check(unistr)) {
-			PyErr_SetString(PyExc_TypeError,
-				"couldn't convert the object to unicode.");
-			Py_DECREF(ucvt);
-			return -1;
-		}
-	}
+	str = encoder_encode_stateful(STATEFUL_ECTX(self), unistr, 0);
+	if (str == NULL)
+		return -1;
 
-	datalen = PyUnicode_GET_SIZE(unistr);
-	if (datalen == 0) {
-		Py_XDECREF(ucvt);
-		return 0;
-	}
-
-	if (self->pendingsize > 0) {
-		inbuf_tmp = PyMem_New(Py_UNICODE, datalen + self->pendingsize);
-		if (inbuf_tmp == NULL)
-			goto errorexit;
-		memcpy(inbuf_tmp, self->pending,
-			Py_UNICODE_SIZE * self->pendingsize);
-		memcpy(inbuf_tmp + self->pendingsize,
-			PyUnicode_AS_UNICODE(unistr),
-			Py_UNICODE_SIZE * datalen);
-		datalen += self->pendingsize;
-		self->pendingsize = 0;
-		inbuf = inbuf_tmp;
-	}
-	else
-		inbuf = (Py_UNICODE *)PyUnicode_AS_UNICODE(unistr);
-
-	inbuf_end = inbuf + datalen;
-
-	r = multibytecodec_encode(self->codec, &self->state,
-			(const Py_UNICODE **)&inbuf, datalen, self->errors, 0);
-	if (r == NULL)
-		goto errorexit;
-
-	if (inbuf < inbuf_end) {
-		self->pendingsize = (Py_ssize_t)(inbuf_end - inbuf);
-		if (self->pendingsize > MAXENCPENDING) {
-			self->pendingsize = 0;
-			PyErr_SetString(PyExc_RuntimeError,
-					"pending buffer overflow");
-			goto errorexit;
-		}
-		memcpy(self->pending, inbuf,
-			self->pendingsize * Py_UNICODE_SIZE);
-	}
-
-	wr = PyObject_CallMethod(self->stream, "write", "O", r);
+	wr = PyObject_CallMethod(self->stream, "write", "O", str);
+	Py_DECREF(str);
 	if (wr == NULL)
-		goto errorexit;
+		return -1;
 
-	if (inbuf_tmp != NULL)
-		PyMem_Del(inbuf_tmp);
-	Py_DECREF(r);
 	Py_DECREF(wr);
-	Py_XDECREF(ucvt);
 	return 0;
-
-errorexit:
-	if (inbuf_tmp != NULL)
-		PyMem_Del(inbuf_tmp);
-	Py_XDECREF(r);
-	Py_XDECREF(ucvt);
-	return -1;
 }
 
 static PyObject *
@@ -1054,10 +1523,8 @@
 
 	if (mbstreamwriter_iwrite(self, strobj))
 		return NULL;
-	else {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+	else
+		Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1087,8 +1554,7 @@
 			return NULL;
 	}
 
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1119,18 +1585,69 @@
 	}
 	Py_DECREF(pwrt);
 
-	Py_INCREF(Py_None);
-	return Py_None;
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+mbstreamwriter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	MultibyteStreamWriterObject *self;
+	PyObject *stream, *codec = NULL;
+	char *errors = NULL;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:StreamWriter",
+				streamkwarglist, &stream, &errors))
+		return NULL;
+
+	self = (MultibyteStreamWriterObject *)type->tp_alloc(type, 0);
+	if (self == NULL)
+		return NULL;
+
+	codec = PyObject_GetAttrString((PyObject *)type, "codec");
+	if (codec == NULL)
+		goto errorexit;
+	if (!MultibyteCodec_Check(codec)) {
+		PyErr_SetString(PyExc_TypeError, "codec is unexpected type");
+		goto errorexit;
+	}
+
+	self->codec = ((MultibyteCodecObject *)codec)->codec;
+	self->stream = stream;
+	Py_INCREF(stream);
+	self->pendingsize = 0;
+	self->errors = internal_error_callback(errors);
+	if (self->errors == NULL)
+		goto errorexit;
+	if (self->codec->encinit != NULL &&
+	    self->codec->encinit(&self->state, self->codec->config) != 0)
+		goto errorexit;
+
+	Py_DECREF(codec);
+	return (PyObject *)self;
+
+errorexit:
+	Py_XDECREF(self);
+	Py_XDECREF(codec);
+	return NULL;
+}
+
+static int
+mbstreamwriter_traverse(MultibyteStreamWriterObject *self,
+			visitproc visit, void *arg)
+{
+	if (ERROR_ISCUSTOM(self->errors))
+		Py_VISIT(self->errors);
+	Py_VISIT(self->stream);
+	return 0;
 }
 
 static void
 mbstreamwriter_dealloc(MultibyteStreamWriterObject *self)
 {
-	if (self->errors > ERROR_MAX) {
-		Py_DECREF(self->errors);
-	}
+	PyObject_GC_UnTrack(self);
+	ERROR_DECREF(self->errors);
 	Py_DECREF(self->stream);
-	PyObject_Del(self);
+	self->ob_type->tp_free(self);
 }
 
 static struct PyMethodDef mbstreamwriter_methods[] = {
@@ -1143,7 +1660,12 @@
 	{NULL,		NULL},
 };
 
-
+static PyMemberDef mbstreamwriter_members[] = {
+	{"stream",	T_OBJECT,
+			offsetof(MultibyteStreamWriterObject, stream),
+			READONLY, NULL},
+	{NULL,}
+};
 
 static PyTypeObject MultibyteStreamWriter_Type = {
 	PyObject_HEAD_INIT(NULL)
@@ -1167,17 +1689,33 @@
 	PyObject_GenericGetAttr,	/* tp_getattro */
 	0,				/* tp_setattro */
 	0,				/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,		/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
+		| Py_TPFLAGS_BASETYPE,	/* tp_flags */
 	0,				/* tp_doc */
-	0,				/* tp_traverse */
+	(traverseproc)mbstreamwriter_traverse,	/* tp_traverse */
 	0,				/* tp_clear */
 	0,				/* tp_richcompare */
 	0,				/* tp_weaklistoffset */
 	0,				/* tp_iter */
 	0,				/* tp_iterext */
 	mbstreamwriter_methods,		/* tp_methods */
+	mbstreamwriter_members,		/* tp_members */
+	codecctx_getsets,		/* tp_getset */
+	0,				/* tp_base */
+	0,				/* tp_dict */
+	0,				/* tp_descr_get */
+	0,				/* tp_descr_set */
+	0,				/* tp_dictoffset */
+	0,				/* tp_init */
+	0,				/* tp_alloc */
+	mbstreamwriter_new,		/* tp_new */
 };
 
+
+/**
+ * Exposed factory function
+ */
+
 static PyObject *
 __create_codec(PyObject *ignore, PyObject *arg)
 {
@@ -1201,80 +1739,38 @@
 	return (PyObject *)self;
 }
 
-static PyObject *
-mbstreamreader_create(MultibyteCodec *codec,
-		      PyObject *stream, const char *errors)
-{
-	MultibyteStreamReaderObject *self;
-
-	self = PyObject_New(MultibyteStreamReaderObject,
-			&MultibyteStreamReader_Type);
-	if (self == NULL)
-		return NULL;
-
-	self->codec = codec;
-	self->stream = stream;
-	Py_INCREF(stream);
-	self->pendingsize = 0;
-	self->errors = get_errorcallback(errors);
-	if (self->errors == NULL)
-		goto errorexit;
-	if (self->codec->decinit != NULL &&
-	    self->codec->decinit(&self->state, self->codec->config) != 0)
-		goto errorexit;
-
-	return (PyObject *)self;
-
-errorexit:
-	Py_XDECREF(self);
-	return NULL;
-}
-
-static PyObject *
-mbstreamwriter_create(MultibyteCodec *codec,
-		      PyObject *stream, const char *errors)
-{
-	MultibyteStreamWriterObject *self;
-
-	self = PyObject_New(MultibyteStreamWriterObject,
-			&MultibyteStreamWriter_Type);
-	if (self == NULL)
-		return NULL;
-
-	self->codec = codec;
-	self->stream = stream;
-	Py_INCREF(stream);
-	self->pendingsize = 0;
-	self->errors = get_errorcallback(errors);
-	if (self->errors == NULL)
-		goto errorexit;
-	if (self->codec->encinit != NULL &&
-	    self->codec->encinit(&self->state, self->codec->config) != 0)
-		goto errorexit;
-
-	return (PyObject *)self;
-
-errorexit:
-	Py_XDECREF(self);
-	return NULL;
-}
-
 static struct PyMethodDef __methods[] = {
 	{"__create_codec", (PyCFunction)__create_codec, METH_O},
 	{NULL, NULL},
 };
 
-void
+PyMODINIT_FUNC
 init_multibytecodec(void)
 {
+	int i;
+	PyObject *m;
+	PyTypeObject *typelist[] = {
+		&MultibyteIncrementalEncoder_Type,
+		&MultibyteIncrementalDecoder_Type,
+		&MultibyteStreamReader_Type,
+		&MultibyteStreamWriter_Type,
+		NULL
+	};
+
 	if (PyType_Ready(&MultibyteCodec_Type) < 0)
 		return;
-	if (PyType_Ready(&MultibyteStreamReader_Type) < 0)
-		return;
-	if (PyType_Ready(&MultibyteStreamWriter_Type) < 0)
+
+	m = Py_InitModule("_multibytecodec", __methods);
+	if (m == NULL)
 		return;
 
-	Py_InitModule("_multibytecodec", __methods);
+	for (i = 0; typelist[i] != NULL; i++) {
+		if (PyType_Ready(typelist[i]) < 0)
+			return;
+		Py_INCREF(typelist[i]);
+		PyModule_AddObject(m, typelist[i]->tp_name,
+				   (PyObject *)typelist[i]);
+	}
 
 	if (PyErr_Occurred())
 		Py_FatalError("can't initialize the _multibytecodec module");
diff --git a/Modules/cjkcodecs/multibytecodec.h b/Modules/cjkcodecs/multibytecodec.h
index ec49c78..22ea5d4 100644
--- a/Modules/cjkcodecs/multibytecodec.h
+++ b/Modules/cjkcodecs/multibytecodec.h
@@ -67,24 +67,51 @@
 	MultibyteCodec *codec;
 } MultibyteCodecObject;
 
-#define MAXDECPENDING	8
+#define MultibyteCodec_Check(op) ((op)->ob_type == &MultibyteCodec_Type)
+
+#define _MultibyteStatefulCodec_HEAD		\
+	PyObject_HEAD				\
+	MultibyteCodec *codec;			\
+	MultibyteCodec_State state;		\
+	PyObject *errors;
 typedef struct {
-	PyObject_HEAD
-	MultibyteCodec *codec;
-	MultibyteCodec_State state;
-	unsigned char pending[MAXDECPENDING];
-	Py_ssize_t pendingsize;
-	PyObject *stream, *errors;
-} MultibyteStreamReaderObject;
+	_MultibyteStatefulCodec_HEAD
+} MultibyteStatefulCodecContext;
 
 #define MAXENCPENDING	2
-typedef struct {
-	PyObject_HEAD
-	MultibyteCodec *codec;
-	MultibyteCodec_State state;
-	Py_UNICODE pending[MAXENCPENDING];
+#define _MultibyteStatefulEncoder_HEAD		\
+	_MultibyteStatefulCodec_HEAD		\
+	Py_UNICODE pending[MAXENCPENDING];	\
 	Py_ssize_t pendingsize;
-	PyObject *stream, *errors;
+typedef struct {
+	_MultibyteStatefulEncoder_HEAD
+} MultibyteStatefulEncoderContext;
+
+#define MAXDECPENDING	8
+#define _MultibyteStatefulDecoder_HEAD		\
+	_MultibyteStatefulCodec_HEAD		\
+	unsigned char pending[MAXDECPENDING];	\
+	Py_ssize_t pendingsize;
+typedef struct {
+	_MultibyteStatefulDecoder_HEAD
+} MultibyteStatefulDecoderContext;
+
+typedef struct {
+	_MultibyteStatefulEncoder_HEAD
+} MultibyteIncrementalEncoderObject;
+
+typedef struct {
+	_MultibyteStatefulDecoder_HEAD
+} MultibyteIncrementalDecoderObject;
+
+typedef struct {
+	_MultibyteStatefulDecoder_HEAD
+	PyObject *stream;
+} MultibyteStreamReaderObject;
+
+typedef struct {
+	_MultibyteStatefulEncoder_HEAD
+	PyObject *stream;
 } MultibyteStreamWriterObject;
 
 /* positive values for illegal sequences */
@@ -95,7 +122,12 @@
 #define ERROR_STRICT		(PyObject *)(1)
 #define ERROR_IGNORE		(PyObject *)(2)
 #define ERROR_REPLACE		(PyObject *)(3)
-#define ERROR_MAX		ERROR_REPLACE
+#define ERROR_ISCUSTOM(p)	((p) < ERROR_STRICT || ERROR_REPLACE < (p))
+#define ERROR_DECREF(p) do {			\
+	if (p != NULL && ERROR_ISCUSTOM(p)) {	\
+		Py_DECREF(p);			\
+	}					\
+} while (0);
 
 #define MBENC_FLUSH		0x0001 /* encode all characters encodable */
 #define MBENC_MAX		MBENC_FLUSH
diff --git a/Modules/collectionsmodule.c b/Modules/collectionsmodule.c
index b80ab07..c7e2c85 100644
--- a/Modules/collectionsmodule.c
+++ b/Modules/collectionsmodule.c
@@ -832,11 +832,11 @@
 	0,				/* tp_itemsize */
 	/* methods */
 	(destructor)deque_dealloc,	/* tp_dealloc */
-	(printfunc)deque_tp_print,	/* tp_print */
+	deque_tp_print,			/* tp_print */
 	0,				/* tp_getattr */
 	0,				/* tp_setattr */
 	0,				/* tp_compare */
-	(reprfunc)deque_repr,		/* tp_repr */
+	deque_repr,			/* tp_repr */
 	0,				/* tp_as_number */
 	&deque_as_sequence,		/* tp_as_sequence */
 	0,				/* tp_as_mapping */
@@ -1236,10 +1236,7 @@
 static int
 defdict_tp_clear(defdictobject *dd)
 {
-	if (dd->default_factory != NULL) {
-		Py_DECREF(dd->default_factory);
-		dd->default_factory = NULL;
-	}
+	Py_CLEAR(dd->default_factory);
 	return PyDict_Type.tp_clear((PyObject *)dd);
 }
 
@@ -1277,8 +1274,11 @@
 A defaultdict compares equal to a dict with the same items.\n\
 ");
 
+/* See comment in xxsubtype.c */
+#define DEFERRED_ADDRESS(ADDR) 0
+
 static PyTypeObject defdict_type = {
-	PyObject_HEAD_INIT(NULL)
+	PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
 	0,				/* ob_size */
 	"collections.defaultdict",	/* tp_name */
 	sizeof(defdictobject),		/* tp_basicsize */
@@ -1302,7 +1302,7 @@
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
 		Py_TPFLAGS_HAVE_WEAKREFS,	/* tp_flags */
 	defdict_doc,			/* tp_doc */
-	(traverseproc)defdict_traverse,	/* tp_traverse */
+	defdict_traverse,		/* tp_traverse */
 	(inquiry)defdict_tp_clear,	/* tp_clear */
 	0,				/* tp_richcompare */
 	0,				/* tp_weaklistoffset*/
@@ -1311,12 +1311,12 @@
 	defdict_methods,		/* tp_methods */
 	defdict_members,		/* tp_members */
 	0,				/* tp_getset */
-	&PyDict_Type,			/* tp_base */
+	DEFERRED_ADDRESS(&PyDict_Type),	/* tp_base */
 	0,				/* tp_dict */
 	0,				/* tp_descr_get */
 	0,				/* tp_descr_set */
 	0,				/* tp_dictoffset */
-	(initproc)defdict_init,		/* tp_init */
+	defdict_init,			/* tp_init */
 	PyType_GenericAlloc,		/* tp_alloc */
 	0,				/* tp_new */
 	PyObject_GC_Del,		/* tp_free */
@@ -1344,6 +1344,7 @@
 	Py_INCREF(&deque_type);
 	PyModule_AddObject(m, "deque", (PyObject *)&deque_type);
 
+	defdict_type.tp_base = &PyDict_Type;
 	if (PyType_Ready(&defdict_type) < 0)
 		return;
 	Py_INCREF(&defdict_type);
diff --git a/Modules/config.c.in b/Modules/config.c.in
index 9ec281c..f811991 100644
--- a/Modules/config.c.in
+++ b/Modules/config.c.in
@@ -17,6 +17,10 @@
 
 #include "Python.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 
 /* -- ADDMODULE MARKER 1 -- */
 
@@ -50,3 +54,9 @@
 	/* Sentinel */
 	{0, 0}
 };
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index c1a0cb3..9ae235a 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -1228,8 +1228,8 @@
 				}
 			}
 			assert(zreplacement != NULL);
-			ptoappend = PyString_AsString(zreplacement);
-			ntoappend = PyString_Size(zreplacement);
+			ptoappend = PyString_AS_STRING(zreplacement);
+			ntoappend = PyString_GET_SIZE(zreplacement);
 		}
 		else if (ch == 'Z') {
 			/* format tzname */
@@ -1257,14 +1257,18 @@
 						Py_DECREF(temp);
 						if (Zreplacement == NULL)
 							goto Done;
+						if (!PyString_Check(Zreplacement)) {
+							PyErr_SetString(PyExc_TypeError, "tzname.replace() did not return a string");
+							goto Done;
+						}
 					}
 					else
 						Py_DECREF(temp);
 				}
 			}
 			assert(Zreplacement != NULL);
-			ptoappend = PyString_AsString(Zreplacement);
-			ntoappend = PyString_Size(Zreplacement);
+			ptoappend = PyString_AS_STRING(Zreplacement);
+			ntoappend = PyString_GET_SIZE(Zreplacement);
 		}
 		else {
 			/* percent followed by neither z nor Z */
@@ -1275,6 +1279,7 @@
  		/* Append the ntoappend chars starting at ptoappend to
  		 * the new format.
  		 */
+ 		assert(ptoappend != NULL);
  		assert(ntoappend >= 0);
  		if (ntoappend == 0)
  			continue;
@@ -2404,11 +2409,11 @@
 date_repr(PyDateTime_Date *self)
 {
 	char buffer[1028];
-	const char *typename;
+	const char *type_name;
 
-	typename = self->ob_type->tp_name;
+	type_name = self->ob_type->tp_name;
 	PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
-		      typename,
+		      type_name,
 		      GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
 
 	return PyString_FromString(buffer);
@@ -3130,7 +3135,7 @@
 time_repr(PyDateTime_Time *self)
 {
 	char buffer[100];
-	const char *typename = self->ob_type->tp_name;
+	const char *type_name = self->ob_type->tp_name;
 	int h = TIME_GET_HOUR(self);
 	int m = TIME_GET_MINUTE(self);
 	int s = TIME_GET_SECOND(self);
@@ -3139,13 +3144,13 @@
 
 	if (us)
 		PyOS_snprintf(buffer, sizeof(buffer),
-			      "%s(%d, %d, %d, %d)", typename, h, m, s, us);
+			      "%s(%d, %d, %d, %d)", type_name, h, m, s, us);
 	else if (s)
 		PyOS_snprintf(buffer, sizeof(buffer),
-			      "%s(%d, %d, %d)", typename, h, m, s);
+			      "%s(%d, %d, %d)", type_name, h, m, s);
 	else
 		PyOS_snprintf(buffer, sizeof(buffer),
-			      "%s(%d, %d)", typename, h, m);
+			      "%s(%d, %d)", type_name, h, m);
 	result = PyString_FromString(buffer);
 	if (result != NULL && HASTZINFO(self))
 		result = append_keyword_tzinfo(result, self->tzinfo);
@@ -3816,6 +3821,10 @@
 		if (PySequence_Check(obj) && PySequence_Size(obj) >= 6)
 			for (i=0; i < 6; i++) {
 				PyObject *p = PySequence_GetItem(obj, i);
+				if (p == NULL) {
+					Py_DECREF(obj);
+					return NULL;
+				}
 				if (PyInt_Check(p))
 					ia[i] = PyInt_AsLong(p);
 				else
@@ -4023,13 +4032,13 @@
 datetime_repr(PyDateTime_DateTime *self)
 {
 	char buffer[1000];
-	const char *typename = self->ob_type->tp_name;
+	const char *type_name = self->ob_type->tp_name;
 	PyObject *baserepr;
 
 	if (DATE_GET_MICROSECOND(self)) {
 		PyOS_snprintf(buffer, sizeof(buffer),
 			      "%s(%d, %d, %d, %d, %d, %d, %d)",
-			      typename,
+			      type_name,
 			      GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
 			      DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
 			      DATE_GET_SECOND(self),
@@ -4038,7 +4047,7 @@
 	else if (DATE_GET_SECOND(self)) {
 		PyOS_snprintf(buffer, sizeof(buffer),
 			      "%s(%d, %d, %d, %d, %d, %d)",
-			      typename,
+			      type_name,
 			      GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
 			      DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
 			      DATE_GET_SECOND(self));
@@ -4046,7 +4055,7 @@
 	else {
 		PyOS_snprintf(buffer, sizeof(buffer),
 			      "%s(%d, %d, %d, %d, %d)",
-			      typename,
+			      type_name,
 			      GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
 			      DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
 	}
diff --git a/Modules/functionalmodule.c b/Modules/functionalmodule.c
index 4b2e9b4..38ef43a 100644
--- a/Modules/functionalmodule.c
+++ b/Modules/functionalmodule.c
@@ -48,7 +48,7 @@
 
 	pto->fn = func;
 	Py_INCREF(func);
-	pto->args = PyTuple_GetSlice(args, 1, INT_MAX);
+	pto->args = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
 	if (pto->args == NULL) {
 		pto->kw = NULL;
 		Py_DECREF(pto);
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 7e3f95a..0176d6f 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -413,8 +413,12 @@
 		assert(delstr != NULL);
 		return _PyInstance_Lookup(op, delstr) != NULL;
 	}
-	else 
+	else if (PyType_HasFeature(op->ob_type, Py_TPFLAGS_HEAPTYPE))
 		return op->ob_type->tp_del != NULL;
+	else if (PyGen_CheckExact(op))
+		return PyGen_NeedsFinalizing((PyGenObject *)op);
+	else
+		return 0;
 }
 
 /* Move the objects in unreachable with __del__ methods into `finalizers`.
@@ -730,6 +734,8 @@
 	PyGC_Head unreachable; /* non-problematic unreachable trash */
 	PyGC_Head finalizers;  /* objects with, & reachable from, __del__ */
 	PyGC_Head *gc;
+	static PyObject *tmod = NULL;
+	double t1 = 0.0;
 
 	if (delstr == NULL) {
 		delstr = PyString_InternFromString("__del__");
@@ -737,19 +743,29 @@
 			Py_FatalError("gc couldn't allocate \"__del__\"");
 	}
 
+	if (tmod == NULL) {
+		tmod = PyImport_ImportModule("time");
+		if (tmod == NULL)
+			PyErr_Clear();
+	}
+
 	if (debug & DEBUG_STATS) {
+		if (tmod != NULL) {
+			PyObject *f = PyObject_CallMethod(tmod, "time", NULL);
+			if (f == NULL) {
+				PyErr_Clear();
+			}
+			else {
+				t1 = PyFloat_AsDouble(f);
+				Py_DECREF(f);
+			}
+		}
 		PySys_WriteStderr("gc: collecting generation %d...\n",
 				  generation);
 		PySys_WriteStderr("gc: objects in each generation:");
-		for (i = 0; i < NUM_GENERATIONS; i++) {
-#ifdef MS_WIN64
-			PySys_WriteStderr(" %Id", gc_list_size(GEN_HEAD(i)));
-#else
-			PySys_WriteStderr(" %ld",
-				Py_SAFE_DOWNCAST(gc_list_size(GEN_HEAD(i)),
-						 Py_ssize_t, long));
-#endif
-		}
+		for (i = 0; i < NUM_GENERATIONS; i++)
+			PySys_WriteStderr(" %" PY_FORMAT_SIZE_T "d",
+					  gc_list_size(GEN_HEAD(i)));
 		PySys_WriteStderr("\n");
 	}
 
@@ -816,6 +832,17 @@
 		if (debug & DEBUG_COLLECTABLE) {
 			debug_cycle("collectable", FROM_GC(gc));
 		}
+		if (tmod != NULL && (debug & DEBUG_STATS)) {
+			PyObject *f = PyObject_CallMethod(tmod, "time", NULL);
+			if (f == NULL) {
+				PyErr_Clear();
+			}
+			else {
+				t1 = PyFloat_AsDouble(f)-t1;
+				Py_DECREF(f);
+				PySys_WriteStderr("gc: %.4fs elapsed.\n", t1);
+			}
+		}
 	}
 
 	/* Clear weakrefs and invoke callbacks as necessary. */
@@ -837,21 +864,14 @@
 			debug_cycle("uncollectable", FROM_GC(gc));
 	}
 	if (debug & DEBUG_STATS) {
-		if (m == 0 && n == 0) {
+		if (m == 0 && n == 0)
 			PySys_WriteStderr("gc: done.\n");
-		}
-		else {
-#ifdef MS_WIN64
+		else
 			PySys_WriteStderr(
-			    "gc: done, %Id unreachable, %Id uncollectable.\n",
+			    "gc: done, "
+			    "%" PY_FORMAT_SIZE_T "d unreachable, "
+			    "%" PY_FORMAT_SIZE_T "d uncollectable.\n",
 			    n+m, n);
-#else
-			PySys_WriteStderr(
-			    "gc: done, %ld unreachable, %ld uncollectable.\n",
-			    Py_SAFE_DOWNCAST(n+m, Py_ssize_t, long),
-			    Py_SAFE_DOWNCAST(n, Py_ssize_t, long));
-#endif
-		}
 	}
 
 	/* Append instances in the uncollectable set to a Python
@@ -1050,7 +1070,7 @@
 static int
 referrersvisit(PyObject* obj, PyObject *objs)
 {
-	int i;
+	Py_ssize_t i;
 	for (i = 0; i < PyTuple_GET_SIZE(objs); i++)
 		if (PyTuple_GET_ITEM(objs, i) == obj)
 			return 1;
@@ -1085,6 +1105,8 @@
 {
 	int i;
 	PyObject *result = PyList_New(0);
+	if (!result) return NULL;
+
 	for (i = 0; i < NUM_GENERATIONS; i++) {
 		if (!(gc_referrers_for(args, GEN_HEAD(i), result))) {
 			Py_DECREF(result);
@@ -1108,7 +1130,7 @@
 static PyObject *
 gc_get_referents(PyObject *self, PyObject *args)
 {
-	int i;
+	Py_ssize_t i;
 	PyObject *result = PyList_New(0);
 
 	if (result == NULL)
@@ -1288,7 +1310,8 @@
 _PyObject_GC_Malloc(size_t basicsize)
 {
 	PyObject *op;
-	PyGC_Head *g = PyObject_MALLOC(sizeof(PyGC_Head) + basicsize);
+	PyGC_Head *g = (PyGC_Head *)PyObject_MALLOC(
+                sizeof(PyGC_Head) + basicsize);
 	if (g == NULL)
 		return PyErr_NoMemory();
 	g->gc.gc_refs = GC_UNTRACKED;
@@ -1330,7 +1353,7 @@
 {
 	const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems);
 	PyGC_Head *g = AS_GC(op);
-	g = PyObject_REALLOC(g,  sizeof(PyGC_Head) + basicsize);
+	g = (PyGC_Head *)PyObject_REALLOC(g,  sizeof(PyGC_Head) + basicsize);
 	if (g == NULL)
 		return (PyVarObject *)PyErr_NoMemory();
 	op = (PyVarObject *) FROM_GC(g);
diff --git a/Modules/getpath.c b/Modules/getpath.c
index 4716d15..8eba730 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -91,6 +91,11 @@
  * process to find the installed Python tree.
  */
 
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
 #ifndef VERSION
 #if defined(__VMS)
 #define VERSION "2_1"
@@ -566,7 +571,7 @@
     bufsz += strlen(exec_prefix) + 1;
 
     /* This is the only malloc call in this file */
-    buf = PyMem_Malloc(bufsz);
+    buf = (char *)PyMem_Malloc(bufsz);
 
     if (buf == NULL) {
         /* We can't exit, so print a warning and limp along */
@@ -681,3 +686,9 @@
         calculate_path();
     return progpath;
 }
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c
index de849c9..12d33dd 100644
--- a/Modules/grpmodule.c
+++ b/Modules/grpmodule.c
@@ -29,6 +29,7 @@
 };
 
 
+static int initialized;
 static PyTypeObject StructGrpType;
 
 static PyObject *
@@ -174,6 +175,8 @@
     if (m == NULL)
         return;
     d = PyModule_GetDict(m);
-    PyStructSequence_InitType(&StructGrpType, &struct_group_type_desc);
+    if (!initialized)
+	    PyStructSequence_InitType(&StructGrpType, &struct_group_type_desc);
     PyDict_SetItemString(d, "struct_group", (PyObject *) &StructGrpType);
+    initialized = 1;
 }
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 49d241f..94617a9 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -340,7 +340,7 @@
 {
 	teedataobject *tdo;
 
-	tdo = PyObject_New(teedataobject, &teedataobject_type);
+	tdo = PyObject_GC_New(teedataobject, &teedataobject_type);
 	if (tdo == NULL)
 		return NULL;
 
@@ -348,6 +348,7 @@
 	tdo->nextlink = NULL;
 	Py_INCREF(it);
 	tdo->it = it;
+	PyObject_GC_Track(tdo);
 	return (PyObject *)tdo;
 }
 
@@ -381,16 +382,34 @@
 	return value;
 }
 
+static int
+teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg)
+{
+	int i;
+	Py_VISIT(tdo->it);
+	for (i = 0; i < tdo->numread; i++)
+		Py_VISIT(tdo->values[i]);
+	Py_VISIT(tdo->nextlink);
+	return 0;
+}
+
+static int
+teedataobject_clear(teedataobject *tdo)
+{
+	int i;
+	Py_CLEAR(tdo->it);
+	for (i=0 ; i<tdo->numread ; i++)
+		Py_CLEAR(tdo->values[i]);
+	Py_CLEAR(tdo->nextlink);
+	return 0;
+}
+
 static void
 teedataobject_dealloc(teedataobject *tdo)
 {
-	int i;
-
-	for (i=0 ; i<tdo->numread ; i++)
-		Py_DECREF(tdo->values[i]);
-	Py_XDECREF(tdo->it);
-	Py_XDECREF(tdo->nextlink);
-	PyObject_Del(tdo);
+	PyObject_GC_UnTrack(tdo);
+	teedataobject_clear(tdo);
+	PyObject_GC_Del(tdo);
 }
 
 PyDoc_STRVAR(teedataobject_doc, "Data container common to multiple tee objects.");
@@ -417,9 +436,26 @@
 	PyObject_GenericGetAttr,		/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,			/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,	/* tp_flags */
 	teedataobject_doc,			/* tp_doc */
-	0,					/* tp_traverse */
+	(traverseproc)teedataobject_traverse,	/* tp_traverse */
+	(inquiry)teedataobject_clear,		/* tp_clear */
+	0,					/* tp_richcompare */
+	0,					/* tp_weaklistoffset */
+	0,					/* tp_iter */
+	0,					/* tp_iternext */
+	0,					/* tp_methods */
+	0,					/* tp_members */
+	0,					/* tp_getset */
+	0,					/* tp_base */
+	0,					/* tp_dict */
+	0,					/* tp_descr_get */
+	0,					/* tp_descr_set */
+	0,					/* tp_dictoffset */
+	0,					/* tp_init */
+	0,					/* tp_alloc */
+	0,					/* tp_new */
+	PyObject_GC_Del,			/* tp_free */
 };
 
 
@@ -443,18 +479,26 @@
 	return value;
 }
 
+static int
+tee_traverse(teeobject *to, visitproc visit, void *arg)
+{
+	Py_VISIT((PyObject *)to->dataobj);
+	return 0;
+}
+
 static PyObject *
 tee_copy(teeobject *to)
 {
 	teeobject *newto;
 
-	newto = PyObject_New(teeobject, &tee_type);
+	newto = PyObject_GC_New(teeobject, &tee_type);
 	if (newto == NULL)
 		return NULL;
 	Py_INCREF(to->dataobj);
 	newto->dataobj = to->dataobj;
 	newto->index = to->index;
 	newto->weakreflist = NULL;
+	PyObject_GC_Track(newto);
 	return (PyObject *)newto;
 }
 
@@ -474,12 +518,13 @@
 		goto done;
 	}
 
-	to = PyObject_New(teeobject, &tee_type);
+	to = PyObject_GC_New(teeobject, &tee_type);
 	if (to == NULL) 
 		goto done;
 	to->dataobj = (teedataobject *)teedataobject_new(it);
 	to->index = 0;
 	to->weakreflist = NULL;
+	PyObject_GC_Track(to);
 done:
 	Py_XDECREF(it);
 	return (PyObject *)to;
@@ -495,13 +540,21 @@
 	return tee_fromiterable(iterable);
 }
 
-static void
-tee_dealloc(teeobject *to)
+static int
+tee_clear(teeobject *to)
 {
 	if (to->weakreflist != NULL)
 		PyObject_ClearWeakRefs((PyObject *) to);
-	Py_XDECREF(to->dataobj);
-	PyObject_Del(to);
+	Py_CLEAR(to->dataobj);
+	return 0;
+}
+
+static void
+tee_dealloc(teeobject *to)
+{
+	PyObject_GC_UnTrack(to);
+	tee_clear(to);
+	PyObject_GC_Del(to);
 }
 
 PyDoc_STRVAR(teeobject_doc,
@@ -534,10 +587,10 @@
 	0,				/* tp_getattro */
 	0,				/* tp_setattro */
 	0,				/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,		/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,	/* tp_flags */
 	teeobject_doc,			/* tp_doc */
-	0,				/* tp_traverse */
-	0,				/* tp_clear */
+	(traverseproc)tee_traverse,	/* tp_traverse */
+	(inquiry)tee_clear,		/* tp_clear */
 	0,				/* tp_richcompare */
 	offsetof(teeobject, weakreflist),	/* tp_weaklistoffset */
 	PyObject_SelfIter,		/* tp_iter */
@@ -553,7 +606,7 @@
 	0,				/* tp_init */
 	0,				/* tp_alloc */
 	tee_new,			/* tp_new */
-	PyObject_Del,			/* tp_free */
+	PyObject_GC_Del,		/* tp_free */
 };
 
 static PyObject *
diff --git a/Modules/main.c b/Modules/main.c
index b3ce16e..7326a27 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -28,6 +28,10 @@
     "Type \"help\", \"copyright\", \"credits\" or \"license\" " \
     "for more information."
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* For Py_GetArgcArgv(); set by main() */
 static char **orig_argv;
 static int  orig_argc;
@@ -206,7 +210,7 @@
 			/* -c is the last option; following arguments
 			   that look like options are left for the
 			   command to interpret. */
-			command = malloc(strlen(_PyOS_optarg) + 2);
+			command = (char *)malloc(strlen(_PyOS_optarg) + 2);
 			if (command == NULL)
 				Py_FatalError(
 				   "not enough memory to copy -c argument");
@@ -219,7 +223,7 @@
 			/* -m is the last option; following arguments
 			   that look like options are left for the
 			   module to interpret. */
-			module = malloc(strlen(_PyOS_optarg) + 2);
+			module = (char *)malloc(strlen(_PyOS_optarg) + 2);
 			if (module == NULL)
 				Py_FatalError(
 				   "not enough memory to copy -m argument");
@@ -509,3 +513,8 @@
 	*argc = orig_argc;
 	*argv = orig_argv;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/Modules/md5.c b/Modules/md5.c
new file mode 100644
index 0000000..c35d96c
--- /dev/null
+++ b/Modules/md5.c
@@ -0,0 +1,381 @@
+/*
+  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+	either statically or dynamically; added missing #include <string.h>
+	in library.
+  2002-03-11 lpd Corrected argument list for main(), and added int return
+	type, in test program and T value program.
+  2002-02-21 lpd Added missing #include <stdio.h> in test program.
+  2000-07-03 lpd Patched to eliminate warnings about "constant is
+	unsigned in ANSI C, signed in traditional"; made test program
+	self-checking.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+#  define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3    0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6    0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9    0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13    0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16    0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19    0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22    0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25    0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28    0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31    0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35    0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38    0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41    0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44    0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47    0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50    0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53    0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57    0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60    0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63    0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+	a = pms->abcd[0], b = pms->abcd[1],
+	c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+#if BYTE_ORDER > 0
+    /* Define storage only for big-endian CPUs. */
+    md5_word_t X[16];
+#else
+    /* Define storage for little-endian or both types of CPUs. */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+#endif
+
+    {
+#if BYTE_ORDER == 0
+	/*
+	 * Determine dynamically whether this is a big-endian or
+	 * little-endian machine, since we can use a more efficient
+	 * algorithm on the latter.
+	 */
+	static const int w = 1;
+
+	if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0		/* little-endian */
+	{
+	    /*
+	     * On little-endian machines, we can process properly aligned
+	     * data without copying it.
+	     */
+	    if (!((data - (const md5_byte_t *)0) & 3)) {
+		/* data are properly aligned */
+		X = (const md5_word_t *)data;
+	    } else {
+		/* not aligned */
+		memcpy(xbuf, data, 64);
+		X = xbuf;
+	    }
+	}
+#endif
+#if BYTE_ORDER == 0
+	else			/* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0		/* big-endian */
+	{
+	    /*
+	     * On big-endian machines, we must arrange the bytes in the
+	     * right order.
+	     */
+	    const md5_byte_t *xp = data;
+	    int i;
+
+#  if BYTE_ORDER == 0
+	    X = xbuf;		/* (dynamic only) */
+#  else
+#    define xbuf X		/* (static only) */
+#  endif
+	    for (i = 0; i < 16; ++i, xp += 4)
+		xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+	}
+#endif
+    }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+     /* Round 2. */
+     /* Let [abcd k s i] denote the operation
+          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+     /* Round 3. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+     /* Round 4. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+     /* Then perform the following additions. (That is increment each
+        of the four registers by the value it had before this block
+        was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+    pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+	return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+	pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+	memcpy(pms->buf + offset, p, copy);
+	if (offset + copy < 64)
+	    return;
+	p += copy;
+	left -= copy;
+	md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+	md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+	memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/Modules/md5.h b/Modules/md5.h
index 13628df..5eb6d6c 100644
--- a/Modules/md5.h
+++ b/Modules/md5.h
@@ -1,62 +1,91 @@
-/* MD5.H - header file for MD5C.C
+/*
+  Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id$ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Removed support for non-ANSI compilers; removed
+	references to Ghostscript; clarified derivation from RFC 1321;
+	now handles byte order either statically or dynamically.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+	added conditionalization for C++ compilation from Martin
+	Purschke <purschke@bnl.gov>.
+  1999-05-03 lpd Original version.
  */
 
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
 
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
  */
 
-/* ========== include global.h ========== */
-/* GLOBAL.H - RSAREF types and constants
- */
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
 
-/* POINTER defines a generic pointer type */
-typedef unsigned char *POINTER;
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];	/* message length in bits, lsw first */
+    md5_word_t abcd[4];		/* digest buffer */
+    md5_byte_t buf[64];		/* accumulate block */
+} md5_state_t;
 
-/* UINT4 defines a four byte word */
-#if SIZEOF_LONG == 4
-typedef unsigned long int UINT4;
-#elif SIZEOF_SHORT == 4
-typedef unsigned short int UINT4;
-#elif INT_MAX == 2147483647
-typedef unsigned int UINT4;
-#else
-#error "Can't find a 4-byte integral type"
+#ifdef __cplusplus
+extern "C" 
+{
 #endif
 
-/* ========== End global.h; continue md5.h ========== */
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
 
-/* MD5 context. */
-typedef struct {
-    UINT4 state[4];                                   /* state (ABCD) */
-    UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
-    unsigned char buffer[64];                         /* input buffer */
-} MD5_CTX;
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
 
-/* Rename all exported symbols to avoid conflicts with similarly named
-   symbols in some systems' standard C libraries... */
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
 
-#define MD5Init _Py_MD5Init
-#define MD5Update _Py_MD5Update
-#define MD5Final _Py_MD5Final
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
 
-void MD5Init(MD5_CTX *);
-void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
-void MD5Final(unsigned char [16], MD5_CTX *);
+#endif /* md5_INCLUDED */
diff --git a/Modules/md5c.c b/Modules/md5c.c
deleted file mode 100644
index 1b8dfdb..0000000
--- a/Modules/md5c.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-#include "Python.h"
-#include "md5.h"
-
-/* Constants for MD5Transform routine. */
-
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-static void MD5Transform(UINT4[4], unsigned char[64]);
-
-
-/* Encodes input (UINT4) into output (unsigned char). Assumes len is
-   a multiple of 4.
- */
-static void
-Encode(unsigned char *output, UINT4 *input, unsigned int len)
-{
-    unsigned int i, j;
-
-    for (i = 0, j = 0; j < len; i++, j += 4) {
-        output[j] = (unsigned char)(input[i] & 0xff);
-        output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
-        output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
-        output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
-    }
-}
-
-
-/* Decodes input (unsigned char) into output (UINT4). Assumes len is
-   a multiple of 4.
- */
-static void
-Decode(UINT4 *output, unsigned char *input, unsigned int len)
-{
-    unsigned int i, j;
-
-    for (i = 0, j = 0; j < len; i++, j += 4) {
-        output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
-            (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
-    }
-}
-
-
-static unsigned char PADDING[64] = {
-    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions. */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits. */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-   Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
-     (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
-     (a) = ROTATE_LEFT ((a), (s)); \
-     (a) += (b); \
-    }
-#define GG(a, b, c, d, x, s, ac) { \
-     (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
-     (a) = ROTATE_LEFT ((a), (s)); \
-     (a) += (b); \
-    }
-#define HH(a, b, c, d, x, s, ac) { \
-     (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
-     (a) = ROTATE_LEFT ((a), (s)); \
-     (a) += (b); \
-    }
-#define II(a, b, c, d, x, s, ac) { \
-     (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
-     (a) = ROTATE_LEFT ((a), (s)); \
-     (a) += (b); \
-    }
-
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context. */
-void
-MD5Init(MD5_CTX *context)
-{
-    context->count[0] = context->count[1] = 0;
-    /* Load magic initialization constants. */
-    context->state[0] = 0x67452301;
-    context->state[1] = 0xefcdab89;
-    context->state[2] = 0x98badcfe;
-    context->state[3] = 0x10325476;
-}
-
-
-/* MD5 block update operation. Continues an MD5 message-digest
-   operation, processing another message block, and updating the
-   context.
- */
-void
-MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen)
-{
-    unsigned int i, index, partLen;
-
-    /* Compute number of bytes mod 64 */
-    index = (unsigned int)((context->count[0] >> 3) & 0x3F);
-
-    /* Update number of bits */
-    if ((context->count[0] += ((UINT4)inputLen << 3))
-        < ((UINT4)inputLen << 3))
-        context->count[1]++;
-    context->count[1] += ((UINT4)inputLen >> 29);
-
-    partLen = 64 - index;
-
-    /* Transform as many times as possible. */
-    if (inputLen >= partLen) {
-        memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
-        MD5Transform(context->state, context->buffer);
-
-        for (i = partLen; i + 63 < inputLen; i += 64)
-            MD5Transform(context->state, &input[i]);
-
-        index = 0;
-    }
-    else
-        i = 0;
-
-    /* Buffer remaining input */
-    memcpy((POINTER)&context->buffer[index],
-               (POINTER)&input[i], inputLen-i);
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
-  message digest and zeroing the context.
- */
-void
-MD5Final(unsigned char digest[16], MD5_CTX *context)
-{
-    unsigned char bits[8];
-    unsigned int index, padLen;
-
-    /* Save number of bits */
-    Encode (bits, context->count, 8);
-
-    /* Pad out to 56 mod 64. */
-    index = (unsigned int)((context->count[0] >> 3) & 0x3f);
-    padLen = (index < 56) ? (56 - index) : (120 - index);
-    MD5Update(context, PADDING, padLen);
-
-    /* Append length (before padding) */
-    MD5Update(context, bits, 8);
-
-    /* Store state in digest */
-    Encode(digest, context->state, 16);
-
-    /* Zeroize sensitive information. */
-    memset((POINTER)context, 0, sizeof (*context));
-}
-
-
-/* MD5 basic transformation. Transforms state based on block. */
-static void
-MD5Transform(UINT4 state[4], unsigned char block[64])
-{
-    UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
-
-    Decode (x, block, 64);
-
-    /* Round 1 */
-    FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
-    FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
-    FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
-    FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
-    FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
-    FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
-    FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
-    FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
-    FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
-    FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
-    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
-    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
-    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
-    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
-    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
-    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
-    /* Round 2 */
-    GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
-    GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
-    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
-    GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
-    GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
-    GG(d, a, b, c, x[10], S22,  0x2441453); /* 22 */
-    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
-    GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
-    GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
-    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
-    GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
-    GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
-    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
-    GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
-    GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
-    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
-    /* Round 3 */
-    HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
-    HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
-    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
-    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
-    HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
-    HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
-    HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
-    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
-    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
-    HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
-    HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
-    HH(b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
-    HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
-    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
-    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
-    HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
-    /* Round 4 */
-    II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
-    II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
-    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
-    II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
-    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
-    II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
-    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
-    II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
-    II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
-    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
-    II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
-    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
-    II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
-    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
-    II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
-    II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
-    state[0] += a;
-    state[1] += b;
-    state[2] += c;
-    state[3] += d;
-
-    /* Zeroize sensitive information. */
-    memset((POINTER)x, 0, sizeof (x));
-}
diff --git a/Modules/md5module.c b/Modules/md5module.c
index e12bef8..5e4f116 100644
--- a/Modules/md5module.c
+++ b/Modules/md5module.c
@@ -15,7 +15,7 @@
 
 typedef struct {
 	PyObject_HEAD
-        MD5_CTX	md5;		/* the context holder */
+        md5_state_t	md5;		/* the context holder */
 } md5object;
 
 static PyTypeObject MD5type;
@@ -31,7 +31,7 @@
 	if (md5p == NULL)
 		return NULL;
 
-	MD5Init(&md5p->md5);	/* actual initialisation */
+	md5_init(&md5p->md5);	/* actual initialisation */
 	return md5p;
 }
 
@@ -56,7 +56,7 @@
 	if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
 		return NULL;
 
-	MD5Update(&self->md5, cp, len);
+	md5_append(&self->md5, cp, len);
 
 	Py_INCREF(Py_None);
 	return Py_None;
@@ -73,12 +73,12 @@
 static PyObject *
 md5_digest(md5object *self)
 {
- 	MD5_CTX mdContext;
+ 	md5_state_t mdContext;
 	unsigned char aDigest[16];
 
 	/* make a temporary copy, and perform the final */
 	mdContext = self->md5;
-	MD5Final(aDigest, &mdContext);
+	md5_finish(&mdContext, aDigest);
 
 	return PyString_FromStringAndSize((char *)aDigest, 16);
 }
@@ -94,14 +94,14 @@
 static PyObject *
 md5_hexdigest(md5object *self)
 {
- 	MD5_CTX mdContext;
+ 	md5_state_t mdContext;
 	unsigned char digest[16];
 	unsigned char hexdigest[32];
 	int i, j;
 
 	/* make a temporary copy, and perform the final */
 	mdContext = self->md5;
-	MD5Final(digest, &mdContext);
+	md5_finish(&mdContext, digest);
 
 	/* Make hex version of the digest */
 	for(i=j=0; i<16; i++) {
@@ -272,7 +272,7 @@
 		return NULL;
 
 	if (cp)
-		MD5Update(&md5p->md5, cp, len);
+		md5_append(&md5p->md5, cp, len);
 
 	return (PyObject *)md5p;
 }
diff --git a/Modules/operator.c b/Modules/operator.c
index 24f4e0a..cbce16e 100644
--- a/Modules/operator.c
+++ b/Modules/operator.c
@@ -354,8 +354,7 @@
 static int
 itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
 {
-	if (ig->item)
-		return visit(ig->item, arg);
+	Py_VISIT(ig->item);
 	return 0;
 }
 
@@ -493,8 +492,7 @@
 static int
 attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
 {
-	if (ag->attr)
-		return visit(ag->attr, arg);
+	Py_VISIT(ag->attr);
 	return 0;
 }
 
diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c
index ce8a0d0..563620c 100644
--- a/Modules/ossaudiodev.c
+++ b/Modules/ossaudiodev.c
@@ -935,24 +935,32 @@
 
     labels = PyList_New(num_controls);
     names = PyList_New(num_controls);
+    if (labels == NULL || names == NULL)
+        goto error2;
     for (i = 0; i < num_controls; i++) {
         s = PyString_FromString(control_labels[i]);
         if (s == NULL)
-            return -1;
+            goto error2;
         PyList_SET_ITEM(labels, i, s);
 
         s = PyString_FromString(control_names[i]);
         if (s == NULL)
-            return -1;
+            goto error2;
         PyList_SET_ITEM(names, i, s);
     }
 
     if (PyModule_AddObject(module, "control_labels", labels) == -1)
-        return -1;
+        goto error2;
     if (PyModule_AddObject(module, "control_names", names) == -1)
-        return -1;
+        goto error1;
 
     return 0;
+
+error2:
+    Py_XDECREF(labels);
+error1:
+    Py_XDECREF(names);
+    return -1;
 }
 
 
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
index 83165ba..c9edae6 100644
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -657,9 +657,10 @@
             }
         }
         if (!ok) {
-            PyErr_SetObject(parser_error,
-                            Py_BuildValue("os", elem,
-                                          "Illegal node construct."));
+            PyObject *err = Py_BuildValue("os", elem,
+                                          "Illegal node construct.");
+            PyErr_SetObject(parser_error, err);
+            Py_XDECREF(err);
             Py_XDECREF(elem);
             return (0);
         }
@@ -700,7 +701,7 @@
                 }
             }
             len = PyString_GET_SIZE(temp) + 1;
-            strn = (char *)PyMem_MALLOC(len);
+            strn = (char *)PyObject_MALLOC(len);
             if (strn != NULL)
                 (void) memcpy(strn, PyString_AS_STRING(temp), len);
             Py_DECREF(temp);
@@ -710,18 +711,19 @@
              *  It has to be one or the other; this is an error.
              *  Throw an exception.
              */
-            PyErr_SetObject(parser_error,
-                            Py_BuildValue("os", elem, "unknown node type."));
+            PyObject *err = Py_BuildValue("os", elem, "unknown node type.");
+            PyErr_SetObject(parser_error, err);
+            Py_XDECREF(err);
             Py_XDECREF(elem);
             return (0);
         }
         err = PyNode_AddChild(root, type, strn, *line_num, 0);
         if (err == E_NOMEM) {
-            PyMem_DEL(strn);
+            PyObject_FREE(strn);
             return (node *) PyErr_NoMemory();
         }
         if (err == E_OVERFLOW) {
-            PyMem_DEL(strn);
+            PyObject_FREE(strn);
             PyErr_SetString(PyExc_ValueError,
                             "unsupported number of child nodes");
             return NULL;
@@ -740,7 +742,7 @@
         }
         Py_XDECREF(elem);
     }
-    return (root);
+    return root;
 }
 
 
@@ -762,6 +764,7 @@
         tuple = Py_BuildValue("os", tuple,
                     "Illegal syntax-tree; cannot start with terminal symbol.");
         PyErr_SetObject(parser_error, tuple);
+        Py_XDECREF(tuple);
     }
     else if (ISNONTERMINAL(num)) {
         /*
@@ -784,7 +787,7 @@
             if (res && encoding) {
                 Py_ssize_t len;
                 len = PyString_GET_SIZE(encoding) + 1;
-                res->n_str = (char *)PyMem_MALLOC(len);
+                res->n_str = (char *)PyObject_MALLOC(len);
                 if (res->n_str != NULL)
                     (void) memcpy(res->n_str, PyString_AS_STRING(encoding), len);
                 Py_DECREF(encoding);
@@ -792,14 +795,16 @@
             }
         }
     }
-    else
+    else {
         /*  The tuple is illegal -- if the number is neither TERMINAL nor
          *  NONTERMINAL, we can't use it.  Not sure the implementation
          *  allows this condition, but the API doesn't preclude it.
          */
-        PyErr_SetObject(parser_error,
-                        Py_BuildValue("os", tuple,
-                                      "Illegal component tuple."));
+        PyObject *err = Py_BuildValue("os", tuple,
+                                      "Illegal component tuple.");
+        PyErr_SetObject(parser_error, err);
+        Py_XDECREF(err);
+    }
 
     return (res);
 }
@@ -1321,7 +1326,7 @@
     return res;
 }
 
-/*  list_if:  'if' test [list_iter]
+/*  list_if:  'if' old_test [list_iter]
  */
 static int
 validate_list_if(node *tree)
@@ -1336,12 +1341,12 @@
 
     if (res)
         res = (validate_name(CHILD(tree, 0), "if")
-               && validate_test(CHILD(tree, 1)));
+               && validate_old_test(CHILD(tree, 1)));
 
     return res;
 }
 
-/*  gen_if:  'if' test [gen_iter]
+/*  gen_if:  'if' old_test [gen_iter]
  */
 static int
 validate_gen_if(node *tree)
@@ -1356,7 +1361,7 @@
     
     if (res)
         res = (validate_name(CHILD(tree, 0), "if")
-               && validate_test(CHILD(tree, 1)));
+               && validate_old_test(CHILD(tree, 1)));
 
     return res;
 }
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 1fbc353..b51ba5d 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -22,6 +22,10 @@
 #    include <unixio.h>
 #endif /* defined(__VMS) */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 PyDoc_STRVAR(posix__doc__,
 "This module provides access to operating system functionality that is\n\
 standardized by the C Standard and the POSIX standard (a thinly\n\
@@ -264,6 +268,12 @@
 #define WTERMSIG(u_wait) ((u_wait).w_termsig)
 #endif
 
+#define WAIT_TYPE union wait
+#define WAIT_STATUS_INT(s) (s.w_status)
+
+#else /* !UNION_WAIT */
+#define WAIT_TYPE int
+#define WAIT_STATUS_INT(s) (s)
 #endif /* UNION_WAIT */
 
 /* Don't use the "_r" form if we don't need it (also, won't have a
@@ -971,6 +981,7 @@
 	10
 };
 
+static int initialized;
 static PyTypeObject StatResultType;
 static PyTypeObject StatVFSResultType;
 static newfunc structseq_new;
@@ -1839,6 +1850,7 @@
 	struct dirent *ep;
 	int arg_is_unicode = 1;
 
+	errno = 0;
 	if (!PyArg_ParseTuple(args, "U:listdir", &v)) {
 		arg_is_unicode = 0;
 		PyErr_Clear();
@@ -1895,6 +1907,12 @@
 		}
 		Py_DECREF(v);
 	}
+	if (errno != 0 && d != NULL) {
+		/* readdir() returned NULL and set errno */
+		closedir(dirp);
+		Py_DECREF(d);
+		return posix_error_with_allocated_filename(name); 
+	}
 	closedir(dirp);
 	PyMem_Free(name);
 
@@ -1995,13 +2013,13 @@
 }
 
 
-#ifdef HAVE_NICE
-#if defined(HAVE_BROKEN_NICE) && defined(HAVE_SYS_RESOURCE_H)
-#if defined(HAVE_GETPRIORITY) && !defined(PRIO_PROCESS)
+/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
+#if defined(HAVE_SYS_RESOURCE_H)
 #include <sys/resource.h>
 #endif
-#endif
 
+
+#ifdef HAVE_NICE
 PyDoc_STRVAR(posix_nice__doc__,
 "nice(inc) -> new_priority\n\n\
 Decrease the priority of process by inc and return the new priority.");
@@ -3088,7 +3106,7 @@
 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
 	PyOS_sighandler_t sig_saved;
 #ifdef sun
-	extern char *ptsname();
+	extern char *ptsname(int fildes);
 #endif
 #endif
 
@@ -5091,6 +5109,114 @@
 }
 #endif /* HAVE_SETGROUPS */
 
+#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
+static PyObject *
+wait_helper(int pid, int status, struct rusage *ru)
+{
+	PyObject *result;
+   	static PyObject *struct_rusage;
+
+	if (pid == -1)
+		return posix_error();
+
+	if (struct_rusage == NULL) {
+		PyObject *m = PyImport_ImportModule("resource");
+		if (m == NULL)
+			return NULL;
+		struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
+		Py_DECREF(m);
+		if (struct_rusage == NULL)
+			return NULL;
+	}
+
+	/* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
+	result = PyStructSequence_New((PyTypeObject*) struct_rusage);
+	if (!result)
+		return NULL;
+
+#ifndef doubletime
+#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
+#endif
+
+	PyStructSequence_SET_ITEM(result, 0,
+			PyFloat_FromDouble(doubletime(ru->ru_utime)));
+	PyStructSequence_SET_ITEM(result, 1,
+			PyFloat_FromDouble(doubletime(ru->ru_stime)));
+#define SET_INT(result, index, value)\
+		PyStructSequence_SET_ITEM(result, index, PyInt_FromLong(value))
+	SET_INT(result, 2, ru->ru_maxrss);
+	SET_INT(result, 3, ru->ru_ixrss);
+	SET_INT(result, 4, ru->ru_idrss);
+	SET_INT(result, 5, ru->ru_isrss);
+	SET_INT(result, 6, ru->ru_minflt);
+	SET_INT(result, 7, ru->ru_majflt);
+	SET_INT(result, 8, ru->ru_nswap);
+	SET_INT(result, 9, ru->ru_inblock);
+	SET_INT(result, 10, ru->ru_oublock);
+	SET_INT(result, 11, ru->ru_msgsnd);
+	SET_INT(result, 12, ru->ru_msgrcv);
+	SET_INT(result, 13, ru->ru_nsignals);
+	SET_INT(result, 14, ru->ru_nvcsw);
+	SET_INT(result, 15, ru->ru_nivcsw);
+#undef SET_INT
+
+	if (PyErr_Occurred()) {
+		Py_DECREF(result);
+		return NULL;
+	}
+
+	return Py_BuildValue("iiN", pid, status, result);
+}
+#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
+
+#ifdef HAVE_WAIT3
+PyDoc_STRVAR(posix_wait3__doc__,
+"wait3(options) -> (pid, status, rusage)\n\n\
+Wait for completion of a child process.");
+
+static PyObject *
+posix_wait3(PyObject *self, PyObject *args)
+{
+	int pid, options;
+	struct rusage ru;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
+
+	if (!PyArg_ParseTuple(args, "i:wait3", &options))
+		return NULL;
+
+	Py_BEGIN_ALLOW_THREADS
+	pid = wait3(&status, options, &ru);
+	Py_END_ALLOW_THREADS
+
+	return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
+}
+#endif /* HAVE_WAIT3 */
+
+#ifdef HAVE_WAIT4
+PyDoc_STRVAR(posix_wait4__doc__,
+"wait4(pid, options) -> (pid, status, rusage)\n\n\
+Wait for completion of a given child process.");
+
+static PyObject *
+posix_wait4(PyObject *self, PyObject *args)
+{
+	int pid, options;
+	struct rusage ru;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
+
+	if (!PyArg_ParseTuple(args, "ii:wait4", &pid, &options))
+		return NULL;
+
+	Py_BEGIN_ALLOW_THREADS
+	pid = wait4(pid, &status, options, &ru);
+	Py_END_ALLOW_THREADS
+
+	return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
+}
+#endif /* HAVE_WAIT4 */
+
 #ifdef HAVE_WAITPID
 PyDoc_STRVAR(posix_waitpid__doc__,
 "waitpid(pid, options) -> (pid, status)\n\n\
@@ -5100,14 +5226,8 @@
 posix_waitpid(PyObject *self, PyObject *args)
 {
 	int pid, options;
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
 	if (!PyArg_ParseTuple(args, "ii:waitpid", &pid, &options))
 		return NULL;
@@ -5116,8 +5236,8 @@
 	Py_END_ALLOW_THREADS
 	if (pid == -1)
 		return posix_error();
-	else
-		return Py_BuildValue("ii", pid, status_i);
+
+	return Py_BuildValue("ii", pid, WAIT_STATUS_INT(status));
 }
 
 #elif defined(HAVE_CWAIT)
@@ -5140,10 +5260,9 @@
 	Py_END_ALLOW_THREADS
 	if (pid == -1)
 		return posix_error();
-	else
-		/* shift the status left a byte so this is more like the
-		   POSIX waitpid */
-		return Py_BuildValue("ii", pid, status << 8);
+
+	/* shift the status left a byte so this is more like the POSIX waitpid */
+	return Py_BuildValue("ii", pid, status << 8);
 }
 #endif /* HAVE_WAITPID || HAVE_CWAIT */
 
@@ -5156,23 +5275,16 @@
 posix_wait(PyObject *self, PyObject *noargs)
 {
 	int pid;
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	status_i = 0;
 	Py_BEGIN_ALLOW_THREADS
 	pid = wait(&status);
 	Py_END_ALLOW_THREADS
 	if (pid == -1)
 		return posix_error();
-	else
-		return Py_BuildValue("ii", pid, status_i);
-#undef status_i
+
+	return Py_BuildValue("ii", pid, WAIT_STATUS_INT(status));
 }
 #endif
 
@@ -5668,9 +5780,24 @@
 			     "invalid file mode '%s'", mode);
 		return NULL;
 	}
-
 	Py_BEGIN_ALLOW_THREADS
+#if !defined(MS_WINDOWS) && defined(HAVE_FCNTL_H)
+	if (mode[0] == 'a') {
+		/* try to make sure the O_APPEND flag is set */
+		int flags;
+		flags = fcntl(fd, F_GETFL);
+		if (flags != -1)
+			fcntl(fd, F_SETFL, flags | O_APPEND);
+		fp = fdopen(fd, mode);
+		if (fp == NULL && flags != -1)
+			/* restore old mode if fdopen failed */
+			fcntl(fd, F_SETFL, flags);
+	} else {
+		fp = fdopen(fd, mode);
+	}
+#else
 	fp = fdopen(fd, mode);
+#endif
 	Py_END_ALLOW_THREADS
 	if (fp == NULL)
 		return posix_error();
@@ -5887,7 +6014,7 @@
 posix_putenv(PyObject *self, PyObject *args)
 {
         char *s1, *s2;
-        char *new;
+        char *newenv;
 	PyObject *newstr;
 	size_t len;
 
@@ -5918,9 +6045,9 @@
 	newstr = PyString_FromStringAndSize(NULL, (int)len - 1);
 	if (newstr == NULL)
 		return PyErr_NoMemory();
-	new = PyString_AS_STRING(newstr);
-	PyOS_snprintf(new, len, "%s=%s", s1, s2);
-	if (putenv(new)) {
+	newenv = PyString_AS_STRING(newstr);
+	PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
+	if (putenv(newenv)) {
                 Py_DECREF(newstr);
                 posix_error();
                 return NULL;
@@ -6010,22 +6137,13 @@
 static PyObject *
 posix_WCOREDUMP(PyObject *self, PyObject *args)
 {
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &status_i))
-	{
+	if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
 		return NULL;
-	}
 
 	return PyBool_FromLong(WCOREDUMP(status));
-#undef status_i
 }
 #endif /* WCOREDUMP */
 
@@ -6038,22 +6156,13 @@
 static PyObject *
 posix_WIFCONTINUED(PyObject *self, PyObject *args)
 {
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	if (!PyArg_ParseTuple(args, "i:WCONTINUED", &status_i))
-	{
+	if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
 		return NULL;
-	}
 
 	return PyBool_FromLong(WIFCONTINUED(status));
-#undef status_i
 }
 #endif /* WIFCONTINUED */
 
@@ -6065,22 +6174,13 @@
 static PyObject *
 posix_WIFSTOPPED(PyObject *self, PyObject *args)
 {
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &status_i))
-	{
+	if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
 		return NULL;
-	}
 
 	return PyBool_FromLong(WIFSTOPPED(status));
-#undef status_i
 }
 #endif /* WIFSTOPPED */
 
@@ -6092,22 +6192,13 @@
 static PyObject *
 posix_WIFSIGNALED(PyObject *self, PyObject *args)
 {
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &status_i))
-	{
+	if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
 		return NULL;
-	}
 
 	return PyBool_FromLong(WIFSIGNALED(status));
-#undef status_i
 }
 #endif /* WIFSIGNALED */
 
@@ -6120,22 +6211,13 @@
 static PyObject *
 posix_WIFEXITED(PyObject *self, PyObject *args)
 {
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	if (!PyArg_ParseTuple(args, "i:WIFEXITED", &status_i))
-	{
+	if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
 		return NULL;
-	}
 
 	return PyBool_FromLong(WIFEXITED(status));
-#undef status_i
 }
 #endif /* WIFEXITED */
 
@@ -6147,22 +6229,13 @@
 static PyObject *
 posix_WEXITSTATUS(PyObject *self, PyObject *args)
 {
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &status_i))
-	{
+	if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
 		return NULL;
-	}
 
 	return Py_BuildValue("i", WEXITSTATUS(status));
-#undef status_i
 }
 #endif /* WEXITSTATUS */
 
@@ -6175,22 +6248,13 @@
 static PyObject *
 posix_WTERMSIG(PyObject *self, PyObject *args)
 {
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	if (!PyArg_ParseTuple(args, "i:WTERMSIG", &status_i))
-	{
+	if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
 		return NULL;
-	}
 
 	return Py_BuildValue("i", WTERMSIG(status));
-#undef status_i
 }
 #endif /* WTERMSIG */
 
@@ -6203,22 +6267,13 @@
 static PyObject *
 posix_WSTOPSIG(PyObject *self, PyObject *args)
 {
-#ifdef UNION_WAIT
-	union wait status;
-#define status_i (status.w_status)
-#else
-	int status;
-#define status_i status
-#endif
-	status_i = 0;
+	WAIT_TYPE status;
+	WAIT_STATUS_INT(status) = 0;
 
-	if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &status_i))
-	{
+	if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
 		return NULL;
-	}
 
 	return Py_BuildValue("i", WSTOPSIG(status));
-#undef status_i
 }
 #endif /* WSTOPSIG */
 
@@ -6396,15 +6451,16 @@
     name = tmpnam(buffer);
 #endif
     if (name == NULL) {
-        PyErr_SetObject(PyExc_OSError,
-                        Py_BuildValue("is", 0,
+	PyObject *err = Py_BuildValue("is", 0,
 #ifdef USE_TMPNAM_R
                                       "unexpected NULL from tmpnam_r"
 #else
                                       "unexpected NULL from tmpnam"
 #endif
-                                      ));
-        return NULL;
+                                      );
+	PyErr_SetObject(PyExc_OSError, err);
+	Py_XDECREF(err);
+	return NULL;
     }
     return PyString_FromString(buffer);
 }
@@ -6753,26 +6809,30 @@
 {
     PyObject *result = NULL;
     int name;
-    char buffer[64];
+    char buffer[256];
 
     if (PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) {
-        int len = confstr(name, buffer, sizeof(buffer));
+	int len;
 
         errno = 0;
-        if (len == 0) {
-            if (errno != 0)
-                posix_error();
-            else
-                result = PyString_FromString("");
+	len = confstr(name, buffer, sizeof(buffer));
+	if (len == 0) {
+	    if (errno) {
+		posix_error();
+	    }
+	    else {
+		result = Py_None;
+		Py_INCREF(Py_None);
+	    }
         }
         else {
-            if (len >= sizeof(buffer)) {
-                result = PyString_FromStringAndSize(NULL, len);
+	    if ((unsigned int)len >= sizeof(buffer)) {
+                result = PyString_FromStringAndSize(NULL, len-1);
                 if (result != NULL)
-                    confstr(name, PyString_AS_STRING(result), len+1);
+                    confstr(name, PyString_AS_STRING(result), len);
             }
             else
-                result = PyString_FromString(buffer);
+                result = PyString_FromStringAndSize(buffer, len-1);
         }
     }
     return result;
@@ -7423,6 +7483,44 @@
 	char *filepath;
 	char *operation = NULL;
 	HINSTANCE rc;
+#ifdef Py_WIN_WIDE_FILENAMES
+	if (unicode_file_names()) {
+		PyObject *unipath, *woperation = NULL;
+		if (!PyArg_ParseTuple(args, "U|s:startfile",
+				      &unipath, &operation)) {
+			PyErr_Clear();
+			goto normal;
+		}
+		
+
+		if (operation) {
+		    woperation = PyUnicode_DecodeASCII(operation, 
+						       strlen(operation), NULL);
+		    if (!woperation) {
+			    PyErr_Clear();
+			    operation = NULL;
+			    goto normal;
+		    }
+		}
+			
+		Py_BEGIN_ALLOW_THREADS
+		rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0,
+			PyUnicode_AS_UNICODE(unipath),
+			NULL, NULL, SW_SHOWNORMAL);
+		Py_END_ALLOW_THREADS
+
+		Py_XDECREF(woperation);
+		if (rc <= (HINSTANCE)32) {
+			PyObject *errval = win32_error_unicode("startfile",
+						PyUnicode_AS_UNICODE(unipath));
+			return errval;
+		}
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+#endif
+
+normal:
 	if (!PyArg_ParseTuple(args, "et|s:startfile", 
 			      Py_FileSystemDefaultEncoding, &filepath, 
 			      &operation))
@@ -7695,6 +7793,12 @@
 #ifdef HAVE_WAIT
 	{"wait",	posix_wait, METH_NOARGS, posix_wait__doc__},
 #endif /* HAVE_WAIT */
+#ifdef HAVE_WAIT3
+        {"wait3",	posix_wait3, METH_VARARGS, posix_wait3__doc__},
+#endif /* HAVE_WAIT3 */
+#ifdef HAVE_WAIT4
+        {"wait4",	posix_wait4, METH_VARARGS, posix_wait4__doc__},
+#endif /* HAVE_WAIT4 */
 #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
 	{"waitpid",	posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
 #endif /* HAVE_WAITPID */
@@ -8142,19 +8246,27 @@
 		posix_putenv_garbage = PyDict_New();
 #endif
 
-	stat_result_desc.name = MODNAME ".stat_result";
-	stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
-	stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
-	stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
-	PyStructSequence_InitType(&StatResultType, &stat_result_desc);
-	structseq_new = StatResultType.tp_new;
-	StatResultType.tp_new = statresult_new;
+	if (!initialized) {
+		stat_result_desc.name = MODNAME ".stat_result";
+		stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
+		stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
+		stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
+		PyStructSequence_InitType(&StatResultType, &stat_result_desc);
+		structseq_new = StatResultType.tp_new;
+		StatResultType.tp_new = statresult_new;
+
+		statvfs_result_desc.name = MODNAME ".statvfs_result";
+		PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
+	}
 	Py_INCREF((PyObject*) &StatResultType);
 	PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
-
-	statvfs_result_desc.name = MODNAME ".statvfs_result";
-	PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
 	Py_INCREF((PyObject*) &StatVFSResultType);
 	PyModule_AddObject(m, "statvfs_result",
 			   (PyObject*) &StatVFSResultType);
+	initialized = 1;
 }
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c
index 9e7b864..9e01f48 100644
--- a/Modules/pwdmodule.c
+++ b/Modules/pwdmodule.c
@@ -42,6 +42,7 @@
 exception is raised if the entry asked for cannot be found.");
 
       
+static int initialized;
 static PyTypeObject StructPwdType;
 
 static void
@@ -186,9 +187,12 @@
 	if (m == NULL)
     		return;
 
-	PyStructSequence_InitType(&StructPwdType, &struct_pwd_type_desc);
+	if (!initialized)
+		PyStructSequence_InitType(&StructPwdType, 
+					  &struct_pwd_type_desc);
 	Py_INCREF((PyObject *) &StructPwdType);
 	PyModule_AddObject(m, "struct_passwd", (PyObject *) &StructPwdType);
 	/* And for b/w compatibility (this was defined by mistake): */
 	PyModule_AddObject(m, "struct_pwent", (PyObject *) &StructPwdType);
+	initialized = 1;
 }
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index e4bf180..fe50e36 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -1519,6 +1519,8 @@
     if (strcmp(name, "__members__") == 0) {
         int i;
         PyObject *rc = PyList_New(0);
+	if (!rc)
+		return NULL;
         for (i = 0; handler_info[i].name != NULL; i++) {
             PyObject *o = get_handler_name(&handler_info[i]);
             if (o != NULL)
@@ -1652,14 +1654,9 @@
 static int
 xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
 {
-    int i, err;
-    for (i = 0; handler_info[i].name != NULL; i++) {
-        if (!op->handlers[i])
-            continue;
-        err = visit(op->handlers[i], arg);
-        if (err)
-            return err;
-    }
+    int i;
+    for (i = 0; handler_info[i].name != NULL; i++)
+        Py_VISIT(op->handlers[i]);
     return 0;
 }
 
@@ -1667,8 +1664,7 @@
 xmlparse_clear(xmlparseobject *op)
 {
     clear_handlers(op, 0);
-    Py_XDECREF(op->intern);
-    op->intern = 0;
+    Py_CLEAR(op->intern);
     return 0;
 }
 #endif
diff --git a/Modules/regexmodule.c b/Modules/regexmodule.c
deleted file mode 100644
index 2fb4198..0000000
--- a/Modules/regexmodule.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
-XXX support range parameter on search
-XXX support mstop parameter on search
-*/
-
-
-/* Regular expression objects */
-/* This uses Tatu Ylonen's copyleft-free reimplementation of
-   GNU regular expressions */
-
-#include "Python.h"
-
-#include <ctype.h>
-
-#include "regexpr.h"
-
-static PyObject *RegexError;	/* Exception */	
-
-typedef struct {
-	PyObject_HEAD
-	struct re_pattern_buffer re_patbuf; /* The compiled expression */
-	struct re_registers re_regs; /* The registers from the last match */
-	char re_fastmap[256];	/* Storage for fastmap */
-	PyObject *re_translate;	/* String object for translate table */
-	PyObject *re_lastok;	/* String object last matched/searched */
-	PyObject *re_groupindex;	/* Group name to index dictionary */
-	PyObject *re_givenpat;	/* Pattern with symbolic groups */
-	PyObject *re_realpat;	/* Pattern without symbolic groups */
-} regexobject;
-
-/* Regex object methods */
-
-static void
-reg_dealloc(regexobject *re)
-{
-	if (re->re_patbuf.buffer)
-		free(re->re_patbuf.buffer);
-	Py_XDECREF(re->re_translate);
-	Py_XDECREF(re->re_lastok);
-	Py_XDECREF(re->re_groupindex);
-	Py_XDECREF(re->re_givenpat);
-	Py_XDECREF(re->re_realpat);
-	PyObject_Del(re);
-}
-
-static PyObject *
-makeresult(struct re_registers *regs)
-{
-	PyObject *v;
-	int i;
-	static PyObject *filler = NULL;
-
-	if (filler == NULL) {
-		filler = Py_BuildValue("(ii)", -1, -1);
-		if (filler == NULL)
-			return NULL;
-	}
-	v = PyTuple_New(RE_NREGS);
-	if (v == NULL)
-		return NULL;
-
-	for (i = 0; i < RE_NREGS; i++) {
-		int lo = regs->start[i];
-		int hi = regs->end[i];
-		PyObject *w;
-		if (lo == -1 && hi == -1) {
-			w = filler;
-			Py_INCREF(w);
-		}
-		else
-			w = Py_BuildValue("(ii)", lo, hi);
-		if (w == NULL || PyTuple_SetItem(v, i, w) < 0) {
-			Py_DECREF(v);
-			return NULL;
-		}
-	}
-	return v;
-}
-
-static PyObject *
-regobj_match(regexobject *re, PyObject *args)
-{
-	PyObject *argstring;
-	char *buffer;
-	int size;
-	int offset = 0;
-	int result;
-
-	if (!PyArg_ParseTuple(args, "O|i:match", &argstring, &offset))
-		return NULL;
-	if (!PyArg_Parse(argstring, "t#", &buffer, &size))
-		return NULL;
-
-	if (offset < 0 || offset > size) {
-		PyErr_SetString(RegexError, "match offset out of range");
-		return NULL;
-	}
-	Py_XDECREF(re->re_lastok);
-	re->re_lastok = NULL;
-	result = _Py_re_match(&re->re_patbuf, (unsigned char *)buffer, size, offset,
-			      &re->re_regs);
-	if (result < -1) {
-		/* Serious failure of some sort; if re_match didn't 
-		   set an exception, raise a generic error */
-	        if (!PyErr_Occurred())
-		        PyErr_SetString(RegexError, "match failure");
-		return NULL;
-	}
-	if (result >= 0) {
-		Py_INCREF(argstring);
-		re->re_lastok = argstring;
-	}
-	return PyInt_FromLong((long)result); /* Length of the match or -1 */
-}
-
-static PyObject *
-regobj_search(regexobject *re, PyObject *args)
-{
-	PyObject *argstring;
-	char *buffer;
-	int size;
-	int offset = 0;
-	int range;
-	int result;
-	
-	if (!PyArg_ParseTuple(args, "O|i:search", &argstring, &offset))
-		return NULL;
-	if (!PyArg_Parse(argstring, "t#:search", &buffer, &size))
-		return NULL;
-
-	if (offset < 0 || offset > size) {
-		PyErr_SetString(RegexError, "search offset out of range");
-		return NULL;
-	}
-	/* NB: In Emacs 18.57, the documentation for re_search[_2] and
-	   the implementation don't match: the documentation states that
-	   |range| positions are tried, while the code tries |range|+1
-	   positions.  It seems more productive to believe the code! */
-	range = size - offset;
-	Py_XDECREF(re->re_lastok);
-	re->re_lastok = NULL;
-	result = _Py_re_search(&re->re_patbuf, (unsigned char *)buffer, size, offset, range,
-			   &re->re_regs);
-	if (result < -1) {
-		/* Serious failure of some sort; if re_match didn't 
-		   set an exception, raise a generic error */
-	        if (!PyErr_Occurred())
-	  	        PyErr_SetString(RegexError, "match failure");
-		return NULL;
-	}
-	if (result >= 0) {
-		Py_INCREF(argstring);
-		re->re_lastok = argstring;
-	}
-	return PyInt_FromLong((long)result); /* Position of the match or -1 */
-}
-
-/* get the group from the regex where index can be a string (group name) or
-   an integer index [0 .. 99]
- */
-static PyObject*
-group_from_index(regexobject *re, PyObject *index)
-{
-	int i, a, b;
-	char *v;
-
-	if (PyString_Check(index))
-		if (re->re_groupindex == NULL ||
-		    !(index = PyDict_GetItem(re->re_groupindex, index)))
-		{
-			PyErr_SetString(RegexError,
-					"group() group name doesn't exist");
-			return NULL;
-		}
-
-	i = PyInt_AsLong(index);
-	if (i == -1 && PyErr_Occurred())
-		return NULL;
-
-	if (i < 0 || i >= RE_NREGS) {
-		PyErr_SetString(RegexError, "group() index out of range");
-		return NULL;
-	}
-	if (re->re_lastok == NULL) {
-		PyErr_SetString(RegexError,
-			   "group() only valid after successful match/search");
-		return NULL;
-	}
-	a = re->re_regs.start[i];
-	b = re->re_regs.end[i];
-	if (a < 0 || b < 0) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	if (!(v = PyString_AsString(re->re_lastok)))
-		return NULL;
-
-	return PyString_FromStringAndSize(v+a, b-a);
-}
-
-
-static PyObject *
-regobj_group(regexobject *re, PyObject *args)
-{
-	int n = PyTuple_Size(args);
-	int i;
-	PyObject *res = NULL;
-
-	if (n < 0)
-		return NULL;
-	if (n == 0) {
-		PyErr_SetString(PyExc_TypeError, "not enough arguments");
-		return NULL;
-	}
-	if (n == 1) {
-		/* return value is a single string */
-		PyObject *index = PyTuple_GetItem(args, 0);
-		if (!index)
-			return NULL;
-		
-		return group_from_index(re, index);
-	}
-
-	/* return value is a tuple */
-	if (!(res = PyTuple_New(n)))
-		return NULL;
-
-	for (i = 0; i < n; i++) {
-		PyObject *index = PyTuple_GetItem(args, i);
-		PyObject *group = NULL;
-
-		if (!index)
-			goto finally;
-		if (!(group = group_from_index(re, index)))
-			goto finally;
-		if (PyTuple_SetItem(res, i, group) < 0)
-			goto finally;
-	}
-	return res;
-
-  finally:
-	Py_DECREF(res);
-	return NULL;
-}
-
-
-static struct PyMethodDef reg_methods[] = {
-	{"match",	(PyCFunction)regobj_match, METH_VARARGS},
-	{"search",	(PyCFunction)regobj_search, METH_VARARGS},
-	{"group",	(PyCFunction)regobj_group, METH_VARARGS},
-	{NULL,		NULL}		/* sentinel */
-};
-
-
-
-static char* members[] = {
-	"last", "regs", "translate",
-	"groupindex", "realpat", "givenpat",
-	NULL
-};
-
-
-static PyObject *
-regobj_getattr(regexobject *re, char *name)
-{
-	if (strcmp(name, "regs") == 0) {
-		if (re->re_lastok == NULL) {
-			Py_INCREF(Py_None);
-			return Py_None;
-		}
-		return makeresult(&re->re_regs);
-	}
-	if (strcmp(name, "last") == 0) {
-		if (re->re_lastok == NULL) {
-			Py_INCREF(Py_None);
-			return Py_None;
-		}
-		Py_INCREF(re->re_lastok);
-		return re->re_lastok;
-	}
-	if (strcmp(name, "translate") == 0) {
-		if (re->re_translate == NULL) {
-			Py_INCREF(Py_None);
-			return Py_None;
-		}
-		Py_INCREF(re->re_translate);
-		return re->re_translate;
-	}
-	if (strcmp(name, "groupindex") == 0) {
-		if (re->re_groupindex == NULL) {
-			Py_INCREF(Py_None);
-			return Py_None;
-		}
-		Py_INCREF(re->re_groupindex);
-		return re->re_groupindex;
-	}
-	if (strcmp(name, "realpat") == 0) {
-		if (re->re_realpat == NULL) {
-			Py_INCREF(Py_None);
-			return Py_None;
-		}
-		Py_INCREF(re->re_realpat);
-		return re->re_realpat;
-	}
-	if (strcmp(name, "givenpat") == 0) {
-		if (re->re_givenpat == NULL) {
-			Py_INCREF(Py_None);
-			return Py_None;
-		}
-		Py_INCREF(re->re_givenpat);
-		return re->re_givenpat;
-	}
-	if (strcmp(name, "__members__") == 0) {
-		int i = 0;
-		PyObject *list = NULL;
-
-		/* okay, so it's unlikely this list will change that often.
-		   still, it's easier to change it in just one place.
-		 */
-		while (members[i])
-			i++;
-		if (!(list = PyList_New(i)))
-			return NULL;
-
-		i = 0;
-		while (members[i]) {
-			PyObject* v = PyString_FromString(members[i]);
-			if (!v || PyList_SetItem(list, i, v) < 0) {
-				Py_DECREF(list);
-				return NULL;
-			}
-			i++;
-		}
-		return list;
-	}
-	return Py_FindMethod(reg_methods, (PyObject *)re, name);
-}
-
-static PyTypeObject Regextype = {
-	PyObject_HEAD_INIT(NULL)
-	0,				     /*ob_size*/
-	"regex.regex",			     /*tp_name*/
-	sizeof(regexobject),		     /*tp_size*/
-	0,				     /*tp_itemsize*/
-	/* methods */
-	(destructor)reg_dealloc,	     /*tp_dealloc*/
-	0,				     /*tp_print*/
-	(getattrfunc)regobj_getattr,	     /*tp_getattr*/
-	0,				     /*tp_setattr*/
-	0,				     /*tp_compare*/
-	0,				     /*tp_repr*/
-};
-
-/* reference counting invariants:
-   pattern: borrowed
-   translate: borrowed
-   givenpat: borrowed
-   groupindex: transferred
-*/
-static PyObject *
-newregexobject(PyObject *pattern, PyObject *translate, PyObject *givenpat, PyObject *groupindex)
-{
-	regexobject *re;
-	char *pat;
-	int size;
-
-	if (!PyArg_Parse(pattern, "t#", &pat, &size))
-		return NULL;
-	
-	if (translate != NULL && PyString_Size(translate) != 256) {
-		PyErr_SetString(RegexError,
-				"translation table must be 256 bytes");
-		return NULL;
-	}
-	re = PyObject_New(regexobject, &Regextype);
-	if (re != NULL) {
-		char *error;
-		re->re_patbuf.buffer = NULL;
-		re->re_patbuf.allocated = 0;
-		re->re_patbuf.fastmap = (unsigned char *)re->re_fastmap;
-		if (translate) {
-			re->re_patbuf.translate = (unsigned char *)PyString_AsString(translate);
-			if (!re->re_patbuf.translate)
-				goto finally;
-			Py_INCREF(translate);
-		}
-		else
-			re->re_patbuf.translate = NULL;
-		re->re_translate = translate;
-		re->re_lastok = NULL;
-		re->re_groupindex = groupindex;
-		Py_INCREF(pattern);
-		re->re_realpat = pattern;
-		Py_INCREF(givenpat);
-		re->re_givenpat = givenpat;
-		error = _Py_re_compile_pattern((unsigned char *)pat, size, &re->re_patbuf);
-		if (error != NULL) {
-			PyErr_SetString(RegexError, error);
-			goto finally;
-		}
-	}
-	return (PyObject *)re;
-  finally:
-	Py_DECREF(re);
-	return NULL;
-}
-
-static PyObject *
-regex_compile(PyObject *self, PyObject *args)
-{
-	PyObject *pat = NULL;
-	PyObject *tran = NULL;
-
-	if (!PyArg_ParseTuple(args, "S|S:compile", &pat, &tran))
-		return NULL;
-	return newregexobject(pat, tran, pat, NULL);
-}
-
-static PyObject *
-symcomp(PyObject *pattern, PyObject *gdict)
-{
-	char *opat, *oend, *o, *n, *g, *v;
-	int group_count = 0;
-	int sz;
-	int escaped = 0;
-	char name_buf[128];
-	PyObject *npattern;
-	int require_escape = re_syntax & RE_NO_BK_PARENS ? 0 : 1;
-
-	if (!(opat = PyString_AsString(pattern)))
-		return NULL;
-
-	if ((sz = PyString_Size(pattern)) < 0)
-		return NULL;
-
-	oend = opat + sz;
-	o = opat;
-
-	if (oend == opat) {
-		Py_INCREF(pattern);
-		return pattern;
-	}
-
-	if (!(npattern = PyString_FromStringAndSize((char*)NULL, sz)) ||
-	    !(n = PyString_AsString(npattern)))
-		return NULL;
-
-	while (o < oend) {
-		if (*o == '(' && escaped == require_escape) {
-			char *backtrack;
-			escaped = 0;
-			++group_count;
-			*n++ = *o;
-			if (++o >= oend || *o != '<')
-				continue;
-			/* *o == '<' */
-			if (o+1 < oend && *(o+1) == '>')
-				continue;
-			backtrack = o;
-			g = name_buf;
-			for (++o; o < oend;) {
-				if (*o == '>') {
-				    PyObject *group_name = NULL;
-				    PyObject *group_index = NULL;
-				    *g++ = '\0';
-				    group_name = PyString_FromString(name_buf);
-				    group_index = PyInt_FromLong(group_count);
-				    if (group_name == NULL ||
-					group_index == NULL ||
-					PyDict_SetItem(gdict, group_name,
-						       group_index) != 0)
-				    {
-					    Py_XDECREF(group_name);
-					    Py_XDECREF(group_index);
-					    Py_XDECREF(npattern);
-					    return NULL;
-				    }
-				    Py_DECREF(group_name);
-				    Py_DECREF(group_index);
-				    ++o;     /* eat the '>' */
-				    break;
-				}
-				if (!isalnum(Py_CHARMASK(*o)) && *o != '_') {
-					o = backtrack;
-					break;
-				}
-				*g++ = *o++;
-			}
-		}
-		else if (*o == '[' && !escaped) {
-			*n++ = *o;
-			++o;		     /* eat the char following '[' */
-			*n++ = *o;
-			while (o < oend && *o != ']') {
-				++o;
-				*n++ = *o;
-			}
-			if (o < oend)
-				++o;
-		}
-		else if (*o == '\\') {
-			escaped = 1;
-			*n++ = *o;
-			++o;
-		}
-		else {
-			escaped = 0;
-			*n++ = *o;
-			++o;
-		}
-	}
-
-	if (!(v = PyString_AsString(npattern))) {
-		Py_DECREF(npattern);
-		return NULL;
-	}
-	/* _PyString_Resize() decrements npattern on failure */
-	_PyString_Resize(&npattern, n - v);
-	return npattern;
-
-}
-
-static PyObject *
-regex_symcomp(PyObject *self, PyObject *args)
-{
-	PyObject *pattern;
-	PyObject *tran = NULL;
-	PyObject *gdict = NULL;
-	PyObject *npattern;
-	PyObject *retval = NULL;
-
-	if (!PyArg_ParseTuple(args, "S|S:symcomp", &pattern, &tran))
-		return NULL;
-
-	gdict = PyDict_New();
-	if (gdict == NULL || (npattern = symcomp(pattern, gdict)) == NULL) {
-		Py_XDECREF(gdict);
-		return NULL;
-	}
-	retval = newregexobject(npattern, tran, pattern, gdict);
-	Py_DECREF(npattern);
-	return retval;
-}
-
-
-static PyObject *cache_pat;
-static PyObject *cache_prog;
-
-static int
-update_cache(PyObject *pat)
-{
-	PyObject *tuple = PyTuple_Pack(1, pat);
-	int status = 0;
-
-	if (!tuple)
-		return -1;
-
-	if (pat != cache_pat) {
-		Py_XDECREF(cache_pat);
-		cache_pat = NULL;
-		Py_XDECREF(cache_prog);
-		cache_prog = regex_compile((PyObject *)NULL, tuple);
-		if (cache_prog == NULL) {
-			status = -1;
-			goto finally;
-		}
-		cache_pat = pat;
-		Py_INCREF(cache_pat);
-	}
-  finally:
-	Py_DECREF(tuple);
-	return status;
-}
-
-static PyObject *
-regex_match(PyObject *self, PyObject *args)
-{
-	PyObject *pat, *string;
-	PyObject *tuple, *v;
-
-	if (!PyArg_ParseTuple(args, "SS:match", &pat, &string))
-		return NULL;
-	if (update_cache(pat) < 0)
-		return NULL;
-
-	if (!(tuple = Py_BuildValue("(S)", string)))
-		return NULL;
-	v = regobj_match((regexobject *)cache_prog, tuple);
-	Py_DECREF(tuple);
-	return v;
-}
-
-static PyObject *
-regex_search(PyObject *self, PyObject *args)
-{
-	PyObject *pat, *string;
-	PyObject *tuple, *v;
-
-	if (!PyArg_ParseTuple(args, "SS:search", &pat, &string))
-		return NULL;
-	if (update_cache(pat) < 0)
-		return NULL;
-
-	if (!(tuple = Py_BuildValue("(S)", string)))
-		return NULL;
-	v = regobj_search((regexobject *)cache_prog, tuple);
-	Py_DECREF(tuple);
-	return v;
-}
-
-static PyObject *
-regex_set_syntax(PyObject *self, PyObject *args)
-{
-	int syntax;
-	if (!PyArg_ParseTuple(args, "i:set_syntax", &syntax))
-		return NULL;
-	syntax = re_set_syntax(syntax);
-	/* wipe the global pattern cache */
-	Py_XDECREF(cache_pat);
-	cache_pat = NULL;
-	Py_XDECREF(cache_prog);
-	cache_prog = NULL;
-	return PyInt_FromLong((long)syntax);
-}
-
-static PyObject *
-regex_get_syntax(PyObject *self)
-{
-	return PyInt_FromLong((long)re_syntax);
-}
-
-
-static struct PyMethodDef regex_global_methods[] = {
-	{"compile",	regex_compile, METH_VARARGS},
-	{"symcomp",	regex_symcomp, METH_VARARGS},
-	{"match",	regex_match, METH_VARARGS},
-	{"search",	regex_search, METH_VARARGS},
-	{"set_syntax",	regex_set_syntax, METH_VARARGS},
-	{"get_syntax",  (PyCFunction)regex_get_syntax, METH_NOARGS},
-	{NULL,		NULL}		     /* sentinel */
-};
-
-PyMODINIT_FUNC
-initregex(void)
-{
-	PyObject *m, *d, *v;
-	int i;
-	char *s;
-	
-	/* Initialize object type */
-	Regextype.ob_type = &PyType_Type;
-
-	m = Py_InitModule("regex", regex_global_methods);
-	if (m == NULL)
-		return;
-	d = PyModule_GetDict(m);
-
-	if (PyErr_Warn(PyExc_DeprecationWarning,
-		       "the regex module is deprecated; "
-		       "please use the re module") < 0)
-		return;
-	
-	/* Initialize regex.error exception */
-	v = RegexError = PyErr_NewException("regex.error", NULL, NULL);
-	if (v == NULL || PyDict_SetItemString(d, "error", v) != 0)
-		goto finally;
-	
-	/* Initialize regex.casefold constant */
-	if (!(v = PyString_FromStringAndSize((char *)NULL, 256)))
-		goto finally;
-	
-	if (!(s = PyString_AsString(v)))
-		goto finally;
-
-	for (i = 0; i < 256; i++) {
-		if (isupper(i))
-			s[i] = tolower(i);
-		else
-			s[i] = i;
-	}
-	if (PyDict_SetItemString(d, "casefold", v) < 0)
-		goto finally;
-	Py_DECREF(v);
-
-	if (!PyErr_Occurred())
-		return;
-  finally:
-	/* Nothing */ ;
-}
diff --git a/Modules/regexpr.c b/Modules/regexpr.c
deleted file mode 100644
index e6a5417..0000000
--- a/Modules/regexpr.c
+++ /dev/null
@@ -1,2094 +0,0 @@
-/* regexpr.c
- *
- * Author: Tatu Ylonen <ylo@ngs.fi>
- *
- * Copyright (c) 1991 Tatu Ylonen, Espoo, Finland
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without
- * fee, provided that the above copyright notice appear in all copies.
- * This software is provided "as is" without express or implied
- * warranty.
- *
- * Created: Thu Sep 26 17:14:05 1991 ylo
- * Last modified: Mon Nov  4 17:06:48 1991 ylo
- * Ported to Think C: 19 Jan 1992 guido@cwi.nl
- *
- * This code draws many ideas from the regular expression packages by
- * Henry Spencer of the University of Toronto and Richard Stallman of
- * the Free Software Foundation.
- *
- * Emacs-specific code and syntax table code is almost directly borrowed
- * from GNU regexp.
- *
- * Bugs fixed and lots of reorganization by Jeffrey C. Ollie, April
- * 1997 Thanks for bug reports and ideas from Andrew Kuchling, Tim
- * Peters, Guido van Rossum, Ka-Ping Yee, Sjoerd Mullender, and
- * probably one or two others that I'm forgetting.
- *
- * $Id$ */
-
-#include "Python.h"
-#include "regexpr.h"
-
-/* The original code blithely assumed that sizeof(short) == 2.  Not
- * always true.  Original instances of "(short)x" were replaced by
- * SHORT(x), where SHORT is #defined below.  */
-
-#define SHORT(x) ((x) & 0x8000 ? (x) - 0x10000 : (x))
-
-/* The stack implementation is taken from an idea by Andrew Kuchling.
- * It's a doubly linked list of arrays. The advantages of this over a
- * simple linked list are that the number of mallocs required are
- * reduced. It also makes it possible to statically allocate enough
- * space so that small patterns don't ever need to call malloc.
- *
- * The advantages over a single array is that is periodically
- * realloced when more space is needed is that we avoid ever copying
- * the stack. */
-
-/* item_t is the basic stack element.  Defined as a union of
- * structures so that both registers, failure points, and counters can
- * be pushed/popped from the stack.  There's nothing built into the
- * item to keep track of whether a certain stack item is a register, a
- * failure point, or a counter. */
-
-typedef union item_t
-{
-	struct
-	{
-		int num;
-		int level;
-		unsigned char *start;
-		unsigned char *end;
-	} reg;
-	struct
-	{
-		int count;
-		int level;
-		int phantom;
-		unsigned char *code;
-		unsigned char *text;
-	} fail;
-	struct
-	{
-		int num;
-		int level;
-		int count;
-	} cntr;
-} item_t;
-
-#define STACK_PAGE_SIZE 256
-#define NUM_REGISTERS 256
-
-/* A 'page' of stack items. */
-
-typedef struct item_page_t
-{
-	item_t items[STACK_PAGE_SIZE];
-	struct item_page_t *prev;
-	struct item_page_t *next;
-} item_page_t;
-
-
-typedef struct match_state
-{
-	/* The number of registers that have been pushed onto the stack
-	 * since the last failure point. */
-
-	int count;
-
-	/* Used to control when registers need to be pushed onto the
-	 * stack. */
-	
-	int level;
-	
-	/* The number of failure points on the stack. */
-	
-	int point;
-	
-	/* Storage for the registers.  Each register consists of two
-	 * pointers to characters.  So register N is represented as
-	 * start[N] and end[N].  The pointers must be converted to
-	 * offsets from the beginning of the string before returning the
-	 * registers to the calling program. */
-	
-	unsigned char *start[NUM_REGISTERS];
-	unsigned char *end[NUM_REGISTERS];
-	
-	/* Keeps track of whether a register has changed recently. */
-	
-	int changed[NUM_REGISTERS];
-	
-	/* Structure to encapsulate the stack. */
-	struct
-	{
-		/* index into the current page.  If index == 0 and you need
-		 * to pop an item, move to the previous page and set index
-		 * = STACK_PAGE_SIZE - 1.  Otherwise decrement index to
-		 * push a page. If index == STACK_PAGE_SIZE and you need
-		 * to push a page move to the next page and set index =
-		 * 0. If there is no new next page, allocate a new page
-		 * and link it in. Otherwise, increment index to push a
-		 * page. */
-		
-		int index;
-		item_page_t *current; /* Pointer to the current page. */
-		item_page_t first; /* First page is statically allocated. */
-	} stack;
-} match_state;
-
-/* Initialize a state object */
-
-/* #define NEW_STATE(state) \ */
-/* memset(&state, 0, (void *)(&state.stack) - (void *)(&state)); \ */
-/* state.stack.current = &state.stack.first; \ */
-/* state.stack.first.prev = NULL; \ */
-/* state.stack.first.next = NULL; \ */
-/* state.stack.index = 0; \ */
-/* state.level = 1 */
-
-#define NEW_STATE(state, nregs) \
-{ \
-	int i; \
-	for (i = 0; i < nregs; i++) \
-	{ \
-		state.start[i] = NULL; \
-		state.end[i] = NULL; \
-		state.changed[i] = 0; \
-	} \
-	state.stack.current = &state.stack.first; \
-	state.stack.first.prev = NULL; \
-	state.stack.first.next = NULL; \
-	state.stack.index = 0; \
-	state.level = 1; \
-	state.count = 0; \
-	state.level = 0; \
-	state.point = 0; \
-}
-
-/* Free any memory that might have been malloc'd */
-
-#define FREE_STATE(state) \
-while(state.stack.first.next != NULL) \
-{ \
-	state.stack.current = state.stack.first.next; \
-	state.stack.first.next = state.stack.current->next; \
-	free(state.stack.current); \
-}
-
-/* Discard the top 'count' stack items. */
-
-#define STACK_DISCARD(stack, count, on_error) \
-stack.index -= count; \
-while (stack.index < 0) \
-{ \
-	if (stack.current->prev == NULL) \
-		on_error; \
-	stack.current = stack.current->prev; \
-	stack.index += STACK_PAGE_SIZE; \
-}
-
-/* Store a pointer to the previous item on the stack. Used to pop an
- * item off of the stack. */
-
-#define STACK_PREV(stack, top, on_error) \
-if (stack.index == 0) \
-{ \
-	if (stack.current->prev == NULL) \
-		on_error; \
-	stack.current = stack.current->prev; \
-	stack.index = STACK_PAGE_SIZE - 1; \
-} \
-else \
-{ \
-	stack.index--; \
-} \
-top = &(stack.current->items[stack.index])
-
-/* Store a pointer to the next item on the stack. Used to push an item
- * on to the stack. */
-
-#define STACK_NEXT(stack, top, on_error) \
-if (stack.index == STACK_PAGE_SIZE) \
-{ \
-	if (stack.current->next == NULL) \
-	{ \
-		stack.current->next = (item_page_t *)malloc(sizeof(item_page_t)); \
-		if (stack.current->next == NULL) \
-			on_error; \
-		stack.current->next->prev = stack.current; \
-		stack.current->next->next = NULL; \
-	} \
-	stack.current = stack.current->next; \
-	stack.index = 0; \
-} \
-top = &(stack.current->items[stack.index++])
-
-/* Store a pointer to the item that is 'count' items back in the
- * stack. STACK_BACK(stack, top, 1, on_error) is equivalent to
- * STACK_TOP(stack, top, on_error).  */
-
-#define STACK_BACK(stack, top, count, on_error) \
-{ \
-	int index; \
-	item_page_t *current; \
-	current = stack.current; \
-	index = stack.index - (count); \
-	while (index < 0) \
-	{ \
-		if (current->prev == NULL) \
-			on_error; \
-		current = current->prev; \
-		index += STACK_PAGE_SIZE; \
-	} \
-	top = &(current->items[index]); \
-}
-
-/* Store a pointer to the top item on the stack. Execute the
- * 'on_error' code if there are no items on the stack. */
-
-#define STACK_TOP(stack, top, on_error) \
-if (stack.index == 0) \
-{ \
-	if (stack.current->prev == NULL) \
-		on_error; \
-	top = &(stack.current->prev->items[STACK_PAGE_SIZE - 1]); \
-} \
-else \
-{ \
-	top = &(stack.current->items[stack.index - 1]); \
-}
-
-/* Test to see if the stack is empty */
-
-#define STACK_EMPTY(stack) ((stack.index == 0) && \
-			    (stack.current->prev == NULL))
-
-/* Return the start of register 'reg' */
-
-#define GET_REG_START(state, reg) (state.start[reg])
-
-/* Return the end of register 'reg' */
-
-#define GET_REG_END(state, reg) (state.end[reg])
-
-/* Set the start of register 'reg'. If the state of the register needs
- * saving, push it on the stack. */
-
-#define SET_REG_START(state, reg, text, on_error) \
-if(state.changed[reg] < state.level) \
-{ \
-	item_t *item; \
-	STACK_NEXT(state.stack, item, on_error); \
-	item->reg.num = reg; \
-	item->reg.start = state.start[reg]; \
-	item->reg.end = state.end[reg]; \
-	item->reg.level = state.changed[reg]; \
-	state.changed[reg] = state.level; \
-	state.count++; \
-} \
-state.start[reg] = text
-
-/* Set the end of register 'reg'. If the state of the register needs
- * saving, push it on the stack. */
-
-#define SET_REG_END(state, reg, text, on_error) \
-if(state.changed[reg] < state.level) \
-{ \
-	item_t *item; \
-	STACK_NEXT(state.stack, item, on_error); \
-	item->reg.num = reg; \
-	item->reg.start = state.start[reg]; \
-	item->reg.end = state.end[reg]; \
-	item->reg.level = state.changed[reg]; \
-	state.changed[reg] = state.level; \
-	state.count++; \
-} \
-state.end[reg] = text
-
-#define PUSH_FAILURE(state, xcode, xtext, on_error) \
-{ \
-	item_t *item; \
-	STACK_NEXT(state.stack, item, on_error); \
-	item->fail.code = xcode; \
-	item->fail.text = xtext; \
-	item->fail.count = state.count; \
-	item->fail.level = state.level; \
-	item->fail.phantom = 0; \
-	state.count = 0; \
-	state.level++; \
-	state.point++; \
-}
-
-/* Update the last failure point with a new position in the text. */
-
-#define UPDATE_FAILURE(state, xtext, on_error) \
-{ \
-	item_t *item; \
-	STACK_BACK(state.stack, item, state.count + 1, on_error); \
-	if (!item->fail.phantom) \
-	{ \
-		item_t *item2; \
-		STACK_NEXT(state.stack, item2, on_error); \
-		item2->fail.code = item->fail.code; \
-		item2->fail.text = xtext; \
-		item2->fail.count = state.count; \
-		item2->fail.level = state.level; \
-		item2->fail.phantom = 1; \
-		state.count = 0; \
-		state.level++; \
-		state.point++; \
-	} \
-	else \
-	{ \
-		STACK_DISCARD(state.stack, state.count, on_error); \
-		STACK_TOP(state.stack, item, on_error); \
-		item->fail.text = xtext; \
-		state.count = 0; \
-		state.level++; \
-	} \
-}
-
-#define POP_FAILURE(state, xcode, xtext, on_empty, on_error) \
-{ \
-	item_t *item; \
-	do \
-	{ \
-		while(state.count > 0) \
-		{ \
-			STACK_PREV(state.stack, item, on_error); \
-			state.start[item->reg.num] = item->reg.start; \
-			state.end[item->reg.num] = item->reg.end; \
-			state.changed[item->reg.num] = item->reg.level; \
-			state.count--; \
-		} \
-		STACK_PREV(state.stack, item, on_empty); \
-		xcode = item->fail.code; \
-		xtext = item->fail.text; \
-		state.count = item->fail.count; \
-		state.level = item->fail.level; \
-		state.point--; \
-	} \
-	while (item->fail.text == NULL); \
-}
-
-enum regexp_compiled_ops /* opcodes for compiled regexp */
-{
-	Cend,		      /* end of pattern reached */
-	Cbol,		      /* beginning of line */
-	Ceol,		      /* end of line */
-	Cset,		      /* character set.  Followed by 32 bytes of set. */
-	Cexact,		      /* followed by a byte to match */
-	Canychar,	      /* matches any character except newline */
-	Cstart_memory,	      /* set register start addr (followed by reg number) */
-	Cend_memory,	      /* set register end addr (followed by reg number) */
-	Cmatch_memory,	      /* match a duplicate of reg contents (regnum follows)*/
-	Cjump,		      /* followed by two bytes (lsb,msb) of displacement. */
-	Cstar_jump,	      /* will change to jump/update_failure_jump at runtime */
-	Cfailure_jump,	      /* jump to addr on failure */
-	Cupdate_failure_jump, /* update topmost failure point and jump */
-	Cdummy_failure_jump,  /* push a dummy failure point and jump */
-	Cbegbuf,	      /* match at beginning of buffer */
-	Cendbuf,	      /* match at end of buffer */
-	Cwordbeg,	      /* match at beginning of word */
-	Cwordend,	      /* match at end of word */
-	Cwordbound,	      /* match if at word boundary */
-	Cnotwordbound,        /* match if not at word boundary */
-	Csyntaxspec,	      /* matches syntax code (1 byte follows) */
-	Cnotsyntaxspec,       /* matches if syntax code does not match (1 byte follows) */
-	Crepeat1
-};
-
-enum regexp_syntax_op	/* syntax codes for plain and quoted characters */
-{
-	Rend,		  /* special code for end of regexp */
-	Rnormal,	  /* normal character */
-	Ranychar,	  /* any character except newline */
-	Rquote,		  /* the quote character */
-	Rbol,		  /* match beginning of line */
-	Reol,		  /* match end of line */
-	Roptional,	  /* match preceding expression optionally */
-	Rstar,		  /* match preceding expr zero or more times */
-	Rplus,		  /* match preceding expr one or more times */
-	Ror,		  /* match either of alternatives */
-	Ropenpar,	  /* opening parenthesis */
-	Rclosepar,	  /* closing parenthesis */
-	Rmemory,	  /* match memory register */
-	Rextended_memory, /* \vnn to match registers 10-99 */
-	Ropenset,	  /* open set.  Internal syntax hard-coded below. */
-	/* the following are gnu extensions to "normal" regexp syntax */
-	Rbegbuf,	  /* beginning of buffer */
-	Rendbuf,	  /* end of buffer */
-	Rwordchar,	  /* word character */
-	Rnotwordchar,	  /* not word character */
-	Rwordbeg,	  /* beginning of word */
-	Rwordend,	  /* end of word */
-	Rwordbound,	  /* word bound */
-	Rnotwordbound,	  /* not word bound */
-	Rnum_ops
-};
-
-static int re_compile_initialized = 0;
-static int regexp_syntax = 0;
-int re_syntax = 0; /* Exported copy of regexp_syntax */
-static unsigned char regexp_plain_ops[256];
-static unsigned char regexp_quoted_ops[256];
-static unsigned char regexp_precedences[Rnum_ops];
-static int regexp_context_indep_ops;
-static int regexp_ansi_sequences;
-
-#define NUM_LEVELS  5    /* number of precedence levels in use */
-#define MAX_NESTING 100  /* max nesting level of operators */
-
-#define SYNTAX(ch) re_syntax_table[(unsigned char)(ch)]
-
-unsigned char re_syntax_table[256];
-
-void re_compile_initialize(void)
-{
-	int a;
-  
-	static int syntax_table_inited = 0;
-
-	if (!syntax_table_inited)
-	{
-		syntax_table_inited = 1;
-		memset(re_syntax_table, 0, 256);
-		for (a = 'a'; a <= 'z'; a++)
-			re_syntax_table[a] = Sword;
-		for (a = 'A'; a <= 'Z'; a++)
-			re_syntax_table[a] = Sword;
-		for (a = '0'; a <= '9'; a++)
-			re_syntax_table[a] = Sword | Sdigit | Shexdigit;
-		for (a = '0'; a <= '7'; a++)
-			re_syntax_table[a] |= Soctaldigit;
-		for (a = 'A'; a <= 'F'; a++)
-			re_syntax_table[a] |= Shexdigit;
-		for (a = 'a'; a <= 'f'; a++)
-			re_syntax_table[a] |= Shexdigit;
-		re_syntax_table['_'] = Sword;
-		for (a = 9; a <= 13; a++)
-			re_syntax_table[a] = Swhitespace;
-		re_syntax_table[' '] = Swhitespace;
-	}
-	re_compile_initialized = 1;
-	for (a = 0; a < 256; a++)
-	{
-		regexp_plain_ops[a] = Rnormal;
-		regexp_quoted_ops[a] = Rnormal;
-	}
-	for (a = '0'; a <= '9'; a++)
-		regexp_quoted_ops[a] = Rmemory;
-	regexp_plain_ops['\134'] = Rquote;
-	if (regexp_syntax & RE_NO_BK_PARENS)
-	{
-		regexp_plain_ops['('] = Ropenpar;
-		regexp_plain_ops[')'] = Rclosepar;
-	}
-	else
-	{
-		regexp_quoted_ops['('] = Ropenpar;
-		regexp_quoted_ops[')'] = Rclosepar;
-	}
-	if (regexp_syntax & RE_NO_BK_VBAR)
-		regexp_plain_ops['\174'] = Ror;
-	else
-		regexp_quoted_ops['\174'] = Ror;
-	regexp_plain_ops['*'] = Rstar;
-	if (regexp_syntax & RE_BK_PLUS_QM)
-	{
-		regexp_quoted_ops['+'] = Rplus;
-		regexp_quoted_ops['?'] = Roptional;
-	}
-	else
-	{
-		regexp_plain_ops['+'] = Rplus;
-		regexp_plain_ops['?'] = Roptional;
-	}
-	if (regexp_syntax & RE_NEWLINE_OR)
-		regexp_plain_ops['\n'] = Ror;
-	regexp_plain_ops['\133'] = Ropenset;
-	regexp_plain_ops['\136'] = Rbol;
-	regexp_plain_ops['$'] = Reol;
-	regexp_plain_ops['.'] = Ranychar;
-	if (!(regexp_syntax & RE_NO_GNU_EXTENSIONS))
-	{
-		regexp_quoted_ops['w'] = Rwordchar;
-		regexp_quoted_ops['W'] = Rnotwordchar;
-		regexp_quoted_ops['<'] = Rwordbeg;
-		regexp_quoted_ops['>'] = Rwordend;
-		regexp_quoted_ops['b'] = Rwordbound;
-		regexp_quoted_ops['B'] = Rnotwordbound;
-		regexp_quoted_ops['`'] = Rbegbuf;
-		regexp_quoted_ops['\''] = Rendbuf;
-	}
-	if (regexp_syntax & RE_ANSI_HEX)
-		regexp_quoted_ops['v'] = Rextended_memory;
-	for (a = 0; a < Rnum_ops; a++)
-		regexp_precedences[a] = 4;
-	if (regexp_syntax & RE_TIGHT_VBAR)
-	{
-		regexp_precedences[Ror] = 3;
-		regexp_precedences[Rbol] = 2;
-		regexp_precedences[Reol] = 2;
-	}
-	else
-	{
-		regexp_precedences[Ror] = 2;
-		regexp_precedences[Rbol] = 3;
-		regexp_precedences[Reol] = 3;
-	}
-	regexp_precedences[Rclosepar] = 1;
-	regexp_precedences[Rend] = 0;
-	regexp_context_indep_ops = (regexp_syntax & RE_CONTEXT_INDEP_OPS) != 0;
-	regexp_ansi_sequences = (regexp_syntax & RE_ANSI_HEX) != 0;
-}
-
-int re_set_syntax(int syntax)
-{
-	int ret;
-	
-	ret = regexp_syntax;
-	regexp_syntax = syntax;
-	re_syntax = syntax; /* Exported copy */
-	re_compile_initialize();
-	return ret;
-}
-
-static int hex_char_to_decimal(int ch)
-{
-	if (ch >= '0' && ch <= '9')
-		return ch - '0';
-	if (ch >= 'a' && ch <= 'f')
-		return ch - 'a' + 10;
-	if (ch >= 'A' && ch <= 'F')
-		return ch - 'A' + 10;
-	return 16;
-}
-
-static void re_compile_fastmap_aux(unsigned char *code, int pos,
-                                   unsigned char *visited,
-                                   unsigned char *can_be_null,
-                                   unsigned char *fastmap)
-{
-	int a;
-	int b;
-	int syntaxcode;
-	
-	if (visited[pos])
-		return;  /* we have already been here */
-	visited[pos] = 1;
-	for (;;)
-		switch (code[pos++]) {
-		case Cend:
-			{
-				*can_be_null = 1;
-				return;
-			}
-		case Cbol:
-		case Cbegbuf:
-		case Cendbuf:
-		case Cwordbeg:
-		case Cwordend:
-		case Cwordbound:
-		case Cnotwordbound:
-		{
-			for (a = 0; a < 256; a++)
-				fastmap[a] = 1;
-			break;
-		}
-		case Csyntaxspec:
-		{
-			syntaxcode = code[pos++];
-			for (a = 0; a < 256; a++)
-				if (SYNTAX(a) & syntaxcode) 
-					fastmap[a] = 1;
-			return;
-		}
-		case Cnotsyntaxspec:
-		{
-			syntaxcode = code[pos++];
-			for (a = 0; a < 256; a++)
-				if (!(SYNTAX(a) & syntaxcode) )
-					fastmap[a] = 1;
-			return;
-		}
-		case Ceol:
-		{
-			fastmap['\n'] = 1;
-			if (*can_be_null == 0)
-				*can_be_null = 2; /* can match null, but only at end of buffer*/
-			return;
-		}
-		case Cset:
-		{
-			for (a = 0; a < 256/8; a++)
-				if (code[pos + a] != 0)
-					for (b = 0; b < 8; b++)
-						if (code[pos + a] & (1 << b))
-							fastmap[(a << 3) + b] = 1;
-			pos += 256/8;
-			return;
-		}
-		case Cexact:
-		{
-			fastmap[(unsigned char)code[pos]] = 1;
-			return;
-		}
-		case Canychar:
-		{
-			for (a = 0; a < 256; a++)
-				if (a != '\n')
-					fastmap[a] = 1;
-			return;
-		}
-		case Cstart_memory:
-		case Cend_memory:
-		{
-			pos++;
-			break;
-		}
-		case Cmatch_memory:
-		{
-			for (a = 0; a < 256; a++)
-				fastmap[a] = 1;
-			*can_be_null = 1;
-			return;
-		}
-		case Cjump:
-		case Cdummy_failure_jump:
-		case Cupdate_failure_jump:
-		case Cstar_jump:
-		{
-			a = (unsigned char)code[pos++];
-			a |= (unsigned char)code[pos++] << 8;
-			pos += (int)SHORT(a);
-			if (visited[pos])
-			{
-				/* argh... the regexp contains empty loops.  This is not
-				   good, as this may cause a failure stack overflow when
-				   matching.  Oh well. */
-				/* this path leads nowhere; pursue other paths. */
-				return;
-			}
-			visited[pos] = 1;
-			break;
-		}
-		case Cfailure_jump:
-		{
-			a = (unsigned char)code[pos++];
-			a |= (unsigned char)code[pos++] << 8;
-			a = pos + (int)SHORT(a);
-			re_compile_fastmap_aux(code, a, visited, can_be_null, fastmap);
-			break;
-		}
-		case Crepeat1:
-		{
-			pos += 2;
-			break;
-		}
-		default:
-		{
-		        PyErr_SetString(PyExc_SystemError, "Unknown regex opcode: memory corrupted?");
-		        return;
-			/*NOTREACHED*/
-		}
-		}
-}
-
-static int re_do_compile_fastmap(unsigned char *buffer, int used, int pos,
-                                 unsigned char *can_be_null,
-                                 unsigned char *fastmap)
-{
-	unsigned char small_visited[512], *visited;
-   
-	if (used <= sizeof(small_visited))
-		visited = small_visited;
-	else
-	{
-		visited = malloc(used);
-		if (!visited)
-			return 0;
-	}
-	*can_be_null = 0;
-	memset(fastmap, 0, 256);
-	memset(visited, 0, used);
-	re_compile_fastmap_aux(buffer, pos, visited, can_be_null, fastmap);
-	if (visited != small_visited)
-		free(visited);
-	return 1;
-}
-
-void re_compile_fastmap(regexp_t bufp)
-{
-	if (!bufp->fastmap || bufp->fastmap_accurate)
-		return;
-	assert(bufp->used > 0);
-	if (!re_do_compile_fastmap(bufp->buffer,
-				   bufp->used,
-				   0,
-				   &bufp->can_be_null,
-				   bufp->fastmap))
-		return;
-	if (PyErr_Occurred()) return;
-	if (bufp->buffer[0] == Cbol)
-		bufp->anchor = 1;   /* begline */
-	else
-		if (bufp->buffer[0] == Cbegbuf)
-			bufp->anchor = 2; /* begbuf */
-		else
-			bufp->anchor = 0; /* none */
-	bufp->fastmap_accurate = 1;
-}
-
-/* 
- * star is coded as:
- * 1: failure_jump 2
- *    ... code for operand of star
- *    star_jump 1
- * 2: ... code after star
- *
- * We change the star_jump to update_failure_jump if we can determine
- * that it is safe to do so; otherwise we change it to an ordinary
- * jump.
- *
- * plus is coded as
- *
- *    jump 2
- * 1: failure_jump 3
- * 2: ... code for operand of plus
- *    star_jump 1
- * 3: ... code after plus
- *
- * For star_jump considerations this is processed identically to star.
- *
- */
-
-static int re_optimize_star_jump(regexp_t bufp, unsigned char *code)
-{
-	unsigned char map[256];
-	unsigned char can_be_null;
-	unsigned char *p1;
-	unsigned char *p2;
-	unsigned char ch;
-	int a;
-	int b;
-	int num_instructions = 0;
-
-	a = (unsigned char)*code++;
-	a |= (unsigned char)*code++ << 8;
-	a = (int)SHORT(a);
-	
-	p1 = code + a + 3; /* skip the failure_jump */
-	/* Check that the jump is within the pattern */
-	if (p1<bufp->buffer || bufp->buffer+bufp->used<p1)
-	  {
-	    PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (failure_jump opt)");
-	    return 0;
-	  }
-	
-	assert(p1[-3] == Cfailure_jump);
-	p2 = code;
-	/* p1 points inside loop, p2 points to after loop */
-	if (!re_do_compile_fastmap(bufp->buffer, bufp->used,
-				   (int)(p2 - bufp->buffer),
-				   &can_be_null, map))
-		goto make_normal_jump;
-	
-	/* If we might introduce a new update point inside the
-	 * loop, we can't optimize because then update_jump would
-	 * update a wrong failure point.  Thus we have to be
-	 * quite careful here.
-	 */
-	
-	/* loop until we find something that consumes a character */
-  loop_p1:
-	num_instructions++;
-	switch (*p1++)
-	{
-	case Cbol:
-	case Ceol:
-	case Cbegbuf:
-	case Cendbuf:
-	case Cwordbeg:
-	case Cwordend:
-	case Cwordbound:
-	case Cnotwordbound:
-	{
-		goto loop_p1;
-	}
-	case Cstart_memory:
-	case Cend_memory:
-	{
-		p1++;
-		goto loop_p1;
-	}
-	case Cexact:
-	{
-		ch = (unsigned char)*p1++;
-		if (map[(int)ch])
-			goto make_normal_jump;
-		break;
-	}
-	case Canychar:
-	{
-		for (b = 0; b < 256; b++)
-			if (b != '\n' && map[b])
-				goto make_normal_jump;
-		break;
-	}
-	case Cset:
-	{
-		for (b = 0; b < 256; b++)
-			if ((p1[b >> 3] & (1 << (b & 7))) && map[b])
-				goto make_normal_jump;
-		p1 += 256/8;
-		break;
-	}
-	default:
-	{
-		goto make_normal_jump;
-	}
-	}
-	/* now we know that we can't backtrack. */
-	while (p1 != p2 - 3)
-	{
-		num_instructions++;
-		switch (*p1++)
-		{
-		case Cend:
-		{
-			return 0;
-		}
-		case Cbol:
-		case Ceol:
-		case Canychar:
-		case Cbegbuf:
-		case Cendbuf:
-		case Cwordbeg:
-		case Cwordend:
-		case Cwordbound:
-		case Cnotwordbound:
-		{
-			break;
-		}
-		case Cset:
-		{
-			p1 += 256/8;
-			break;
-		}
-		case Cexact:
-		case Cstart_memory:
-		case Cend_memory:
-		case Cmatch_memory:
-		case Csyntaxspec:
-		case Cnotsyntaxspec:
-		{
-			p1++;
-			break;
-		}
-		case Cjump:
-		case Cstar_jump:
-		case Cfailure_jump:
-		case Cupdate_failure_jump:
-		case Cdummy_failure_jump:
-		{
-			goto make_normal_jump;
-		}
-		default:
-		{
-			return 0;
-		}
-		}
-	}
-	
-	/* make_update_jump: */
-	code -= 3;
-	a += 3;  /* jump to after the Cfailure_jump */
-	code[0] = Cupdate_failure_jump;
-	code[1] = a & 0xff;
-	code[2] = a >> 8;
-	if (num_instructions > 1)
-		return 1;
-	assert(num_instructions == 1);
-	/* if the only instruction matches a single character, we can do
-	 * better */
-	p1 = code + 3 + a;   /* start of sole instruction */
-	if (*p1 == Cset || *p1 == Cexact || *p1 == Canychar ||
-	    *p1 == Csyntaxspec || *p1 == Cnotsyntaxspec)
-		code[0] = Crepeat1;
-	return 1;
-	
-  make_normal_jump:
-	code -= 3;
-	*code = Cjump;
-	return 1;
-}
-
-static int re_optimize(regexp_t bufp)
-{
-	unsigned char *code;
-	
-	code = bufp->buffer;
-	
-	while(1)
-	{
-		switch (*code++)
-		{
-		case Cend:
-		{
-			return 1;
-		}
-		case Canychar:
-		case Cbol:
-		case Ceol:
-		case Cbegbuf:
-		case Cendbuf:
-		case Cwordbeg:
-		case Cwordend:
-		case Cwordbound:
-		case Cnotwordbound:
-		{
-			break;
-		}
-		case Cset:
-		{
-			code += 256/8;
-			break;
-		}
-		case Cexact:
-		case Cstart_memory:
-		case Cend_memory:
-		case Cmatch_memory:
-		case Csyntaxspec:
-		case Cnotsyntaxspec:
-		{
-			code++;
-			break;
-		}
-		case Cstar_jump:
-		{
-			if (!re_optimize_star_jump(bufp, code))
-			{
-				return 0;
-			}
-			/* fall through */
-		}
-		case Cupdate_failure_jump:
-		case Cjump:
-		case Cdummy_failure_jump:
-		case Cfailure_jump:
-		case Crepeat1:
-		{
-			code += 2;
-			break;
-		}
-		default:
-		{
-			return 0;
-		}
-		}
-	}
-}
-
-#define NEXTCHAR(var) \
-{ \
-	if (pos >= size) \
-		goto ends_prematurely; \
-	(var) = regex[pos]; \
-	pos++; \
-}
-
-#define ALLOC(amount) \
-{ \
-	  if (pattern_offset+(amount) > alloc) \
-	  { \
-		  alloc += 256 + (amount); \
-		  pattern = realloc(pattern, alloc); \
-		  if (!pattern) \
-			  goto out_of_memory; \
-	  } \
-}
-
-#define STORE(ch) pattern[pattern_offset++] = (ch)
-
-#define CURRENT_LEVEL_START (starts[starts_base + current_level])
-
-#define SET_LEVEL_START starts[starts_base + current_level] = pattern_offset
-
-#define PUSH_LEVEL_STARTS \
-if (starts_base < (MAX_NESTING-1)*NUM_LEVELS) \
-	starts_base += NUM_LEVELS; \
-else \
-	goto too_complex \
-
-#define POP_LEVEL_STARTS starts_base -= NUM_LEVELS
-
-#define PUT_ADDR(offset,addr) \
-{ \
-	int disp = (addr) - (offset) - 2; \
-	pattern[(offset)] = disp & 0xff; \
-	pattern[(offset)+1] = (disp>>8) & 0xff; \
-}
-
-#define INSERT_JUMP(pos,type,addr) \
-{ \
-	int a, p = (pos), t = (type), ad = (addr); \
-	for (a = pattern_offset - 1; a >= p; a--) \
-		pattern[a + 3] = pattern[a]; \
-	pattern[p] = t; \
-	PUT_ADDR(p+1,ad); \
-	pattern_offset += 3; \
-}
-
-#define SETBIT(buf,offset,bit) (buf)[(offset)+(bit)/8] |= (1<<((bit) & 7))
-
-#define SET_FIELDS \
-{ \
-	bufp->allocated = alloc; \
-	bufp->buffer = pattern; \
-	bufp->used = pattern_offset; \
-}
-    
-#define GETHEX(var) \
-{ \
-	unsigned char gethex_ch, gethex_value; \
-	NEXTCHAR(gethex_ch); \
-	gethex_value = hex_char_to_decimal(gethex_ch); \
-	if (gethex_value == 16) \
-		goto hex_error; \
-	NEXTCHAR(gethex_ch); \
-	gethex_ch = hex_char_to_decimal(gethex_ch); \
-	if (gethex_ch == 16) \
-		goto hex_error; \
-	(var) = gethex_value * 16 + gethex_ch; \
-}
-
-#define ANSI_TRANSLATE(ch) \
-{ \
-	switch (ch) \
-	{ \
-	case 'a': \
-	case 'A': \
-	{ \
-		ch = 7; /* audible bell */ \
-		break; \
-	} \
-	case 'b': \
-	case 'B': \
-	{ \
-		ch = 8; /* backspace */ \
-		break; \
-	} \
-	case 'f': \
-	case 'F': \
-	{ \
-		ch = 12; /* form feed */ \
-		break; \
-	} \
-	case 'n': \
-	case 'N': \
-	{ \
-		ch = 10; /* line feed */ \
-		break; \
-	} \
-	case 'r': \
-	case 'R': \
-	{ \
-		ch = 13; /* carriage return */ \
-		break; \
-	} \
-	case 't': \
-	case 'T': \
-	{ \
-	      ch = 9; /* tab */ \
-	      break; \
-	} \
-	case 'v': \
-	case 'V': \
-	{ \
-		ch = 11; /* vertical tab */ \
-		break; \
-	} \
-	case 'x': /* hex code */ \
-	case 'X': \
-	{ \
-		GETHEX(ch); \
-		break; \
-	} \
-	default: \
-	{ \
-		/* other characters passed through */ \
-		if (translate) \
-			ch = translate[(unsigned char)ch]; \
-		break; \
-	} \
-	} \
-}
-
-char *re_compile_pattern(unsigned char *regex, int size, regexp_t bufp)
-{
-	int a;
-	int pos;
-	int op;
-	int current_level;
-	int level;
-	int opcode;
-	int pattern_offset = 0, alloc;
-	int starts[NUM_LEVELS * MAX_NESTING];
-	int starts_base;
-	int future_jumps[MAX_NESTING];
-	int num_jumps;
-	unsigned char ch = '\0';
-	unsigned char *pattern;
-	unsigned char *translate;
-	int next_register;
-	int paren_depth;
-	int num_open_registers;
-	int open_registers[RE_NREGS];
-	int beginning_context;
-	
-	if (!re_compile_initialized)
-		re_compile_initialize();
-	bufp->used = 0;
-	bufp->fastmap_accurate = 0;
-	bufp->uses_registers = 1;
-	bufp->num_registers = 1;
-	translate = bufp->translate;
-	pattern = bufp->buffer;
-	alloc = bufp->allocated;
-	if (alloc == 0 || pattern == NULL)
-	{
-		alloc = 256;
-		pattern = malloc(alloc);
-		if (!pattern)
-			goto out_of_memory;
-	}
-	pattern_offset = 0;
-	starts_base = 0;
-	num_jumps = 0;
-	current_level = 0;
-	SET_LEVEL_START;
-	num_open_registers = 0;
-	next_register = 1;
-	paren_depth = 0;
-	beginning_context = 1;
-	op = -1;
-	/* we use Rend dummy to ensure that pending jumps are updated
-	   (due to low priority of Rend) before exiting the loop. */
-	pos = 0;
-	while (op != Rend)
-	{
-		if (pos >= size)
-			op = Rend;
-		else
-		{
-			NEXTCHAR(ch);
-			if (translate)
-				ch = translate[(unsigned char)ch];
-			op = regexp_plain_ops[(unsigned char)ch];
-			if (op == Rquote)
-			{
-				NEXTCHAR(ch);
-				op = regexp_quoted_ops[(unsigned char)ch];
-				if (op == Rnormal && regexp_ansi_sequences)
-					ANSI_TRANSLATE(ch);
-			}
-		}
-		level = regexp_precedences[op];
-		/* printf("ch='%c' op=%d level=%d current_level=%d
-		   curlevstart=%d\n", ch, op, level, current_level,
-		   CURRENT_LEVEL_START); */
-		if (level > current_level)
-		{
-			for (current_level++; current_level < level; current_level++)
-				SET_LEVEL_START;
-			SET_LEVEL_START;
-		}
-		else
-			if (level < current_level)
-			{
-				current_level = level;
-				for (;num_jumps > 0 &&
-					     future_jumps[num_jumps-1] >= CURRENT_LEVEL_START;
-				     num_jumps--)
-					PUT_ADDR(future_jumps[num_jumps-1], pattern_offset);
-			}
-		switch (op)
-		{
-		case Rend:
-		{
-			break;
-		}
-		case Rnormal:
-		{
-		  normal_char:
-			opcode = Cexact;
-		  store_opcode_and_arg: /* opcode & ch must be set */
-			SET_LEVEL_START;
-			ALLOC(2);
-			STORE(opcode);
-			STORE(ch);
-			break;
-		}
-		case Ranychar:
-		{
-			opcode = Canychar;
-		  store_opcode:
-			SET_LEVEL_START;
-			ALLOC(1);
-			STORE(opcode);
-			break;
-		}
-		case Rquote:
-		{
-			Py_FatalError("Rquote");
-			/*NOTREACHED*/
-		}
-		case Rbol:
-		{
-			if (!beginning_context) {
-				if (regexp_context_indep_ops)
-					goto op_error;
-				else
-					goto normal_char;
-			}
-			opcode = Cbol;
-			goto store_opcode;
-		}
-		case Reol:
-		{
-			if (!((pos >= size) ||
-			      ((regexp_syntax & RE_NO_BK_VBAR) ?
-			       (regex[pos] == '\174') :
-			       (pos+1 < size && regex[pos] == '\134' &&
-				regex[pos+1] == '\174')) ||
-			      ((regexp_syntax & RE_NO_BK_PARENS)?
-			       (regex[pos] == ')'):
-			       (pos+1 < size && regex[pos] == '\134' &&
-				regex[pos+1] == ')')))) {
-				if (regexp_context_indep_ops)
-					goto op_error;
-				else
-					goto normal_char;
-			}
-			opcode = Ceol;
-			goto store_opcode;
-			/* NOTREACHED */
-			break;
-		}
-		case Roptional:
-		{
-			if (beginning_context) {
-				if (regexp_context_indep_ops)
-					goto op_error;
-				else
-					goto normal_char;
-			}
-			if (CURRENT_LEVEL_START == pattern_offset)
-				break; /* ignore empty patterns for ? */
-			ALLOC(3);
-			INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
-				    pattern_offset + 3);
-			break;
-		}
-		case Rstar:
-		case Rplus:
-		{
-			if (beginning_context) {
-				if (regexp_context_indep_ops)
-					goto op_error;
-				else
-					goto normal_char;
-			}
-			if (CURRENT_LEVEL_START == pattern_offset)
-				break; /* ignore empty patterns for + and * */
-			ALLOC(9);
-			INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
-				    pattern_offset + 6);
-			INSERT_JUMP(pattern_offset, Cstar_jump, CURRENT_LEVEL_START);
-			if (op == Rplus)  /* jump over initial failure_jump */
-				INSERT_JUMP(CURRENT_LEVEL_START, Cdummy_failure_jump,
-					    CURRENT_LEVEL_START + 6);
-			break;
-		}
-		case Ror:
-		{
-			ALLOC(6);
-			INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
-				    pattern_offset + 6);
-			if (num_jumps >= MAX_NESTING)
-				goto too_complex;
-			STORE(Cjump);
-			future_jumps[num_jumps++] = pattern_offset;
-			STORE(0);
-			STORE(0);
-			SET_LEVEL_START;
-			break;
-		}
-		case Ropenpar:
-		{
-			SET_LEVEL_START;
-			if (next_register < RE_NREGS)
-			{
-				bufp->uses_registers = 1;
-				ALLOC(2);
-				STORE(Cstart_memory);
-				STORE(next_register);
-				open_registers[num_open_registers++] = next_register;
-				bufp->num_registers++;
-				next_register++;
-			}
-			paren_depth++;
-			PUSH_LEVEL_STARTS;
-			current_level = 0;
-			SET_LEVEL_START;
-			break;
-		}
-		case Rclosepar:
-		{
-			if (paren_depth <= 0)
-				goto parenthesis_error;
-			POP_LEVEL_STARTS;
-			current_level = regexp_precedences[Ropenpar];
-			paren_depth--;
-			if (paren_depth < num_open_registers)
-			{
-				bufp->uses_registers = 1;
-				ALLOC(2);
-				STORE(Cend_memory);
-				num_open_registers--;
-				STORE(open_registers[num_open_registers]);
-			}
-			break;
-		}
-		case Rmemory:
-		{
-			if (ch == '0')
-				goto bad_match_register;
-			assert(ch >= '0' && ch <= '9');
-			bufp->uses_registers = 1;
-			opcode = Cmatch_memory;
-			ch -= '0';
-			goto store_opcode_and_arg;
-		}
-		case Rextended_memory:
-		{
-			NEXTCHAR(ch);
-			if (ch < '0' || ch > '9')
-				goto bad_match_register;
-			NEXTCHAR(a);
-			if (a < '0' || a > '9')
-				goto bad_match_register;
-			ch = 10 * (a - '0') + ch - '0';
-			if (ch == 0 || ch >= RE_NREGS)
-				goto bad_match_register;
-			bufp->uses_registers = 1;
-			opcode = Cmatch_memory;
-			goto store_opcode_and_arg;
-		}
-		case Ropenset:
-		{
-			int complement;
-			int prev;
-			int offset;
-			int range;
-                        int firstchar;
-                        
-			SET_LEVEL_START;
-			ALLOC(1+256/8);
-			STORE(Cset);
-			offset = pattern_offset;
-			for (a = 0; a < 256/8; a++)
-				STORE(0);
-			NEXTCHAR(ch);
-			if (translate)
-				ch = translate[(unsigned char)ch];
-			if (ch == '\136')
-			{
-				complement = 1;
-				NEXTCHAR(ch);
-				if (translate)
-					ch = translate[(unsigned char)ch];
-			}
-			else
-				complement = 0;
-			prev = -1;
-			range = 0;
-			firstchar = 1;
-			while (ch != '\135' || firstchar)
-			{
-				firstchar = 0;
-				if (regexp_ansi_sequences && ch == '\134')
-				{
-					NEXTCHAR(ch);
-					ANSI_TRANSLATE(ch);
-				}
-				if (range)
-				{
-					for (a = prev; a <= (int)ch; a++)
-						SETBIT(pattern, offset, a);
-					prev = -1;
-					range = 0;
-				}
-				else
-					if (prev != -1 && ch == '-')
-						range = 1;
-					else
-					{
-						SETBIT(pattern, offset, ch);
-						prev = ch;
-					}
-				NEXTCHAR(ch);
-				if (translate)
-					ch = translate[(unsigned char)ch];
-			}
-			if (range)
-				SETBIT(pattern, offset, '-');
-			if (complement)
-			{
-				for (a = 0; a < 256/8; a++)
-					pattern[offset+a] ^= 0xff;
-			}
-			break;
-		}
-		case Rbegbuf:
-		{
-			opcode = Cbegbuf;
-			goto store_opcode;
-		}
-		case Rendbuf:
-		{
-			opcode = Cendbuf;
-			goto store_opcode;
-		}
-		case Rwordchar:
-		{
-			opcode = Csyntaxspec;
-			ch = Sword;
-			goto store_opcode_and_arg;
-		}
-		case Rnotwordchar:
-		{
-			opcode = Cnotsyntaxspec;
-			ch = Sword;
-			goto store_opcode_and_arg;
-		}
-		case Rwordbeg:
-		{
-			opcode = Cwordbeg;
-			goto store_opcode;
-		}
-		case Rwordend:
-		{
-			opcode = Cwordend;
-			goto store_opcode;
-		}
-		case Rwordbound:
-		{
-			opcode = Cwordbound;
-			goto store_opcode;
-		}
-		case Rnotwordbound:
-		{
-			opcode = Cnotwordbound;
-			goto store_opcode;
-		}
-		default:
-		{
-			abort();
-		}
-		}
-		beginning_context = (op == Ropenpar || op == Ror);
-	}
-	if (starts_base != 0)
-		goto parenthesis_error;
-	assert(num_jumps == 0);
-	ALLOC(1);
-	STORE(Cend);
-	SET_FIELDS;
-	if(!re_optimize(bufp))
-		return "Optimization error";
-	return NULL;
-
-  op_error:
-	SET_FIELDS;
-	return "Badly placed special character";
-
-  bad_match_register:
-	SET_FIELDS;
-	return "Bad match register number";
-   
-  hex_error:
-	SET_FIELDS;
-	return "Bad hexadecimal number";
-   
-  parenthesis_error:
-	SET_FIELDS;
-	return "Badly placed parenthesis";
-   
-  out_of_memory:
-	SET_FIELDS;
-	return "Out of memory";
-   
-  ends_prematurely:
-	SET_FIELDS;
-	return "Regular expression ends prematurely";
-
-  too_complex:
-	SET_FIELDS;
-	return "Regular expression too complex";
-}
-
-#undef CHARAT
-#undef NEXTCHAR
-#undef GETHEX
-#undef ALLOC
-#undef STORE
-#undef CURRENT_LEVEL_START
-#undef SET_LEVEL_START
-#undef PUSH_LEVEL_STARTS
-#undef POP_LEVEL_STARTS
-#undef PUT_ADDR
-#undef INSERT_JUMP
-#undef SETBIT
-#undef SET_FIELDS
-
-#define PREFETCH if (text == textend) goto fail
-
-#define NEXTCHAR(var) \
-PREFETCH; \
-var = (unsigned char)*text++; \
-if (translate) \
-	var = translate[var]
-
-int re_match(regexp_t bufp, unsigned char *string, int size, int pos,
-             regexp_registers_t old_regs)
-{
-	unsigned char *code;
-	unsigned char *translate;
-	unsigned char *text;
-	unsigned char *textstart;
-	unsigned char *textend;
-	int a;
-	int b;
-	int ch;
-	int reg;
-	int match_end;
-	unsigned char *regstart;
-	unsigned char *regend;
-	int regsize;
-	match_state state;
-  
-	assert(pos >= 0 && size >= 0);
-	assert(pos <= size);
-  
-	text = string + pos;
-	textstart = string;
-	textend = string + size;
-  
-	code = bufp->buffer;
-  
-	translate = bufp->translate;
-  
-	NEW_STATE(state, bufp->num_registers);
-
-  continue_matching:
-	switch (*code++)
-	{
-	case Cend:
-	{
-		match_end = text - textstart;
-		if (old_regs)
-		{
-			old_regs->start[0] = pos;
-			old_regs->end[0] = match_end;
-			if (!bufp->uses_registers)
-			{
-				for (a = 1; a < RE_NREGS; a++)
-				{
-					old_regs->start[a] = -1;
-					old_regs->end[a] = -1;
-				}
-			}
-			else
-			{
-				for (a = 1; a < bufp->num_registers; a++)
-				{
-					if ((GET_REG_START(state, a) == NULL) ||
-					    (GET_REG_END(state, a) == NULL))
-					{
-						old_regs->start[a] = -1;
-						old_regs->end[a] = -1;
-						continue;
-					}
-					old_regs->start[a] = GET_REG_START(state, a) - textstart;
-					old_regs->end[a] = GET_REG_END(state, a) - textstart;
-				}
-				for (; a < RE_NREGS; a++)
-				{
-					old_regs->start[a] = -1;
-					old_regs->end[a] = -1;
-				}
-			}
-		}
-		FREE_STATE(state);
-		return match_end - pos;
-	}
-	case Cbol:
-	{
-		if (text == textstart || text[-1] == '\n')
-			goto continue_matching;
-		goto fail;
-	}
-	case Ceol:
-	{
-		if (text == textend || *text == '\n')
-			goto continue_matching;
-		goto fail;
-	}
-	case Cset:
-	{
-		NEXTCHAR(ch);
-		if (code[ch/8] & (1<<(ch & 7)))
-		{
-			code += 256/8;
-			goto continue_matching;
-		}
-		goto fail;
-	}
-	case Cexact:
-	{
-		NEXTCHAR(ch);
-		if (ch != (unsigned char)*code++)
-			goto fail;
-		goto continue_matching;
-	}
-	case Canychar:
-	{
-		NEXTCHAR(ch);
-		if (ch == '\n')
-			goto fail;
-		goto continue_matching;
-	}
-	case Cstart_memory:
-	{
-		reg = *code++;
-		SET_REG_START(state, reg, text, goto error);
-		goto continue_matching;
-	}
-	case Cend_memory:
-	{
-		reg = *code++;
-		SET_REG_END(state, reg, text, goto error);
-		goto continue_matching;
-	}
-	case Cmatch_memory:
-	{
-		reg = *code++;
-		regstart = GET_REG_START(state, reg);
-		regend = GET_REG_END(state, reg);
-		if ((regstart == NULL) || (regend == NULL))
-			goto fail;  /* or should we just match nothing? */
-		regsize = regend - regstart;
-
-		if (regsize > (textend - text))
-			goto fail;
-		if(translate)
-		{
-			for (; regstart < regend; regstart++, text++)
-				if (translate[*regstart] != translate[*text])
-					goto fail;
-		}
-		else
-			for (; regstart < regend; regstart++, text++)
-				if (*regstart != *text)
-					goto fail;
-		goto continue_matching;
-	}
-	case Cupdate_failure_jump:
-	{
-		UPDATE_FAILURE(state, text, goto error);
-		/* fall to next case */
-	}
-	/* treat Cstar_jump just like Cjump if it hasn't been optimized */
-	case Cstar_jump:
-	case Cjump:
-	{
-		a = (unsigned char)*code++;
-		a |= (unsigned char)*code++ << 8;
-		code += (int)SHORT(a);
-		if (code<bufp->buffer || bufp->buffer+bufp->used<code) {
-		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cjump)");
-			FREE_STATE(state);
-            	        return -2;
-         	}
-		goto continue_matching;
-	}
-	case Cdummy_failure_jump:
-	{
-                unsigned char *failuredest;
-	  
-		a = (unsigned char)*code++;
-		a |= (unsigned char)*code++ << 8;
-		a = (int)SHORT(a);
-		assert(*code == Cfailure_jump);
-		b = (unsigned char)code[1];
-		b |= (unsigned char)code[2] << 8;
-                failuredest = code + (int)SHORT(b) + 3;
-		if (failuredest<bufp->buffer || bufp->buffer+bufp->used < failuredest) {
-		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cdummy_failure_jump failuredest)");
-			FREE_STATE(state);
-            	        return -2;
-		}
-		PUSH_FAILURE(state, failuredest, NULL, goto error);
-		code += a;
-		if (code<bufp->buffer || bufp->buffer+bufp->used < code) {
-		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cdummy_failure_jump code)");
-			FREE_STATE(state);
-            	        return -2;
-         	}
-		goto continue_matching;
-	}
-	case Cfailure_jump:
-	{
-		a = (unsigned char)*code++;
-		a |= (unsigned char)*code++ << 8;
-		a = (int)SHORT(a);
-		if (code+a<bufp->buffer || bufp->buffer+bufp->used < code+a) {
-		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cfailure_jump)");
-			FREE_STATE(state);
-            	        return -2;
-         	}
-		PUSH_FAILURE(state, code + a, text, goto error);
-		goto continue_matching;
-	}
-	case Crepeat1:
-	{
-		unsigned char *pinst;
-		a = (unsigned char)*code++;
-		a |= (unsigned char)*code++ << 8;
-		a = (int)SHORT(a);
-		pinst = code + a;
-		if (pinst<bufp->buffer || bufp->buffer+bufp->used<pinst) {
-		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Crepeat1)");
-			FREE_STATE(state);
-            	        return -2;
-         	}
-		/* pinst is sole instruction in loop, and it matches a
-		 * single character.  Since Crepeat1 was originally a
-		 * Cupdate_failure_jump, we also know that backtracking
-		 * is useless: so long as the single-character
-		 * expression matches, it must be used.  Also, in the
-		 * case of +, we've already matched one character, so +
-		 * can't fail: nothing here can cause a failure.  */
-		switch (*pinst++)
-		{
-		case Cset:
-		  {
-		        if (translate)
-			{
-				while (text < textend)
-				{
-					ch = translate[(unsigned char)*text];
-					if (pinst[ch/8] & (1<<(ch & 7)))
-						text++;
-					else
-						break;
-				}
-			}
-			else
-			{
-				while (text < textend)
-				{
-					ch = (unsigned char)*text;
-					if (pinst[ch/8] & (1<<(ch & 7)))
-						text++;
-					else
-						break;
-				}
-			}
-			break;
-                }
-		case Cexact:
-		{
-			ch = (unsigned char)*pinst;
-			if (translate)
-			{
-				while (text < textend &&
-				       translate[(unsigned char)*text] == ch)
-					text++;
-			}
-			else
-			{
-				while (text < textend && (unsigned char)*text == ch)
-					text++;
-			}
-			break;
-		}
-		case Canychar:
-		{
-			while (text < textend && (unsigned char)*text != '\n')
-				text++;
-			break;
-		}
-		case Csyntaxspec:
-		{
-			a = (unsigned char)*pinst;
-			if (translate)
-			{
-				while (text < textend &&
-				       (SYNTAX(translate[*text]) & a) )
-					text++;
-			}
-			else
-			{
-				while (text < textend && (SYNTAX(*text) & a) )
-					text++;
-			}
-			break;
-		}
-		case Cnotsyntaxspec:
-		{
-			a = (unsigned char)*pinst;
-			if (translate)
-			{
-				while (text < textend &&
-				       !(SYNTAX(translate[*text]) & a) )
-					text++;
-			}
-			else
-			{
-				while (text < textend && !(SYNTAX(*text) & a) )
-					text++;
-			}
-			break;
-		}
-		default:
-		{
-		        FREE_STATE(state);
-		        PyErr_SetString(PyExc_SystemError, "Unknown regex opcode: memory corrupted?");
-		        return -2;
-			/*NOTREACHED*/
-		}
-		}
-		/* due to the funky way + and * are compiled, the top
-		 * failure- stack entry at this point is actually a
-		 * success entry -- update it & pop it */
-		UPDATE_FAILURE(state, text, goto error);
-		goto fail;      /* i.e., succeed <wink/sigh> */
-	}
-	case Cbegbuf:
-	{
-		if (text == textstart)
-			goto continue_matching;
-		goto fail;
-	}
-	case Cendbuf:
-	{
-		if (text == textend)
-			goto continue_matching;
-		goto fail;
-	}
-	case Cwordbeg:
-	{
-		if (text == textend)
-			goto fail;
-		if (!(SYNTAX(*text) & Sword)) 
-			goto fail;
-		if (text == textstart)
-			goto continue_matching;
-		if (!(SYNTAX(text[-1]) & Sword))
-			goto continue_matching;
-		goto fail;
-	}
-	case Cwordend:
-	{
-		if (text == textstart)
-			goto fail;
-		if (!(SYNTAX(text[-1]) & Sword))
-			goto fail;
-		if (text == textend)
-			goto continue_matching;
-		if (!(SYNTAX(*text) & Sword))
-		        goto continue_matching;
-                goto fail;
-	}
-	case Cwordbound:
-	{
-		/* Note: as in gnu regexp, this also matches at the
-		 * beginning and end of buffer.  */
-
-		if (text == textstart || text == textend)
-			goto continue_matching;
-		if ((SYNTAX(text[-1]) & Sword) ^ (SYNTAX(*text) & Sword))
-			goto continue_matching;
-		goto fail;
-	}
-	case Cnotwordbound:
-	{
-		/* Note: as in gnu regexp, this never matches at the
-		 * beginning and end of buffer.  */
-		if (text == textstart || text == textend)
-			goto fail;
-		if (!((SYNTAX(text[-1]) & Sword) ^ (SYNTAX(*text) & Sword)))
-      		        goto continue_matching;
-		goto fail;
-	}
-	case Csyntaxspec:
-	{
-		NEXTCHAR(ch);
-		if (!(SYNTAX(ch) & (unsigned char)*code++))
-			goto fail;
-		goto continue_matching;
-	}
-	case Cnotsyntaxspec:
-	{
-		NEXTCHAR(ch);
-		if (SYNTAX(ch) & (unsigned char)*code++)
-			goto fail;
-		goto continue_matching;
-	}
-	default:
-	{
-	        FREE_STATE(state);
-	        PyErr_SetString(PyExc_SystemError, "Unknown regex opcode: memory corrupted?");
-		return -2;
-		/*NOTREACHED*/
-	}
-	}
-	
-	
-
-#if 0 /* This line is never reached --Guido */
-	abort();
-#endif
-	/*
-	 *NOTREACHED
-	 */
-
-	/* Using "break;" in the above switch statement is equivalent to "goto fail;" */
-  fail:
-	POP_FAILURE(state, code, text, goto done_matching, goto error);
-	goto continue_matching;
-  
-  done_matching:
-/*   if(translated != NULL) */
-/*      free(translated); */
-	FREE_STATE(state);
-	return -1;
-
-  error:
-/*   if (translated != NULL) */
-/*      free(translated); */
-	FREE_STATE(state);
-	return -2;
-}
-	
-
-#undef PREFETCH
-#undef NEXTCHAR
-
-int re_search(regexp_t bufp, unsigned char *string, int size, int pos,
-              int range, regexp_registers_t regs)
-{
-	unsigned char *fastmap;
-	unsigned char *translate;
-	unsigned char *text;
-	unsigned char *partstart;
-	unsigned char *partend;
-	int dir;
-	int ret;
-	unsigned char anchor;
-  
-	assert(size >= 0 && pos >= 0);
-	assert(pos + range >= 0 && pos + range <= size); /* Bugfix by ylo */
-  
-	fastmap = bufp->fastmap;
-	translate = bufp->translate;
-	if (fastmap && !bufp->fastmap_accurate) {
-                re_compile_fastmap(bufp);
-	        if (PyErr_Occurred()) return -2;
-	}
-	
-	anchor = bufp->anchor;
-	if (bufp->can_be_null == 1) /* can_be_null == 2: can match null at eob */
-		fastmap = NULL;
-
-	if (range < 0)
-	{
-		dir = -1;
-		range = -range;
-	}
-	else
-		dir = 1;
-
-	if (anchor == 2) {
-		if (pos != 0)
-			return -1;
-		else
-			range = 0;
-	}
-
-	for (; range >= 0; range--, pos += dir)
-	{
-		if (fastmap)
-		{
-			if (dir == 1)
-			{ /* searching forwards */
-
-				text = string + pos;
-				partend = string + size;
-				partstart = text;
-				if (translate)
-					while (text != partend &&
-					       !fastmap[(unsigned char) translate[(unsigned char)*text]])
-						text++;
-				else
-					while (text != partend && !fastmap[(unsigned char)*text])
-						text++;
-				pos += text - partstart;
-				range -= text - partstart;
-				if (pos == size && bufp->can_be_null == 0)
-					return -1;
-			}
-			else
-			{ /* searching backwards */
-				text = string + pos;
-				partstart = string + pos - range;
-				partend = text;
-				if (translate)
-					while (text != partstart &&
-					       !fastmap[(unsigned char)
-						       translate[(unsigned char)*text]])
-						text--;
-				else
-					while (text != partstart &&
-					       !fastmap[(unsigned char)*text])
-						text--;
-				pos -= partend - text;
-				range -= partend - text;
-			}
-		}
-		if (anchor == 1)
-		{ /* anchored to begline */
-			if (pos > 0 && (string[pos - 1] != '\n'))
-				continue;
-		}
-		assert(pos >= 0 && pos <= size);
-		ret = re_match(bufp, string, size, pos, regs);
-		if (ret >= 0)
-			return pos;
-		if (ret == -2)
-			return -2;
-	}
-	return -1;
-}
-
-/*
-** Local Variables:
-** mode: c
-** c-file-style: "python"
-** End:
-*/
diff --git a/Modules/regexpr.h b/Modules/regexpr.h
deleted file mode 100644
index 2aee62d..0000000
--- a/Modules/regexpr.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * -*- mode: c-mode; c-file-style: python -*-
- */
-
-#ifndef Py_REGEXPR_H
-#define Py_REGEXPR_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * regexpr.h
- *
- * Author: Tatu Ylonen <ylo@ngs.fi>
- *
- * Copyright (c) 1991 Tatu Ylonen, Espoo, Finland
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies.  This
- * software is provided "as is" without express or implied warranty.
- *
- * Created: Thu Sep 26 17:15:36 1991 ylo
- * Last modified: Mon Nov  4 15:49:46 1991 ylo
- */
-
-/* $Id$ */
-
-#ifndef REGEXPR_H
-#define REGEXPR_H
-
-#define RE_NREGS	100  /* number of registers available */
-
-typedef struct re_pattern_buffer
-{
-	unsigned char *buffer;          /* compiled pattern */
-	int allocated;         /* allocated size of compiled pattern */
-	int used;              /* actual length of compiled pattern */
-	unsigned char *fastmap;         /* fastmap[ch] is true if ch can start pattern */
-	unsigned char *translate;       /* translation to apply during compilation/matching */
-	unsigned char fastmap_accurate; /* true if fastmap is valid */
-	unsigned char can_be_null;      /* true if can match empty string */
-	unsigned char uses_registers;   /* registers are used and need to be initialized */
-	int num_registers;     /* number of registers used */
-	unsigned char anchor;           /* anchor: 0=none 1=begline 2=begbuf */
-} *regexp_t;
-
-typedef struct re_registers
-{
-	int start[RE_NREGS];  /* start offset of region */
-	int end[RE_NREGS];    /* end offset of region */
-} *regexp_registers_t;
-
-/* bit definitions for syntax */
-#define RE_NO_BK_PARENS		1    /* no quoting for parentheses */
-#define RE_NO_BK_VBAR		2    /* no quoting for vertical bar */
-#define RE_BK_PLUS_QM		4    /* quoting needed for + and ? */
-#define RE_TIGHT_VBAR		8    /* | binds tighter than ^ and $ */
-#define RE_NEWLINE_OR		16   /* treat newline as or */
-#define RE_CONTEXT_INDEP_OPS	32   /* ^$?*+ are special in all contexts */
-#define RE_ANSI_HEX		64   /* ansi sequences (\n etc) and \xhh */
-#define RE_NO_GNU_EXTENSIONS   128   /* no gnu extensions */
-
-/* definitions for some common regexp styles */
-#define RE_SYNTAX_AWK	(RE_NO_BK_PARENS|RE_NO_BK_VBAR|RE_CONTEXT_INDEP_OPS)
-#define RE_SYNTAX_EGREP	(RE_SYNTAX_AWK|RE_NEWLINE_OR)
-#define RE_SYNTAX_GREP	(RE_BK_PLUS_QM|RE_NEWLINE_OR)
-#define RE_SYNTAX_EMACS	0
-
-#define Sword       1
-#define Swhitespace 2
-#define Sdigit      4
-#define Soctaldigit 8
-#define Shexdigit   16
-
-/* Rename all exported symbols to avoid conflicts with similarly named
-   symbols in some systems' standard C libraries... */
-
-#define re_syntax _Py_re_syntax
-#define re_syntax_table _Py_re_syntax_table
-#define re_compile_initialize _Py_re_compile_initialize
-#define re_set_syntax _Py_re_set_syntax
-#define re_compile_pattern _Py_re_compile_pattern
-#define re_match _Py_re_match
-#define re_search _Py_re_search
-#define re_compile_fastmap _Py_re_compile_fastmap
-#define re_comp _Py_re_comp
-#define re_exec _Py_re_exec
-
-#ifdef HAVE_PROTOTYPES
-
-extern int re_syntax;
-/* This is the actual syntax mask.  It was added so that Python could do
- * syntax-dependent munging of patterns before compilation. */
-
-extern unsigned char re_syntax_table[256];
-
-void re_compile_initialize(void);
-
-int re_set_syntax(int syntax);
-/* This sets the syntax to use and returns the previous syntax.  The
- * syntax is specified by a bit mask of the above defined bits. */
-
-char *re_compile_pattern(unsigned char *regex, int regex_size, regexp_t compiled);
-/* This compiles the regexp (given in regex and length in regex_size).
- * This returns NULL if the regexp compiled successfully, and an error
- * message if an error was encountered.  The buffer field must be
- * initialized to a memory area allocated by malloc (or to NULL) before
- * use, and the allocated field must be set to its length (or 0 if
- * buffer is NULL).  Also, the translate field must be set to point to a
- * valid translation table, or NULL if it is not used. */
-
-int re_match(regexp_t compiled, unsigned char *string, int size, int pos,
-	     regexp_registers_t old_regs);
-/* This tries to match the regexp against the string.  This returns the
- * length of the matched portion, or -1 if the pattern could not be
- * matched and -2 if an error (such as failure stack overflow) is
- * encountered. */
-
-int re_search(regexp_t compiled, unsigned char *string, int size, int startpos,
-	      int range, regexp_registers_t regs);
-/* This searches for a substring matching the regexp.  This returns the
- * first index at which a match is found.  range specifies at how many
- * positions to try matching; positive values indicate searching
- * forwards, and negative values indicate searching backwards.  mstop
- * specifies the offset beyond which a match must not go.  This returns
- * -1 if no match is found, and -2 if an error (such as failure stack
- * overflow) is encountered. */
-
-void re_compile_fastmap(regexp_t compiled);
-/* This computes the fastmap for the regexp.  For this to have any effect,
- * the calling program must have initialized the fastmap field to point
- * to an array of 256 characters. */
-
-#else /* HAVE_PROTOTYPES */
-
-extern int re_syntax;
-extern unsigned char re_syntax_table[256];
-void re_compile_initialize();
-int re_set_syntax();
-char *re_compile_pattern();
-int re_match();
-int re_search();
-void re_compile_fastmap();
-
-#endif /* HAVE_PROTOTYPES */
-
-#endif /* REGEXPR_H */
-
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* !Py_REGEXPR_H */
diff --git a/Modules/resource.c b/Modules/resource.c
index 7cbd2c9..e73c878 100644
--- a/Modules/resource.c
+++ b/Modules/resource.c
@@ -55,6 +55,7 @@
 	16	/* n_in_sequence */
 };
 
+static int initialized;
 static PyTypeObject StructRUsageType;
 
 static PyObject *
@@ -244,7 +245,10 @@
 	}
 	Py_INCREF(ResourceError);
 	PyModule_AddObject(m, "error", ResourceError);
- 	PyStructSequence_InitType(&StructRUsageType, &struct_rusage_desc);
+	if (!initialized)
+		PyStructSequence_InitType(&StructRUsageType, 
+					  &struct_rusage_desc);
+	Py_INCREF(&StructRUsageType);
  	PyModule_AddObject(m, "struct_rusage", 
 			   (PyObject*) &StructRUsageType);
 
@@ -320,4 +324,5 @@
 	if (v) {
 		PyModule_AddObject(m, "RLIM_INFINITY", v);
 	}
+	initialized = 1;
 }
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index c526d75..c9dd4a3 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -62,6 +62,7 @@
 */
 
 #include "Python.h"
+#include "structmember.h"
 
 #undef MAX
 #define MAX(x, y) ((x) < (y) ? (y) : (x))
@@ -967,7 +968,18 @@
 	case AF_UNIX:
 	{
 		struct sockaddr_un *a = (struct sockaddr_un *) addr;
-		return PyString_FromString(a->sun_path);
+#ifdef linux
+		if (a->sun_path[0] == 0) {  /* Linux abstract namespace */
+			addrlen -= (sizeof(*a) - sizeof(a->sun_path));
+			return PyString_FromStringAndSize(a->sun_path,
+							  addrlen);
+		}
+		else
+#endif /* linux */
+		{
+			/* regular NULL-terminated string */
+			return PyString_FromString(a->sun_path);
+		}
 	}
 #endif /* AF_UNIX */
 
@@ -1097,14 +1109,28 @@
 		addr = (struct sockaddr_un*)&(s->sock_addr).un;
 		if (!PyArg_Parse(args, "t#", &path, &len))
 			return 0;
-		if (len > sizeof addr->sun_path) {
-			PyErr_SetString(socket_error,
-					"AF_UNIX path too long");
-			return 0;
+#ifdef linux
+		if (len > 0 && path[0] == 0) {
+			/* Linux abstract namespace extension */
+			if (len > sizeof addr->sun_path) {
+				PyErr_SetString(socket_error,
+						"AF_UNIX path too long");
+				return 0;
+			}
+		}
+		else
+#endif /* linux */
+                {
+			/* regular NULL-terminated string */
+			if (len >= sizeof addr->sun_path) {
+				PyErr_SetString(socket_error,
+						"AF_UNIX path too long");
+				return 0;
+			}
+			addr->sun_path[len] = 0;
 		}
 		addr->sun_family = s->sock_family;
 		memcpy(addr->sun_path, path, len);
-		addr->sun_path[len] = 0;
 		*addr_ret = (struct sockaddr *) addr;
 #if defined(PYOS_OS2)
 		*len_ret = sizeof(*addr);
@@ -2207,18 +2233,20 @@
 	Py_BEGIN_ALLOW_THREADS
 	memset(&addrbuf, 0, addrlen);
 	timeout = internal_select(s, 0);
-	if (!timeout)
-		n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
+	if (!timeout) {
 #ifndef MS_WINDOWS
 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
-			     (struct sockaddr *) &addrbuf, &addrlen
+		n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
+			     (struct sockaddr *) &addrbuf, &addrlen);
 #else
-			     (void *) &addrbuf, &addrlen
+		n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
+			     (void *) &addrbuf, &addrlen);
 #endif
 #else
-			     (struct sockaddr *) &addrbuf, &addrlen
+		n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
+			     (struct sockaddr *) &addrbuf, &addrlen);
 #endif
-			);
+	}
 	Py_END_ALLOW_THREADS
 
 	if (timeout) {
@@ -2502,6 +2530,14 @@
 	{NULL,			NULL}		/* sentinel */
 };
 
+/* SockObject members */
+static PyMemberDef sock_memberlist[] = {
+       {"family", T_INT, offsetof(PySocketSockObject, sock_family), READONLY, "the socket family"},
+       {"type", T_INT, offsetof(PySocketSockObject, sock_type), READONLY, "the socket type"},
+       {"proto", T_INT, offsetof(PySocketSockObject, sock_proto), READONLY, "the socket protocol"},
+       {"timeout", T_DOUBLE, offsetof(PySocketSockObject, sock_timeout), READONLY, "the socket timeout"},
+       {0},
+};
 
 /* Deallocate a socket object in response to the last Py_DECREF().
    First close the file description. */
@@ -2625,7 +2661,7 @@
 	0,					/* tp_iter */
 	0,					/* tp_iternext */
 	sock_methods,				/* tp_methods */
-	0,					/* tp_members */
+	sock_memberlist,			/* tp_members */
 	0,					/* tp_getset */
 	0,					/* tp_base */
 	0,					/* tp_dict */
@@ -3159,7 +3195,8 @@
 PyDoc_STRVAR(fromfd_doc,
 "fromfd(fd, family, type[, proto]) -> socket object\n\
 \n\
-Create a socket object from the given file descriptor.\n\
+Create a socket object from a duplicate of the given\n\
+file descriptor.\n\
 The remaining arguments are the same as for socket().");
 
 #endif /* NO_DUP */
@@ -4026,7 +4063,12 @@
 	/*  */
 	PyModule_AddIntConstant(m, "AF_NETLINK", AF_NETLINK);
 	PyModule_AddIntConstant(m, "NETLINK_ROUTE", NETLINK_ROUTE);
+#ifdef NETLINK_SKIP
 	PyModule_AddIntConstant(m, "NETLINK_SKIP", NETLINK_SKIP);
+#endif
+#ifdef NETLINK_W1
+	PyModule_AddIntConstant(m, "NETLINK_W1", NETLINK_W1);
+#endif
 	PyModule_AddIntConstant(m, "NETLINK_USERSOCK", NETLINK_USERSOCK);
 	PyModule_AddIntConstant(m, "NETLINK_FIREWALL", NETLINK_FIREWALL);
 #ifdef NETLINK_TCPDIAG
@@ -4038,12 +4080,18 @@
 #ifdef NETLINK_XFRM
 	PyModule_AddIntConstant(m, "NETLINK_XFRM", NETLINK_XFRM);
 #endif
+#ifdef NETLINK_ARPD
 	PyModule_AddIntConstant(m, "NETLINK_ARPD", NETLINK_ARPD);
+#endif
+#ifdef NETLINK_ROUTE6
 	PyModule_AddIntConstant(m, "NETLINK_ROUTE6", NETLINK_ROUTE6);
+#endif
 	PyModule_AddIntConstant(m, "NETLINK_IP6_FW", NETLINK_IP6_FW);
 	PyModule_AddIntConstant(m, "NETLINK_DNRTMSG", NETLINK_DNRTMSG);
+#ifdef NETLINK_TAPBASE
 	PyModule_AddIntConstant(m, "NETLINK_TAPBASE", NETLINK_TAPBASE);
 #endif
+#endif /* AF_NETLINK */
 #ifdef AF_ROUTE
 	/* Alias to emulate 4.4BSD */
 	PyModule_AddIntConstant(m, "AF_ROUTE", AF_ROUTE);
diff --git a/Modules/spwdmodule.c b/Modules/spwdmodule.c
index 7c618e7..b7bf20e 100644
--- a/Modules/spwdmodule.c
+++ b/Modules/spwdmodule.c
@@ -52,6 +52,7 @@
 	9,
 };
 
+static int initialized;
 static PyTypeObject StructSpwdType;
 
 
@@ -173,7 +174,10 @@
 	m=Py_InitModule3("spwd", spwd_methods, spwd__doc__);
 	if (m == NULL)
 		return;
-	PyStructSequence_InitType(&StructSpwdType, &struct_spwd_type_desc);
+	if (!initialized)
+		PyStructSequence_InitType(&StructSpwdType, 
+					  &struct_spwd_type_desc);
 	Py_INCREF((PyObject *) &StructSpwdType);
 	PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType);
+	initialized = 1;
 }
diff --git a/Modules/stropmodule.c b/Modules/stropmodule.c
index cffef3a..8b00fed 100644
--- a/Modules/stropmodule.c
+++ b/Modules/stropmodule.c
@@ -333,7 +333,7 @@
 {
 	char *s, *sub;
 	Py_ssize_t len, n, j;
-	Py_ssize_t i = 0, last = INT_MAX;
+	Py_ssize_t i = 0, last = PY_SSIZE_T_MAX;
 
 	WARN;
 	if (!PyArg_ParseTuple(args, "t#t#|nn:rfind", &s, &len, &sub, &n, &i, &last))
@@ -446,16 +446,16 @@
 {
 	char *s, *s_new;
 	Py_ssize_t i, n;
-	PyObject *new;
+	PyObject *newstr;
 	int changed;
 
 	WARN;
 	if (PyString_AsStringAndSize(args, &s, &n))
 		return NULL;
-	new = PyString_FromStringAndSize(NULL, n);
-	if (new == NULL)
+	newstr = PyString_FromStringAndSize(NULL, n);
+	if (newstr == NULL)
 		return NULL;
-	s_new = PyString_AsString(new);
+	s_new = PyString_AsString(newstr);
 	changed = 0;
 	for (i = 0; i < n; i++) {
 		int c = Py_CHARMASK(*s++);
@@ -467,11 +467,11 @@
 		s_new++;
 	}
 	if (!changed) {
-		Py_DECREF(new);
+		Py_DECREF(newstr);
 		Py_INCREF(args);
 		return args;
 	}
-	return new;
+	return newstr;
 }
 
 
@@ -485,16 +485,16 @@
 {
 	char *s, *s_new;
 	Py_ssize_t i, n;
-	PyObject *new;
+	PyObject *newstr;
 	int changed;
 
 	WARN;
 	if (PyString_AsStringAndSize(args, &s, &n))
 		return NULL;
-	new = PyString_FromStringAndSize(NULL, n);
-	if (new == NULL)
+	newstr = PyString_FromStringAndSize(NULL, n);
+	if (newstr == NULL)
 		return NULL;
-	s_new = PyString_AsString(new);
+	s_new = PyString_AsString(newstr);
 	changed = 0;
 	for (i = 0; i < n; i++) {
 		int c = Py_CHARMASK(*s++);
@@ -506,11 +506,11 @@
 		s_new++;
 	}
 	if (!changed) {
-		Py_DECREF(new);
+		Py_DECREF(newstr);
 		Py_INCREF(args);
 		return args;
 	}
-	return new;
+	return newstr;
 }
 
 
@@ -525,16 +525,16 @@
 {
 	char *s, *s_new;
 	Py_ssize_t i, n;
-	PyObject *new;
+	PyObject *newstr;
 	int changed;
 
 	WARN;
 	if (PyString_AsStringAndSize(args, &s, &n))
 		return NULL;
-	new = PyString_FromStringAndSize(NULL, n);
-	if (new == NULL)
+	newstr = PyString_FromStringAndSize(NULL, n);
+	if (newstr == NULL)
 		return NULL;
-	s_new = PyString_AsString(new);
+	s_new = PyString_AsString(newstr);
 	changed = 0;
 	if (0 < n) {
 		int c = Py_CHARMASK(*s++);
@@ -555,11 +555,11 @@
 		s_new++;
 	}
 	if (!changed) {
-		Py_DECREF(new);
+		Py_DECREF(newstr);
 		Py_INCREF(args);
 		return args;
 	}
-	return new;
+	return newstr;
 }
 
 
@@ -647,7 +647,7 @@
 {
 	char *s, *sub;
 	Py_ssize_t len, n;
-	Py_ssize_t i = 0, last = INT_MAX;
+	Py_ssize_t i = 0, last = PY_SSIZE_T_MAX;
 	Py_ssize_t m, r;
 
 	WARN;
@@ -691,16 +691,16 @@
 {
 	char *s, *s_new;
 	Py_ssize_t i, n;
-	PyObject *new;
+	PyObject *newstr;
 	int changed;
 
 	WARN;
 	if (PyString_AsStringAndSize(args, &s, &n))
 		return NULL;
-	new = PyString_FromStringAndSize(NULL, n);
-	if (new == NULL)
+	newstr = PyString_FromStringAndSize(NULL, n);
+	if (newstr == NULL)
 		return NULL;
-	s_new = PyString_AsString(new);
+	s_new = PyString_AsString(newstr);
 	changed = 0;
 	for (i = 0; i < n; i++) {
 		int c = Py_CHARMASK(*s++);
@@ -717,11 +717,11 @@
 		s_new++;
 	}
 	if (!changed) {
-		Py_DECREF(new);
+		Py_DECREF(newstr);
 		Py_INCREF(args);
 		return args;
 	}
-	return new;
+	return newstr;
 }
 
 
@@ -942,7 +942,7 @@
 	}
 
 	table = table1;
-	inlen = PyString_Size(input_obj);
+	inlen = PyString_GET_SIZE(input_obj);
 	result = PyString_FromStringAndSize((char *)NULL, inlen);
 	if (result == NULL)
 		return NULL;
@@ -1078,7 +1078,7 @@
 	/* find length of output string */
 	nfound = mymemcnt(str, len, pat, pat_len);
 	if (count < 0)
-		count = INT_MAX;
+		count = PY_SSIZE_T_MAX;
 	else if (nfound > count)
 		nfound = count;
 	if (nfound == 0)
@@ -1141,7 +1141,7 @@
 	char *str, *pat,*sub,*new_s;
 	Py_ssize_t len,pat_len,sub_len,out_len;
 	Py_ssize_t count = -1;
-	PyObject *new;
+	PyObject *newstr;
 
 	WARN;
 	if (!PyArg_ParseTuple(args, "t#t#t#|n:replace",
@@ -1165,14 +1165,14 @@
 	}
 	if (out_len == -1) {
 		/* we're returning another reference to the input string */
-		new = PyTuple_GetItem(args, 0);
-		Py_XINCREF(new);
+		newstr = PyTuple_GetItem(args, 0);
+		Py_XINCREF(newstr);
 	}
 	else {
-		new = PyString_FromStringAndSize(new_s, out_len);
+		newstr = PyString_FromStringAndSize(new_s, out_len);
 		PyMem_FREE(new_s);
 	}
-	return new;
+	return newstr;
 }
 
 
diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c
index 9a6c5d8..83313df 100644
--- a/Modules/threadmodule.c
+++ b/Modules/threadmodule.c
@@ -22,24 +22,6 @@
 	PyThread_type_lock lock_lock;
 } lockobject;
 
-static PyTypeObject Locktype;
-
-static lockobject *
-newlockobject(void)
-{
-	lockobject *self;
-	self = PyObject_New(lockobject, &Locktype);
-	if (self == NULL)
-		return NULL;
-	self->lock_lock = PyThread_allocate_lock();
-	if (self->lock_lock == NULL) {
-		PyObject_Del(self);
-		self = NULL;
-		PyErr_SetString(ThreadError, "can't allocate lock");
-	}
-	return self;
-}
-
 static void
 lock_dealloc(lockobject *self)
 {
@@ -166,6 +148,22 @@
 	0,				/*tp_repr*/
 };
 
+static lockobject *
+newlockobject(void)
+{
+	lockobject *self;
+	self = PyObject_New(lockobject, &Locktype);
+	if (self == NULL)
+		return NULL;
+	self->lock_lock = PyThread_allocate_lock();
+	if (self->lock_lock == NULL) {
+		PyObject_Del(self);
+		self = NULL;
+		PyErr_SetString(ThreadError, "can't allocate lock");
+	}
+	return self;
+}
+
 /* Thread-local objects */
 
 #include "structmember.h"
@@ -178,8 +176,6 @@
 	PyObject *dict;
 } localobject;
 
-static PyTypeObject localtype;
-
 static PyObject *
 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
 {
@@ -315,29 +311,6 @@
 	return ldict;
 }
 
-static PyObject *
-local_getattro(localobject *self, PyObject *name)
-{
-	PyObject *ldict, *value;
-
-	ldict = _ldict(self);
-	if (ldict == NULL) 
-		return NULL;
-
-	if (self->ob_type != &localtype)
-		/* use generic lookup for subtypes */
-		return PyObject_GenericGetAttr((PyObject *)self, name);
-
-	/* Optimization: just look in dict ourselves */
-	value = PyDict_GetItem(ldict, name);
-	if (value == NULL) 
-		/* Fall back on generic to get __class__ and __dict__ */
-		return PyObject_GenericGetAttr((PyObject *)self, name);
-
-	Py_INCREF(value);
-	return value;
-}
-
 static int
 local_setattro(localobject *self, PyObject *name, PyObject *v)
 {
@@ -368,6 +341,8 @@
 	{NULL}  /* Sentinel */
 };
 
+static PyObject *local_getattro(localobject *, PyObject *);
+
 static PyTypeObject localtype = {
 	PyObject_HEAD_INIT(NULL)
 	/* ob_size           */ 0,
@@ -375,17 +350,17 @@
 	/* tp_basicsize      */ sizeof(localobject),
 	/* tp_itemsize       */ 0,
 	/* tp_dealloc        */ (destructor)local_dealloc,
-	/* tp_print          */ (printfunc)0,
-	/* tp_getattr        */ (getattrfunc)0,
-	/* tp_setattr        */ (setattrfunc)0,
-	/* tp_compare        */ (cmpfunc)0,
-	/* tp_repr           */ (reprfunc)0,
+	/* tp_print          */ 0,
+	/* tp_getattr        */ 0,
+	/* tp_setattr        */ 0,
+	/* tp_compare        */ 0,
+	/* tp_repr           */ 0,
 	/* tp_as_number      */ 0,
 	/* tp_as_sequence    */ 0,
 	/* tp_as_mapping     */ 0,
-	/* tp_hash           */ (hashfunc)0,
-	/* tp_call           */ (ternaryfunc)0,
-	/* tp_str            */ (reprfunc)0,
+	/* tp_hash           */ 0,
+	/* tp_call           */ 0,
+	/* tp_str            */ 0,
 	/* tp_getattro       */ (getattrofunc)local_getattro,
 	/* tp_setattro       */ (setattrofunc)local_setattro,
 	/* tp_as_buffer      */ 0,
@@ -393,25 +368,47 @@
 	/* tp_doc            */ "Thread-local data",
 	/* tp_traverse       */ (traverseproc)local_traverse,
 	/* tp_clear          */ (inquiry)local_clear,
-	/* tp_richcompare    */ (richcmpfunc)0,
-	/* tp_weaklistoffset */ (long)0,
-	/* tp_iter           */ (getiterfunc)0,
-	/* tp_iternext       */ (iternextfunc)0,
+	/* tp_richcompare    */ 0,
+	/* tp_weaklistoffset */ 0,
+	/* tp_iter           */ 0,
+	/* tp_iternext       */ 0,
 	/* tp_methods        */ 0,
 	/* tp_members        */ 0,
 	/* tp_getset         */ local_getset,
 	/* tp_base           */ 0,
 	/* tp_dict           */ 0, /* internal use */
-	/* tp_descr_get      */ (descrgetfunc)0,
-	/* tp_descr_set      */ (descrsetfunc)0,
+	/* tp_descr_get      */ 0,
+	/* tp_descr_set      */ 0,
 	/* tp_dictoffset     */ offsetof(localobject, dict),
-	/* tp_init           */ (initproc)0,
-	/* tp_alloc          */ (allocfunc)0,
-	/* tp_new            */ (newfunc)local_new,
+	/* tp_init           */ 0,
+	/* tp_alloc          */ 0,
+	/* tp_new            */ local_new,
 	/* tp_free           */ 0, /* Low-level free-mem routine */
-	/* tp_is_gc          */ (inquiry)0, /* For PyObject_IS_GC */
+	/* tp_is_gc          */ 0, /* For PyObject_IS_GC */
 };
 
+static PyObject *
+local_getattro(localobject *self, PyObject *name)
+{
+	PyObject *ldict, *value;
+
+	ldict = _ldict(self);
+	if (ldict == NULL) 
+		return NULL;
+
+	if (self->ob_type != &localtype)
+		/* use generic lookup for subtypes */
+		return PyObject_GenericGetAttr((PyObject *)self, name);
+
+	/* Optimization: just look in dict ourselves */
+	value = PyDict_GetItem(ldict, name);
+	if (value == NULL) 
+		/* Fall back on generic to get __class__ and __dict__ */
+		return PyObject_GenericGetAttr((PyObject *)self, name);
+
+	Py_INCREF(value);
+	return value;
+}
 
 /* Module functions */
 
@@ -560,6 +557,8 @@
 }
 #endif
 
+static lockobject *newlockobject(void);
+
 static PyObject *
 thread_PyThread_allocate_lock(PyObject *self)
 {
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index ba93957..08d28a1 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -228,6 +228,7 @@
 	9,
 };
 
+static int initialized;
 static PyTypeObject StructTimeType;
 
 static PyObject *
@@ -443,7 +444,7 @@
 	 * will be ahead of time...
 	 */
 	for (i = 1024; ; i += i) {
-		outbuf = malloc(i);
+		outbuf = (char *)malloc(i);
 		if (outbuf == NULL) {
 			return PyErr_NoMemory();
 		}
@@ -807,9 +808,13 @@
 	hInterruptEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 	SetConsoleCtrlHandler( PyCtrlHandler, TRUE);
 #endif /* MS_WINDOWS */
-        PyStructSequence_InitType(&StructTimeType, &struct_time_type_desc);
+	if (!initialized) {
+		PyStructSequence_InitType(&StructTimeType, 
+					  &struct_time_type_desc);
+	}
 	Py_INCREF(&StructTimeType);
 	PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType);
+	initialized = 1;
 }
 
 
diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c
index 9eda653..297611c 100644
--- a/Modules/unicodedata.c
+++ b/Modules/unicodedata.c
@@ -446,7 +446,7 @@
     return PyString_FromString(decomp);
 }
 
-void
+static void
 get_decomp_record(PyObject *self, Py_UCS4 code, int *index, int *prefix, int *count)
 {
     if (code >= 0x110000) {
@@ -486,8 +486,8 @@
     Py_UNICODE *i, *end, *o;
     /* Longest decomposition in Unicode 3.2: U+FDFA */
     Py_UNICODE stack[20]; 
-    int space, stackptr, isize;
-    int index, prefix, count;
+    Py_ssize_t space, isize;
+    int index, prefix, count, stackptr;
     unsigned char prev, cur;
 	
     stackptr = 0;
@@ -508,7 +508,7 @@
             /* Hangul Decomposition adds three characters in
                a single step, so we need atleast that much room. */
             if (space < 3) {
-                int newsize = PyString_GET_SIZE(result) + 10;
+                Py_ssize_t newsize = PyString_GET_SIZE(result) + 10;
                 space += 10;
                 if (PyUnicode_Resize(&result, newsize) == -1)
                     return NULL;
@@ -759,7 +759,7 @@
     unsigned long h = 0;
     unsigned long ix;
     for (i = 0; i < len; i++) {
-        h = (h * scale) + (unsigned char) toupper(s[i]);
+        h = (h * scale) + (unsigned char) toupper(Py_CHARMASK(s[i]));
         ix = h & 0xff000000;
         if (ix)
             h = (h ^ ((ix>>24) & 0xff)) & 0x00ffffff;
@@ -906,7 +906,7 @@
     if (!_getucname(self, code, buffer, sizeof(buffer)))
         return 0;
     for (i = 0; i < namelen; i++) {
-        if (toupper(name[i]) != buffer[i])
+        if (toupper(Py_CHARMASK(name[i])) != buffer[i])
             return 0;
     }
     return buffer[namelen] == '\0';
diff --git a/Modules/xxsubtype.c b/Modules/xxsubtype.c
index ffbc72b..88ce6c5 100644
--- a/Modules/xxsubtype.c
+++ b/Modules/xxsubtype.c
@@ -79,8 +79,6 @@
 	{NULL,	NULL},
 };
 
-static PyTypeObject spamlist_type;
-
 static int
 spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
 {
@@ -179,8 +177,6 @@
 	{NULL,	NULL},
 };
 
-static PyTypeObject spamdict_type;
-
 static int
 spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
 {
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
index 637dc48..d59ebd8 100644
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -40,7 +40,6 @@
 	PyObject *files;    /* dict with file info {path: toc_entry} */
 };
 
-static PyTypeObject ZipImporter_Type;
 static PyObject *ZipImportError;
 static PyObject *zip_directory_cache = NULL;
 
@@ -171,13 +170,7 @@
 zipimporter_traverse(PyObject *obj, visitproc visit, void *arg)
 {
 	ZipImporter *self = (ZipImporter *)obj;
-	int err;
-
-	if (self->files != NULL) {
-		err = visit(self->files, arg);
-		if (err)
-			return err;
-	}
+	Py_VISIT(self->files);
 	return 0;
 }
 
@@ -958,7 +951,7 @@
 	PyObject *fixed_source;
 
 	/* one char extra for trailing \n and one for terminating \0 */
-	buf = PyMem_Malloc(PyString_Size(source) + 2);
+	buf = (char *)PyMem_Malloc(PyString_Size(source) + 2);
 	if (buf == NULL) {
 		PyErr_SetString(PyExc_MemoryError,
 				"zipimport: no memory to allocate "
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index 725755d..35b8c32 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -654,7 +654,9 @@
 }
 
 PyDoc_STRVAR(decomp_flush__doc__,
-"flush() -- Return a string containing any remaining decompressed data.\n"
+"flush( [length] ) -- Return a string containing any remaining\n"
+"decompressed data. length, if given, is the initial size of the\n"
+"output buffer.\n"
 "\n"
 "The decompressor object can no longer be used after this call.");