diff -r 2914c826278e Modules/binascii.c --- a/Modules/binascii.c Thu Aug 16 10:19:01 2012 +0200 +++ b/Modules/binascii.c Thu Aug 16 10:26:38 2012 +0200 @@ -60,8 +60,41 @@ #include "zlib.h" #endif -static PyObject *Error; -static PyObject *Incomplete; +typedef struct { + PyObject *Error; + PyObject *Incomplete; +} binasciistate; + + +#define binascii_state(o) ((binasciistate *)PyModule_GetState(o)) + +static int +binascii_clear(PyObject *m) +{ + Py_CLEAR(binascii_state(m)->Error); + Py_CLEAR(binascii_state(m)->Incomplete); + return 0; +} + +static int +binascii_traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(binascii_state(m)->Error); + Py_VISIT(binascii_state(m)->Incomplete); + return 0; +} + +static void +binascii_free(void *m) +{ + binascii_clear((PyObject *)m); +} + +static PyModuleDef binasciimodule; + +#define binasciistate_global ((binasciistate *)PyModule_GetState(PyState_FindModule(&binasciimodule))) + + /* ** hqx lookup table, ascii->binary. @@ -268,7 +301,7 @@ ** '`' as zero instead of space. */ if ( this_ch < ' ' || this_ch > (' ' + 64)) { - PyErr_SetString(Error, "Illegal char"); + PyErr_SetString(binasciistate_global->Error, "Illegal char"); PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; @@ -297,7 +330,7 @@ /* Extra '`' may be written as padding in some cases */ if ( this_ch != ' ' && this_ch != ' '+64 && this_ch != '\n' && this_ch != '\r' ) { - PyErr_SetString(Error, "Trailing garbage"); + PyErr_SetString(binasciistate_global->Error, "Trailing garbage"); PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; @@ -326,7 +359,7 @@ bin_len = pbin.len; if ( bin_len > 45 ) { /* The 45 is a limit that appears in all uuencode's */ - PyErr_SetString(Error, "At most 45 bytes at once"); + PyErr_SetString(binasciistate_global->Error, "At most 45 bytes at once"); PyBuffer_Release(&pbin); return NULL; } @@ -480,7 +513,7 @@ if (leftbits != 0) { PyBuffer_Release(&pascii); - PyErr_SetString(Error, "Incorrect padding"); + PyErr_SetString(binasciistate_global->Error, "Incorrect padding"); Py_DECREF(rv); return NULL; } @@ -524,7 +557,7 @@ assert(bin_len >= 0); if ( bin_len > BASE64_MAXBIN ) { - PyErr_SetString(Error, "Too much data for base64 line"); + PyErr_SetString(binasciistate_global->Error, "Too much data for base64 line"); PyBuffer_Release(&pbuf); return NULL; } @@ -611,7 +644,7 @@ if ( this_ch == SKIP ) continue; if ( this_ch == FAIL ) { - PyErr_SetString(Error, "Illegal char"); + PyErr_SetString(binasciistate_global->Error, "Illegal char"); PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; @@ -633,7 +666,7 @@ } if ( leftbits && !done ) { - PyErr_SetString(Incomplete, + PyErr_SetString(binasciistate_global->Incomplete, "String has incomplete number of bytes"); PyBuffer_Release(&pascii); Py_DECREF(rv); @@ -821,7 +854,7 @@ #define INBYTE(b) \ do { \ if ( --in_len < 0 ) { \ - PyErr_SetString(Incomplete, ""); \ + PyErr_SetString(binasciistate_global->Incomplete, ""); \ Py_DECREF(rv); \ PyBuffer_Release(&pin); \ return NULL; \ @@ -855,7 +888,7 @@ /* Note Error, not Incomplete (which is at the end ** of the string only). This is a programmer error. */ - PyErr_SetString(Error, "Orphaned RLE code at start"); + PyErr_SetString(binasciistate_global->Error, "Orphaned RLE code at start"); PyBuffer_Release(&pin); Py_DECREF(rv); return NULL; @@ -1170,7 +1203,7 @@ */ if (arglen % 2) { PyBuffer_Release(&parg); - PyErr_SetString(Error, "Odd-length string"); + PyErr_SetString(binasciistate_global->Error, "Odd-length string"); return NULL; } @@ -1185,7 +1218,7 @@ int top = to_int(Py_CHARMASK(argbuf[i])); int bot = to_int(Py_CHARMASK(argbuf[i+1])); if (top == -1 || bot == -1) { - PyErr_SetString(Error, + PyErr_SetString(binasciistate_global->Error, "Non-hexadecimal digit found"); goto finally; } @@ -1546,12 +1579,12 @@ PyModuleDef_HEAD_INIT, "binascii", doc_binascii, - -1, + sizeof(binasciistate), binascii_module_methods, NULL, - NULL, - NULL, - NULL + binascii_traverse, + binascii_clear, + binascii_free }; PyMODINIT_FUNC @@ -1566,10 +1599,10 @@ d = PyModule_GetDict(m); - Error = PyErr_NewException("binascii.Error", PyExc_ValueError, NULL); - PyDict_SetItemString(d, "Error", Error); - Incomplete = PyErr_NewException("binascii.Incomplete", NULL, NULL); - PyDict_SetItemString(d, "Incomplete", Incomplete); + binascii_state(m)->Error = PyErr_NewException("binascii.Error", PyExc_ValueError, NULL); + PyDict_SetItemString(d, "Error", binascii_state(m)->Error); + binascii_state(m)->Incomplete = PyErr_NewException("binascii.Incomplete", NULL, NULL); + PyDict_SetItemString(d, "Incomplete", binascii_state(m)->Incomplete); if (PyErr_Occurred()) { Py_DECREF(m); m = NULL;