summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorThomas Wouters <thomas@python.org>2006-04-21 10:40:58 (GMT)
committerThomas Wouters <thomas@python.org>2006-04-21 10:40:58 (GMT)
commit49fd7fa4431da299196d74087df4a04f99f9c46f (patch)
tree35ace5fe78d3d52c7a9ab356ab9f6dbf8d4b71f4 /Modules
parent9ada3d6e29d5165dadacbe6be07bcd35cfbef59d (diff)
downloadcpython-49fd7fa4431da299196d74087df4a04f99f9c46f.zip
cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.gz
cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.bz2
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.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/Setup.dist4
-rw-r--r--Modules/_bsddb.c28
-rw-r--r--Modules/_csv.c63
-rw-r--r--Modules/_ctypes/_ctypes.c255
-rw-r--r--Modules/_ctypes/_ctypes_test.c72
-rw-r--r--Modules/_ctypes/callbacks.c52
-rw-r--r--Modules/_ctypes/callproc.c100
-rw-r--r--Modules/_ctypes/cfield.c155
-rw-r--r--Modules/_ctypes/ctypes.h39
-rwxr-xr-xModules/_ctypes/libffi/configure1
-rw-r--r--Modules/_ctypes/libffi/configure.ac1
-rw-r--r--Modules/_ctypes/libffi/src/powerpc/darwin_closure.S2
-rw-r--r--Modules/_ctypes/libffi/src/x86/ffi.c4
-rw-r--r--Modules/_ctypes/stgdict.c45
-rw-r--r--Modules/_hotshot.c8
-rw-r--r--Modules/_lsprof.c10
-rw-r--r--Modules/_sqlite/adapters.c40
-rw-r--r--Modules/_sqlite/adapters.h33
-rw-r--r--Modules/_sqlite/cache.c362
-rw-r--r--Modules/_sqlite/cache.h61
-rw-r--r--Modules/_sqlite/connection.c1082
-rw-r--r--Modules/_sqlite/connection.h106
-rw-r--r--Modules/_sqlite/converters.c40
-rw-r--r--Modules/_sqlite/converters.h33
-rw-r--r--Modules/_sqlite/cursor.c1027
-rw-r--r--Modules/_sqlite/cursor.h71
-rw-r--r--Modules/_sqlite/microprotocols.c142
-rw-r--r--Modules/_sqlite/microprotocols.h59
-rw-r--r--Modules/_sqlite/module.c325
-rw-r--r--Modules/_sqlite/module.h55
-rw-r--r--Modules/_sqlite/prepare_protocol.c84
-rw-r--r--Modules/_sqlite/prepare_protocol.h41
-rw-r--r--Modules/_sqlite/row.c202
-rw-r--r--Modules/_sqlite/row.h39
-rw-r--r--Modules/_sqlite/sqlitecompat.h34
-rw-r--r--Modules/_sqlite/statement.c427
-rw-r--r--Modules/_sqlite/statement.h58
-rw-r--r--Modules/_sqlite/util.c96
-rw-r--r--Modules/_sqlite/util.h38
-rw-r--r--Modules/_sre.c407
-rw-r--r--Modules/_ssl.c24
-rw-r--r--Modules/_testcapimodule.c114
-rw-r--r--Modules/_tkinter.c2
-rw-r--r--Modules/almodule.c4
-rw-r--r--Modules/arraymodule.c13
-rw-r--r--Modules/audioop.c2483
-rw-r--r--Modules/cPickle.c92
-rw-r--r--Modules/cStringIO.c26
-rw-r--r--Modules/ccpython.cc11
-rw-r--r--Modules/cjkcodecs/_codecs_cn.c5
-rw-r--r--Modules/cjkcodecs/multibytecodec.c1106
-rw-r--r--Modules/cjkcodecs/multibytecodec.h60
-rw-r--r--Modules/collectionsmodule.c21
-rw-r--r--Modules/config.c.in10
-rw-r--r--Modules/datetimemodule.c39
-rw-r--r--Modules/functionalmodule.c2
-rw-r--r--Modules/gcmodule.c75
-rw-r--r--Modules/getpath.c13
-rw-r--r--Modules/grpmodule.c5
-rw-r--r--Modules/itertoolsmodule.c91
-rw-r--r--Modules/main.c13
-rw-r--r--Modules/md5.c381
-rw-r--r--Modules/md5.h123
-rw-r--r--Modules/md5c.c289
-rw-r--r--Modules/md5module.c16
-rw-r--r--Modules/operator.c6
-rw-r--r--Modules/ossaudiodev.c16
-rw-r--r--Modules/parsermodule.c41
-rw-r--r--Modules/posixmodule.c424
-rw-r--r--Modules/pwdmodule.c6
-rw-r--r--Modules/pyexpat.c16
-rw-r--r--Modules/regexmodule.c690
-rw-r--r--Modules/regexpr.c2094
-rw-r--r--Modules/regexpr.h155
-rw-r--r--Modules/resource.c7
-rw-r--r--Modules/socketmodule.c76
-rw-r--r--Modules/spwdmodule.c6
-rw-r--r--Modules/stropmodule.c66
-rw-r--r--Modules/threadmodule.c121
-rw-r--r--Modules/timemodule.c9
-rw-r--r--Modules/unicodedata.c12
-rw-r--r--Modules/xxsubtype.c4
-rw-r--r--Modules/zipimport.c11
-rw-r--r--Modules/zlibmodule.c4
84 files changed, 8668 insertions, 5815 deletions
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 @@ GLHACK=-Dclear=__GLclear
# 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 PyMethodDef DB_methods[] = {
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 @@ DL_EXPORT(void) init_bsddb(void)
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 @@ DL_EXPORT(void) init_bsddb(void)
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 @@ module instead.
# 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 @@ Reader_dealloc(ReaderObj *self)
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 @@ Writer_dealloc(WriterObj *self)
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_reader_doc,
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 @@ bytes(cdata)
#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 @@ CDataType_from_param(PyObject *type, PyObject *value)
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 @@ CDataType_from_param(PyObject *type, PyObject *value)
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 @@ size property/method, and the sequence protocol.
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 @@ PointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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 @@ ArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject *typedict;
int length;
- int itemsize, itemalign, itemlen;
+ int itemsize, itemalign;
typedict = PyTuple_GetItem(args, 2);
if (!typedict)
@@ -936,7 +941,6 @@ ArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
itemsize = itemdict->size;
itemalign = itemdict->align;
- itemlen = itemdict->length;
stgdict->size = itemsize * length;
stgdict->align = itemalign;
@@ -945,7 +949,7 @@ ArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
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 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
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 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
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 @@ SimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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 @@ SimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject_SetAttrString(swapped, "__ctype_le__", (PyObject *)result);
PyObject_SetAttrString(swapped, "__ctype_be__", swapped);
#endif
+ Py_DECREF(swapped);
};
return (PyObject *)result;
@@ -1624,7 +1635,7 @@ make_funcptrtype_dict(StgDictObject *stgdict)
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 @@ CData_clear(CDataObject *self)
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 @@ static PyMemberDef CData_members[] = {
{ 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 @@ static Py_ssize_t CData_GetBuffer(CDataObject *self, Py_ssize_t seg, void **pptr
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 Py_ssize_t CData_GetSegcount(CDataObject *self, Py_ssize_t *lenp)
}
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 @@ PyTypeObject CData_Type = {
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 @@ static void CData_MallocBuffer(CDataObject *obj, StgDictObject *dict)
/* 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 @@ CData_AtAddress(PyObject *type, void *buf)
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 @@ static PPROC FindAddress(void *handle, char *name, PyObject *type)
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 @@ static PPROC FindAddress(void *handle, char *name, PyObject *type)
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 @@ _validate_paramflags(PyTypeObject *type, PyObject *paramflags)
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 @@ CFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
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 @@ CFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
#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 @@ CFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds)
"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 @@ CFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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)) {
+ if (1 <= PyTuple_GET_SIZE(args) && PyTuple_Check(PyTuple_GET_ITEM(args, 0)))
+ return CFuncPtr_FromDll(type, args, kwds);
+
#ifdef MS_WIN32
- if (PyInt_Check(PyTuple_GET_ITEM(args, 0)))
- return CFuncPtr_FromVtblIndex(type, args, kwds);
+ if (2 <= PyTuple_GET_SIZE(args) && PyInt_Check(PyTuple_GET_ITEM(args, 0)))
+ return CFuncPtr_FromVtblIndex(type, args, kwds);
#endif
- return CFuncPtr_FromDll(type, args, kwds);
- }
if (1 == PyTuple_GET_SIZE(args)
&& (PyInt_Check(PyTuple_GET_ITEM(args, 0))
@@ -2781,7 +2825,7 @@ _get_arg(int *pindex, char *name, PyObject *defval, PyObject *inargs, PyObject *
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 @@ _build_callargs(CFuncPtrObject *self, PyObject *argtypes,
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 @@ _build_callargs(CFuncPtrObject *self, PyObject *argtypes,
*/
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 @@ _build_result(PyObject *result, PyObject *callargs,
}
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 @@ CFuncPtr_call(CFuncPtrObject *self, PyObject *inargs, PyObject *kwds)
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 @@ CFuncPtr_clear(CFuncPtrObject *self)
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 @@ Struct_as_parameter(CDataObject *self)
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 @@ Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
if (!fields) {
PyErr_Clear();
fields = PyTuple_New(0);
+ if (!fields)
+ return -1;
}
if (PyTuple_GET_SIZE(args) > PySequence_Length(fields)) {
@@ -3445,8 +3501,9 @@ Array_init(CDataObject *self, PyObject *args, PyObject *kw)
}
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 @@ Array_item(CDataObject *self, int index)
}
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 @@ Array_slice(CDataObject *self, Py_ssize_t ilow, Py_ssize_t ihigh)
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 @@ Array_ass_item(CDataObject *self, int index, PyObject *value)
}
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 @@ Array_ass_slice(CDataObject *self, int ilow, int ihigh, PyObject *value)
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 @@ Array_ass_slice(CDataObject *self, int ilow, int ihigh, PyObject *value)
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 @@ static PyTypeObject Simple_Type = {
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 @@ Pointer_item(CDataObject *self, int index)
}
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 @@ Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
}
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 @@ Pointer_slice(CDataObject *self, Py_ssize_t ilow, Py_ssize_t ihigh)
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 @@ static PySequenceMethods Pointer_as_sequence = {
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 @@ string_at(const char *ptr, Py_ssize_t size)
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 @@ init_ctypes(void)
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 @@ EXPORT(void) _testfunc_v(int a, int b, int *presult)
*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(double) _testfunc_d_bhilfd(char b, short h, int i, long l, float f, doubl
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(void *) get_strchr(void)
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 @@ EXPORT(char *) my_strdup(char *src)
#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 @@ EXPORT(int) _testfunc_callback_with_pointer(int (*func)(int *))
}
#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 @@ EXPORT(int) _testfunc_ppp(char ***p)
{
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 @@ PyMethodDef module_methods[] = {
#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(float) tf_f(float c) { S; return c/3; }
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 @@ EXPORT(double) __stdcall s_tf_d(double c) { S; return c/3; }
#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 @@ if (x == NULL) _AddTraceback(what, __FILE__, __LINE__ - 1), PyErr_Print()
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 @@ static void closure_fcn(ffi_cif *cif,
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 @@ THUNK AllocFunctionCallback(PyObject *callable,
}
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 @@ THUNK AllocFunctionCallback(PyObject *callable,
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 @@ THUNK AllocFunctionCallback(PyObject *callable,
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 @@ static TCHAR *FormatError(DWORD code)
return lpMsgBuf;
}
+#ifndef DONT_USE_SEH
void SetException(DWORD code, EXCEPTION_RECORD *pr)
{
TCHAR *lpMsgBuf;
@@ -254,6 +258,7 @@ static DWORD HandleException(EXCEPTION_POINTERS *ptrs,
*record = *ptrs->ExceptionRecord;
return EXCEPTION_EXECUTE_HANDLER;
}
+#endif
static PyObject *
check_hresult(PyObject *self, PyObject *args)
@@ -576,14 +581,14 @@ ffi_type *GetType(PyObject *obj)
/* 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 @@ static int _call_function_pointer(int flags,
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 @@ static int _call_function_pointer(int flags,
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 @@ static int _call_function_pointer(int flags,
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 @@ void Extend_Error_Info(PyObject *exc_class, char *fmt, ...)
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 @@ void Extend_Error_Info(PyObject *exc_class, char *fmt, ...)
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 @@ static int
converter(PyObject *obj, void **address)
{
*address = PyLong_AsVoidPtr(obj);
- return address != NULL;
+ return *address != NULL;
}
static PyObject *
@@ -1423,71 +1437,7 @@ set_conversion_mode(PyObject *self, PyObject *args)
}
#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 @@ b_set(void *ptr, PyObject *value, unsigned size)
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 @@ b_set(void *ptr, PyObject *value, unsigned size)
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 @@ static PyObject *
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 @@ h_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ static PyObject *
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 @@ H_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ H_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ H_get(void *ptr, unsigned size)
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 @@ static PyObject *
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 @@ i_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ i_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ i_get(void *ptr, unsigned size)
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 @@ static PyObject *
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 @@ I_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ I_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ I_get(void *ptr, unsigned size)
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 @@ static PyObject *
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 @@ l_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ l_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ l_get(void *ptr, unsigned size)
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 @@ static PyObject *
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 @@ L_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ L_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ L_get(void *ptr, unsigned size)
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 @@ static PyObject *
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 @@ q_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ q_get(void *ptr, unsigned size)
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 @@ static PyObject *
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 @@ Q_set_sw(void *ptr, PyObject *value, unsigned size)
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 @@ Q_get(void *ptr, unsigned size)
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 @@ d_set(void *ptr, PyObject *value, unsigned size)
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 @@ f_set(void *ptr, PyObject *value, unsigned size)
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 @@ Z_set(void *ptr, PyObject *value, unsigned size)
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 @@ typedef int Py_ssize_t;
#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 @@ struct tagCDataObject {
};
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 @@ typedef struct {
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 @@ CreateArrayType(PyObject *itemtype, Py_ssize_t length);
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 @@ typedef struct {
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-*-solaris*) TARGET=X86; TARGETDIR=x86;;
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-*-solaris*) TARGET=X86; TARGETDIR=x86;;
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 @@ Lfinish:
/* 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 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
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 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
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 @@ static void
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 @@ StgDict_clone(StgDictObject *dst, StgDictObject *src)
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 @@ StgDict_clone(StgDictObject *dst, StgDictObject *src)
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 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
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 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
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 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
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 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
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 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
/* 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 @@ typedef __int64 hs_time;
#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 @@ unpack_string(LogReaderObject *self, PyObject **pvalue)
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 @@ calibrate(void)
#endif
}
#if defined(MS_WINDOWS) || defined(PYOS_OS2) || \
- defined(__VMS)
+ defined(__VMS) || defined (__QNX__)
rusage_diff = -1;
#else
{
@@ -1403,7 +1403,7 @@ get_version_string(void)
++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 @@ static PyStructSequence_Desc profiler_subentry_desc = {
5
};
+static int initialized;
static PyTypeObject StatsEntryType;
static PyTypeObject StatsSubEntryType;
@@ -857,8 +858,12 @@ init_lsprof(void)
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 @@ init_lsprof(void)
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_grow(SRE_STATE* state, int size)
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 @@ SRE_AT(SRE_STATE* state, SRE_CHAR* ptr, SRE_CODE at)
{
/* check if pointer is at given position */
- int this, that;
+ int thisp, thatp;
switch (at) {
@@ -362,57 +362,57 @@ SRE_AT(SRE_STATE* state, SRE_CHAR* ptr, SRE_CODE at)
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 @@ LOCAL(int)
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 @@ typedef struct {
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 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern)
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 @@ exit:
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 @@ SRE_SEARCH(SRE_STATE* state, SRE_CODE* pattern)
/* 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 @@ SRE_SEARCH(SRE_STATE* state, SRE_CODE* pattern)
/* 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 @@ SRE_SEARCH(SRE_STATE* state, SRE_CODE* pattern)
}
} 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 @@ SRE_LITERAL_TEMPLATE(SRE_CHAR* ptr, int len)
/* 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 @@ pattern_error(int status)
}
}
-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 @@ error:
}
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 @@ pattern_subx(PatternObject* self, PyObject* template, PyObject* string,
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 @@ pattern_subx(PatternObject* self, PyObject* template, PyObject* string,
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 @@ error:
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 @@ static PyTypeObject Pattern_Type = {
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 @@ match_getslice(MatchObject* self, PyObject* index, PyObject* def)
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 @@ static PyTypeObject Match_Type = {
(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 @@ static PyTypeObject Scanner_Type = {
(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 @@ typedef struct {
SSL_CTX* ctx;
SSL* ssl;
X509* server_cert;
- BIO* sbio;
char server[X509_NAME_MAXLEN];
char issuer[X509_NAME_MAXLEN];
@@ -474,15 +473,22 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
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 @@ raise_test_longlong_error(const char* msg)
#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 @@ getargs_l(PyObject *self, PyObject *args)
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 @@ test_k_code(PyObject *self)
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 @@ test_k_code(PyObject *self)
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 @@ test_u_code(PyObject *self)
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 @@ raise_exception(PyObject *self, PyObject *args)
#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 @@ void _make_call(void *callable)
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 @@ static PyMethodDef TestMethods[] = {
{"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 @@ init_testcapi(void)
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 @@ Tkapp_New(char *screenName, char *baseName, char *className,
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 @@ al_GetParams(PyObject *self, PyObject *args)
}
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 @@ al_GetParamInfo(PyObject *self, PyObject *args)
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 @@ u_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
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 @@ array_reverse(arrayobject *self, PyObject *unused)
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 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
}
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 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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 @@ arrayiter_dealloc(arrayiterobject *it)
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 @@ typedef unsigned long Py_UInt32;
#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 @@ typedef unsigned long Py_UInt32;
#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 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)
+{
+ int i;
+ 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])
+
+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
+};
+
+/*
+ * 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_linear_to_ulaw(int sample)
+st_14linear2ulaw(PyInt16 pcm_val) /* 2's complement (14-bit range) */
{
- 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;
-
- /* 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 */
-
- /* 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
+ 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
+};
- return ulawbyte;
+/*
+ * 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 *AudioopError;
static PyObject *
audioop_getsample(PyObject *self, PyObject *args)
{
- 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);
+ 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);
}
static PyObject *
audioop_max(PyObject *self, PyObject *args)
{
- 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);
+ 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);
}
static PyObject *
audioop_minmax(PyObject *self, PyObject *args)
{
- 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);
+ 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);
}
static PyObject *
audioop_avg(PyObject *self, PyObject *args)
{
- 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);
+ 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);
}
static PyObject *
audioop_rms(PyObject *self, PyObject *args)
{
- 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);
+ 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);
}
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 @@ static double _sum2(short *a, short *b, int len)
** 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 double _sum2(short *a, short *b, int len)
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;
-
- 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;
+ 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 ( 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;
-
- 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];
-
- 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;
-
- if ( result < best_result ) {
- best_result = result;
- best_j = j;
- }
-
- }
-
- factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
+ 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;
+
+ 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];
+
+ 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;
+
+ if ( result < best_result ) {
+ best_result = result;
+ best_j = j;
+ }
+
+ }
+
+ 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 @@ audioop_findfit(PyObject *self, PyObject *args)
static PyObject *
audioop_findfactor(PyObject *self, PyObject *args)
{
- 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);
-
- result = sum_aij_ri / sum_ri_2;
-
- return PyFloat_FromDouble(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);
+
+ result = sum_aij_ri / sum_ri_2;
+
+ return PyFloat_FromDouble(result);
}
/*
@@ -407,981 +554,1053 @@ audioop_findfactor(PyObject *self, PyObject *args)
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;
-
- 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;
+ 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 ( 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;
-
- 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;
+ 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;
- 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;
-
- 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);
+ 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;
+
+ 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;
-
- 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);
+ 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);
}
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;
-
- if ( !PyArg_Parse(args, "(s#id)", &cp, &len, &size, &factor ) )
- return 0;
+ 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 ( 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;
-
- if ( !PyArg_Parse(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
- return 0;
+ 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 ( 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;
-
- if ( !PyArg_Parse(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
- return 0;
+ 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 ( 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);
-
- 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;
-
- 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;
+ 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*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+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;
-
- 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;
- }
+ 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 ( 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;
- }
-
- 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);
-
- 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 ) 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);
+
+ 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;
+
+ 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;
-
- 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;
- }
+ 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 ( 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;
-
- 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;
- }
+ 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 ( 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;
-
- 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;
+ 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;
}
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;
-
- 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;
- }
+ 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 ( (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;
-
- 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;
+ 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;
}
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;
-
- 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;
- }
-
- 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;
- }
- }
-
- /* 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);
-
- 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;
- }
- }
+ 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;
+
+ 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 */
+
+ 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);
+
+ 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;
+ }
+ }
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;
-
- 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;
- }
+ 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);
+ 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_linear_to_ulaw(val);
- }
- return 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_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;
-
- 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;
- }
+ 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_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);
+ 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_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;
-
- if ( !PyArg_Parse(args, "(s#iO)",
- &cp, &len, &size, &state) )
- return 0;
+ 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 ( 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);
-
- /* 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;
-
- 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 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 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 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;
+ 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;
+
+ 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;
+
+ /* 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 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 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;
}
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;
-
- 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;
- }
+ 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 ( 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;
- }
-
- bufferstep = !bufferstep;
-
- /* 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 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;
-
- /* 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 - 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;
+ 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;
+
+ /* 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 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;
+
+ /* 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 - 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;
}
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 @@ static PyObject *__class___str, *__getinitargs___str, *__dict___str,
*__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 @@ Pickler_dealloc(Picklerobject *self)
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 @@ Unpickler_dealloc(Unpicklerobject *self)
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_stuff(PyObject *module_dict)
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 @@ static PyTypeObject Otype = {
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 @@ static PyTypeObject Itype = {
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 @@ ENCODER(gb18030)
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 @@ that encoding errors raise a UnicodeDecodeError. Other possible values\n\
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 @@ make_tuple(PyObject *object, Py_ssize_t len)
}
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 @@ get_errorcallback(const char *errors)
return ERROR_IGNORE;
else if (strcmp(errors, "replace") == 0)
return ERROR_REPLACE;
+ 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 {
- return PyCodec_LookupError(errors);
+ 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 @@ expand_decodebuffer(MultibyteDecodeBuffer *buf, Py_ssize_t esize)
{
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 @@ expand_decodebuffer(MultibyteDecodeBuffer *buf, Py_ssize_t esize)
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 @@ multibytecodec_encerror(MultibyteCodec *codec,
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 @@ multibytecodec_encerror(MultibyteCodec *codec,
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 @@ multibytecodec_encerror(MultibyteCodec *codec,
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 @@ multibytecodec_decerror(MultibyteCodec *codec,
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 @@ multibytecodec_decerror(MultibyteCodec *codec,
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 @@ multibytecodec_decerror(MultibyteCodec *codec,
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 @@ multibytecodec_decerror(MultibyteCodec *codec,
}
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 @@ multibytecodec_encode(MultibyteCodec *codec,
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 @@ MultibyteCodec_Encode(MultibyteCodecObject *self,
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 @@ MultibyteCodec_Encode(MultibyteCodecObject *self,
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 @@ MultibyteCodec_Decode(MultibyteCodecObject *self,
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 @@ MultibyteCodec_Decode(MultibyteCodecObject *self,
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 @@ static struct PyMethodDef multibytecodec_methods[] = {
{"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 @@ multibytecodec_dealloc(MultibyteCodecObject *self)
PyObject_Del(self);
}
-
-
static PyTypeObject MultibyteCodec_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
@@ -690,13 +702,498 @@ static PyTypeObject MultibyteCodec_Type = {
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 @@ mbstreamreader_iread(MultibyteStreamReaderObject *self,
}
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 @@ mbstreamreader_iread(MultibyteStreamReaderObject *self,
}
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 @@ mbstreamreader_reset(MultibyteStreamReaderObject *self)
return NULL;
self->pendingsize = 0;
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
static struct PyMethodDef mbstreamreader_methods[] = {
@@ -917,17 +1376,74 @@ static struct PyMethodDef mbstreamreader_methods[] = {
{NULL, NULL},
};
-static void
-mbstreamreader_dealloc(MultibyteStreamReaderObject *self)
+static PyMemberDef mbstreamreader_members[] = {
+ {"stream", T_OBJECT,
+ offsetof(MultibyteStreamReaderObject, stream),
+ READONLY, NULL},
+ {NULL,}
+};
+
+static PyObject *
+mbstreamreader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- if (self->errors > ERROR_MAX) {
- Py_DECREF(self->errors);
+ 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;
}
- Py_DECREF(self->stream);
- PyObject_Del(self);
+
+ 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)
+{
+ PyObject_GC_UnTrack(self);
+ ERROR_DECREF(self->errors);
+ Py_DECREF(self->stream);
+ self->ob_type->tp_free(self);
+}
static PyTypeObject MultibyteStreamReader_Type = {
PyObject_HEAD_INIT(NULL)
@@ -951,97 +1467,50 @@ static PyTypeObject MultibyteStreamReader_Type = {
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;
-
- 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;
- }
- }
+ PyObject *str, *wr;
- 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);
- }
+ str = encoder_encode_stateful(STATEFUL_ECTX(self), unistr, 0);
+ if (str == NULL)
+ return -1;
- 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 @@ mbstreamwriter_write(MultibyteStreamWriterObject *self, PyObject *args)
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 @@ mbstreamwriter_writelines(MultibyteStreamWriterObject *self, PyObject *args)
return NULL;
}
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
static PyObject *
@@ -1119,18 +1585,69 @@ mbstreamwriter_reset(MultibyteStreamWriterObject *self)
}
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 @@ static struct PyMethodDef mbstreamwriter_methods[] = {
{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 @@ static PyTypeObject MultibyteStreamWriter_Type = {
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 @@ __create_codec(PyObject *ignore, PyObject *arg)
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 @@ typedef struct {
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
+#define _MultibyteStatefulEncoder_HEAD \
+ _MultibyteStatefulCodec_HEAD \
+ Py_UNICODE pending[MAXENCPENDING]; \
+ Py_ssize_t pendingsize;
typedef struct {
- PyObject_HEAD
- MultibyteCodec *codec;
- MultibyteCodec_State state;
- Py_UNICODE pending[MAXENCPENDING];
+ _MultibyteStatefulEncoder_HEAD
+} MultibyteStatefulEncoderContext;
+
+#define MAXDECPENDING 8
+#define _MultibyteStatefulDecoder_HEAD \
+ _MultibyteStatefulCodec_HEAD \
+ unsigned char pending[MAXDECPENDING]; \
Py_ssize_t pendingsize;
- PyObject *stream, *errors;
+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 @@ typedef struct {
#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 @@ static PyTypeObject deque_type = {
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 @@ defdict_traverse(PyObject *self, visitproc visit, void *arg)
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 new value when a key is not present, in __getitem__ only.\n\
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 @@ static PyTypeObject defdict_type = {
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 @@ static PyTypeObject defdict_type = {
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 @@ initcollections(void)
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 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#include "Python.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* -- ADDMODULE MARKER 1 -- */
@@ -50,3 +54,9 @@ struct _inittab _PyImport_Inittab[] = {
/* 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 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
}
}
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 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
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 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
/* 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 @@ static PyObject *
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 @@ static PyObject *
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 @@ time_repr(PyDateTime_Time *self)
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 @@ datetime_strptime(PyObject *cls, PyObject *args)
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 @@ static PyObject *
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 @@ datetime_repr(PyDateTime_DateTime *self)
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 @@ datetime_repr(PyDateTime_DateTime *self)
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 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
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 @@ has_finalizer(PyObject *op)
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 @@ collect(int generation)
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 @@ collect(int generation)
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 @@ collect(int generation)
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 @@ collect(int generation)
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 @@ gc_get_count(PyObject *self, PyObject *noargs)
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 @@ gc_get_referrers(PyObject *self, PyObject *args)
{
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 @@ Return the list of objects that are directly referred to by objs.");
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 *
_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 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems)
{
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 @@ calculate_path(void)
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 @@ Py_GetProgramFullPath(void)
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 PyStructSequence_Desc struct_group_type_desc = {
};
+static int initialized;
static PyTypeObject StructGrpType;
static PyObject *
@@ -174,6 +175,8 @@ initgrp(void)
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_new(PyObject *it)
{
teedataobject *tdo;
- tdo = PyObject_New(teedataobject, &teedataobject_type);
+ tdo = PyObject_GC_New(teedataobject, &teedataobject_type);
if (tdo == NULL)
return NULL;
@@ -348,6 +348,7 @@ teedataobject_new(PyObject *it)
tdo->nextlink = NULL;
Py_INCREF(it);
tdo->it = it;
+ PyObject_GC_Track(tdo);
return (PyObject *)tdo;
}
@@ -381,16 +382,34 @@ teedataobject_getitem(teedataobject *tdo, int i)
return value;
}
-static void
-teedataobject_dealloc(teedataobject *tdo)
+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_DECREF(tdo->values[i]);
- Py_XDECREF(tdo->it);
- Py_XDECREF(tdo->nextlink);
- PyObject_Del(tdo);
+ Py_CLEAR(tdo->values[i]);
+ Py_CLEAR(tdo->nextlink);
+ return 0;
+}
+
+static void
+teedataobject_dealloc(teedataobject *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 @@ static PyTypeObject teedataobject_type = {
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 @@ tee_next(teeobject *to)
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 @@ tee_fromiterable(PyObject *iterable)
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 @@ tee_new(PyTypeObject *type, PyObject *args, PyObject *kw)
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 @@ static PyTypeObject tee_type = {
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 @@ static PyTypeObject tee_type = {
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 @@ Py_Main(int argc, char **argv)
/* -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 @@ Py_Main(int argc, char **argv)
/* -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 @@ Py_GetArgcArgv(int *argc, char ***argv)
*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.
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. 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.
-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.
+ 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:
-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.
+ 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.
-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.
+ L. Peter Deutsch
+ ghost@aladdin.com
-These notices must be retained in any copies of any part of this
-documentation and/or software.
*/
+/* $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):
-/* ========== include global.h ========== */
-/* GLOBAL.H - RSAREF types and constants
+ 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.
*/
-/* POINTER defines a generic pointer type */
-typedef unsigned char *POINTER;
-
-/* 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"
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * 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.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* 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;
+
+#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 @@ newmd5object(void)
if (md5p == NULL)
return NULL;
- MD5Init(&md5p->md5); /* actual initialisation */
+ md5_init(&md5p->md5); /* actual initialisation */
return md5p;
}
@@ -56,7 +56,7 @@ md5_update(md5object *self, PyObject *args)
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 @@ arguments.");
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 @@ including null bytes.");
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 @@ MD5_new(PyObject *self, PyObject *args)
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 @@ itemgetter_dealloc(itemgetterobject *ig)
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 @@ attrgetter_dealloc(attrgetterobject *ag)
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 @@ build_namelists (PyObject *module)
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 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
}
}
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 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
}
}
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 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
* 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 @@ build_node_children(PyObject *tuple, node *root, int *line_num)
}
Py_XDECREF(elem);
}
- return (root);
+ return root;
}
@@ -762,6 +764,7 @@ build_node_tree(PyObject *tuple)
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 @@ build_node_tree(PyObject *tuple)
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 @@ build_node_tree(PyObject *tuple)
}
}
}
- 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 @@ validate_gen_for(node *tree)
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 @@ validate_list_if(node *tree)
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 @@ validate_gen_if(node *tree)
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 @@ extern int lstat(const char *, struct stat *);
#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 @@ static PyStructSequence_Desc statvfs_result_desc = {
10
};
+static int initialized;
static PyTypeObject StatResultType;
static PyTypeObject StatVFSResultType;
static newfunc structseq_new;
@@ -1839,6 +1850,7 @@ posix_listdir(PyObject *self, PyObject *args)
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 @@ posix_listdir(PyObject *self, PyObject *args)
}
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 @@ posix_mkdir(PyObject *self, PyObject *args)
}
-#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 @@ posix_openpty(PyObject *self, PyObject *noargs)
#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 @@ posix_setgroups(PyObject *self, PyObject *args)
}
#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 @@ static PyObject *
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 @@ posix_waitpid(PyObject *self, PyObject *args)
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 @@ posix_waitpid(PyObject *self, PyObject *args)
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 @@ static PyObject *
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 @@ posix_fdopen(PyObject *self, PyObject *args)
"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 @@ static PyObject *
posix_putenv(PyObject *self, PyObject *args)
{
char *s1, *s2;
- char *new;
+ char *newenv;
PyObject *newstr;
size_t len;
@@ -5918,9 +6045,9 @@ posix_putenv(PyObject *self, PyObject *args)
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 @@ Return True if the process returning 'status' was dumped to a core file.");
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 @@ job control stop.");
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 @@ Return True if the process returning 'status' was stopped.");
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 @@ Return True if the process returning 'status' was terminated by a signal.");
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 @@ system call.");
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 @@ Return the process return code from 'status'.");
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 @@ value.");
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 @@ the 'status' value.");
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 @@ posix_tmpnam(PyObject *self, PyObject *noargs)
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 @@ posix_confstr(PyObject *self, PyObject *args)
{
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 @@ win32_startfile(PyObject *self, PyObject *args)
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 @@ static PyMethodDef posix_methods[] = {
#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 @@ INITFUNC(void)
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 @@ The uid and gid items are integers, all others are strings. An\n\
exception is raised if the entry asked for cannot be found.");
+static int initialized;
static PyTypeObject StructPwdType;
static void
@@ -186,9 +187,12 @@ initpwd(void)
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 @@ xmlparse_getattr(xmlparseobject *self, char *name)
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 @@ xmlparse_setattr(xmlparseobject *self, char *name, PyObject *v)
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 @@ static int
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 @@ static PyStructSequence_Desc struct_rusage_desc = {
16 /* n_in_sequence */
};
+static int initialized;
static PyTypeObject StructRUsageType;
static PyObject *
@@ -244,7 +245,10 @@ initresource(void)
}
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 @@ initresource(void)
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 @@ Local naming conventions:
*/
#include "Python.h"
+#include "structmember.h"
#undef MAX
#define MAX(x, y) ((x) < (y) ? (y) : (x))
@@ -967,7 +968,18 @@ makesockaddr(int sockfd, struct sockaddr *addr, int addrlen, int proto)
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 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
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 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args)
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 @@ static PyMethodDef sock_methods[] = {
{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 @@ static PyTypeObject sock_type = {
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 @@ socket_fromfd(PyObject *self, PyObject *args)
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 @@ init_socket(void)
/* */
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 @@ init_socket(void)
#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 @@ static PyStructSequence_Desc struct_spwd_type_desc = {
9,
};
+static int initialized;
static PyTypeObject StructSpwdType;
@@ -173,7 +174,10 @@ initspwd(void)
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 @@ strop_rfind(PyObject *self, PyObject *args)
{
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 @@ strop_lower(PyObject *self, PyObject *args)
{
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 @@ strop_lower(PyObject *self, PyObject *args)
s_new++;
}
if (!changed) {
- Py_DECREF(new);
+ Py_DECREF(newstr);
Py_INCREF(args);
return args;
}
- return new;
+ return newstr;
}
@@ -485,16 +485,16 @@ strop_upper(PyObject *self, PyObject *args)
{
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 @@ strop_upper(PyObject *self, PyObject *args)
s_new++;
}
if (!changed) {
- Py_DECREF(new);
+ Py_DECREF(newstr);
Py_INCREF(args);
return args;
}
- return new;
+ return newstr;
}
@@ -525,16 +525,16 @@ strop_capitalize(PyObject *self, PyObject *args)
{
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 @@ strop_capitalize(PyObject *self, PyObject *args)
s_new++;
}
if (!changed) {
- Py_DECREF(new);
+ Py_DECREF(newstr);
Py_INCREF(args);
return args;
}
- return new;
+ return newstr;
}
@@ -647,7 +647,7 @@ strop_count(PyObject *self, PyObject *args)
{
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 @@ strop_swapcase(PyObject *self, PyObject *args)
{
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 @@ strop_swapcase(PyObject *self, PyObject *args)
s_new++;
}
if (!changed) {
- Py_DECREF(new);
+ Py_DECREF(newstr);
Py_INCREF(args);
return args;
}
- return new;
+ return newstr;
}
@@ -942,7 +942,7 @@ strop_translate(PyObject *self, PyObject *args)
}
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 @@ mymemreplace(const char *str, Py_ssize_t len, /* input string */
/* 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 @@ strop_replace(PyObject *self, PyObject *args)
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 @@ strop_replace(PyObject *self, PyObject *args)
}
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 @@ typedef struct {
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 @@ static PyTypeObject Locktype = {
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 @@ typedef struct {
PyObject *dict;
} localobject;
-static PyTypeObject localtype;
-
static PyObject *
local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
@@ -315,29 +311,6 @@ _ldict(localobject *self)
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 @@ static PyGetSetDef local_getset[] = {
{NULL} /* Sentinel */
};
+static PyObject *local_getattro(localobject *, PyObject *);
+
static PyTypeObject localtype = {
PyObject_HEAD_INIT(NULL)
/* ob_size */ 0,
@@ -375,17 +350,17 @@ static PyTypeObject localtype = {
/* 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 @@ static PyTypeObject localtype = {
/* 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 @@ thread_PyThread_exit_prog(PyObject *self, PyObject *args)
}
#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 @@ static PyStructSequence_Desc struct_time_type_desc = {
9,
};
+static int initialized;
static PyTypeObject StructTimeType;
static PyObject *
@@ -443,7 +444,7 @@ time_strftime(PyObject *self, PyObject *args)
* 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 @@ inittime(void)
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 @@ unicodedata_decomposition(PyObject *self, PyObject *args)
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 @@ nfd_nfkd(PyObject *self, PyObject *input, int k)
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 @@ nfd_nfkd(PyObject *self, PyObject *input, int k)
/* 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 @@ _gethash(const char *s, int len, int scale)
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 @@ _cmpname(PyObject *self, int code, const char* name, int namelen)
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 @@ static PyMethodDef spamlist_methods[] = {
{NULL, NULL},
};
-static PyTypeObject spamlist_type;
-
static int
spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
{
@@ -179,8 +177,6 @@ static PyMethodDef spamdict_methods[] = {
{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 @@ struct _zipimporter {
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 @@ static int
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 @@ normalize_line_endings(PyObject *source)
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 @@ PyZlib_flush(compobject *self, PyObject *args)
}
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.");