diff -r 5b5ef012cd4e Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py Thu Aug 22 17:53:06 2013 +0300 +++ b/Lib/test/test_tcl.py Thu Aug 22 22:17:26 2013 +0300 @@ -163,7 +163,8 @@ self.assertEqual(passValue(False), False) self.assertEqual(passValue('string'), 'string') self.assertEqual(passValue('string\u20ac'), 'string\u20ac') - for i in (0, 1, -1, 2**31-1, -2**31): + for i in (0, 1, -1, 2**31-1, -2**31, 2**31, -2**31-1, + 2**63-1, -2**63, 2**63, -2**63-1, 2**1000, -2**1000): self.assertEqual(passValue(i), i) for f in (0.0, 1.0, -1.0, 1/3, sys.float_info.min, sys.float_info.max, diff -r 5b5ef012cd4e Modules/_tkinter.c --- a/Modules/_tkinter.c Thu Aug 22 17:53:06 2013 +0300 +++ b/Modules/_tkinter.c Thu Aug 22 22:17:26 2013 +0300 @@ -69,6 +69,7 @@ #include #include #endif +#include #include "tkinter.h" @@ -260,6 +261,8 @@ Tcl_ObjType *ByteArrayType; Tcl_ObjType *DoubleType; Tcl_ObjType *IntType; + Tcl_ObjType *WideIntType; + Tcl_ObjType *BignumType; Tcl_ObjType *ListType; Tcl_ObjType *ProcBodyType; Tcl_ObjType *StringType; @@ -548,6 +551,8 @@ v->ByteArrayType = Tcl_GetObjType("bytearray"); v->DoubleType = Tcl_GetObjType("double"); v->IntType = Tcl_GetObjType("int"); + v->WideIntType = Tcl_GetObjType("wideInt"); + v->BignumType = Tcl_GetObjType("bignum"); v->ListType = Tcl_GetObjType("list"); v->ProcBodyType = Tcl_GetObjType("procbody"); v->StringType = Tcl_GetObjType("string"); @@ -835,24 +840,71 @@ AsObj(PyObject *value) { Tcl_Obj *result; - long longVal; - int overflow; if (PyBytes_Check(value)) return Tcl_NewStringObj(PyBytes_AS_STRING(value), PyBytes_GET_SIZE(value)); - else if (PyBool_Check(value)) + if (PyBool_Check(value)) return Tcl_NewBooleanObj(PyObject_IsTrue(value)); - else if (PyLong_CheckExact(value) && - ((longVal = PyLong_AsLongAndOverflow(value, &overflow)), - !overflow)) { - /* If there is an overflow in the long conversion, - fall through to default object handling. */ - return Tcl_NewLongObj(longVal); + + if (PyLong_CheckExact(value)) { + int overflow; + long longValue; +#ifdef HAVE_LONG_LONG + PY_LONG_LONG wideValue; +#endif + int neg; + PyObject *hexstr; + char *hexchars; + mp_int bigValue; + + longValue = PyLong_AsLongAndOverflow(value, &overflow); + if (!overflow) { + /* If there is an overflow in the long conversion, + fall through to wideInt handling. */ + return Tcl_NewLongObj(longValue); + } + +#ifdef HAVE_LONG_LONG + wideValue = PyLong_AsLongLongAndOverflow(value, &overflow); + if (!overflow) { + /* If there is an overflow in the wideInt conversion, + fall through to bignum handling. */ + return Tcl_NewWideIntObj(wideValue); + } +#endif + + neg = Py_SIZE(value) < 0; + hexstr = _PyLong_Format(value, 16); + if (hexstr == NULL) + return NULL; + hexchars = PyUnicode_AsUTF8(hexstr); + if (hexchars == NULL) { + Py_DECREF(hexstr); + return NULL; + } + hexchars += neg + 2; /* skip sign and "0x" */ + mp_init(&bigValue); + if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) { + mp_clear(&bigValue); + Py_DECREF(hexstr); + PyErr_NoMemory(); + return NULL; + } + Py_DECREF(hexstr); + bigValue.sign = neg ? MP_NEG : MP_ZPOS; + result = Tcl_NewBignumObj(&bigValue); + mp_clear(&bigValue); + if (result == NULL) { + PyErr_NoMemory(); + return NULL; + } + return result; } - else if (PyFloat_Check(value)) + + if (PyFloat_Check(value)) return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); - else if (PyTuple_Check(value)) { + if (PyTuple_Check(value)) { Tcl_Obj **argv; Py_ssize_t size, i; @@ -870,7 +922,7 @@ ckfree(FREECAST argv); return result; } - else if (PyUnicode_Check(value)) { + if (PyUnicode_Check(value)) { void *inbuf; Py_ssize_t size; int kind; @@ -916,12 +968,12 @@ ckfree(FREECAST outbuf); return result; } - else if(PyTclObject_Check(value)) { + if(PyTclObject_Check(value)) { Tcl_Obj *v = ((PyTclObject*)value)->value; Tcl_IncrRefCount(v); return v; } - else { + { PyObject *v = PyObject_Str(value); if (!v) return 0; @@ -936,6 +988,7 @@ { PyObject *result = NULL; TkappObject *app = (TkappObject*)tkapp; + Tcl_Interp *interp = Tkapp_Interp(tkapp); if (value->typePtr == NULL) { return PyUnicode_FromStringAndSize(value->bytes, @@ -959,7 +1012,62 @@ } if (value->typePtr == app->IntType) { - return PyLong_FromLong(value->internalRep.longValue); + long longValue; + if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK) + return PyLong_FromLong(longValue); + /* If there is an error in the long conversion, + fall through to wideInt handling. */ + } + +#ifdef HAVE_LONG_LONG + if (value->typePtr == app->IntType || + value->typePtr == app->WideIntType) { + Tcl_WideInt wideValue; + if (Tcl_GetWideIntFromObj(interp, value, &wideValue) == TCL_OK) + return PyLong_FromLongLong(wideValue); + /* If there is an error in the wideInt conversion, + fall through to bignum handling. */ + } +#endif + + if (value->typePtr == app->IntType || + value->typePtr == app->WideIntType || + value->typePtr == app->BignumType || + (app->BignumType == NULL && + strcmp(value->typePtr->name, "bignum") == 0)) { + mp_int bigValue; + /* bignum type is not registered in Tcl */ + if (app->BignumType == NULL && + strcmp(value->typePtr->name, "bignum") == 0) { + app->BignumType = value->typePtr; + } + if (Tcl_GetBignumFromObj(interp, value, &bigValue) == TCL_OK) { + unsigned long numBytes = mp_unsigned_bin_size(&bigValue); + unsigned char *bytes = PyMem_Malloc(numBytes); + PyObject *res; + if (bytes == NULL) { + mp_clear(&bigValue); + return NULL; + } + if (mp_to_unsigned_bin_n(&bigValue, bytes, + &numBytes) != MP_OKAY) { + mp_clear(&bigValue); + PyMem_Free(bytes); + return PyErr_NoMemory(); + } + res = _PyLong_FromByteArray(bytes, numBytes, + /* big-endian */ 0, + /* unsigned */ 0); + PyMem_Free(bytes); + if (res != NULL && bigValue.sign == MP_NEG) { + PyObject *res2 = PyNumber_Negative(res); + Py_DECREF(res); + res = res2; + } + mp_clear(&bigValue); + return res; + } + return Tkinter_Error(tkapp); } if (value->typePtr == app->ListType) { @@ -968,15 +1076,14 @@ PyObject *elem; Tcl_Obj *tcl_elem; - status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size); + status = Tcl_ListObjLength(interp, value, &size); if (status == TCL_ERROR) return Tkinter_Error(tkapp); result = PyTuple_New(size); if (!result) return NULL; for (i = 0; i < size; i++) { - status = Tcl_ListObjIndex(Tkapp_Interp(tkapp), - value, i, &tcl_elem); + status = Tcl_ListObjIndex(interp, value, i, &tcl_elem); if (status == TCL_ERROR) { Py_DECREF(result); return Tkinter_Error(tkapp);