diff options
Diffstat (limited to 'Modules/_tkinter.c')
-rw-r--r-- | Modules/_tkinter.c | 202 |
1 files changed, 95 insertions, 107 deletions
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 52025bb..4d61bb2 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -9,8 +9,8 @@ Copyright (C) 1994 Steen Lumholt. /* TCL/TK VERSION INFO: - Only Tcl/Tk 8.3.1 and later are supported. Older versions are not - supported. Use Python 2.6 or older if you cannot upgrade your + Only Tcl/Tk 8.4 and later are supported. Older versions are not + supported. Use Python 3.4 or older if you cannot upgrade your Tcl/Tk libraries. */ @@ -21,6 +21,7 @@ Copyright (C) 1994 Steen Lumholt. */ +#define PY_SSIZE_T_CLEAN #include "Python.h" #include <ctype.h> @@ -36,13 +37,6 @@ Copyright (C) 1994 Steen Lumholt. #define CHECK_SIZE(size, elemsize) \ ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize))) -/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately, - making _tkinter correct for this API means to break earlier - versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and - earlier versions. Once Tcl releases before 8.4 don't need to be supported - anymore, this should go. */ -#define USE_COMPAT_CONST - /* If Tcl is compiled for threads, we must also define TCL_THREAD. We define it always; if Tcl is not threaded, the thread functions in Tcl are empty. */ @@ -58,15 +52,8 @@ Copyright (C) 1994 Steen Lumholt. #include "tkinter.h" -/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */ -#ifndef CONST84_RETURN -#define CONST84_RETURN -#undef CONST -#define CONST -#endif - -#if TK_HEX_VERSION < 0x08030201 -#error "Tk older than 8.3.1 not supported" +#if TK_HEX_VERSION < 0x08040200 +#error "Tk older than 8.4 not supported" #endif #if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \ @@ -385,10 +372,10 @@ unicodeFromTclObj(Tcl_Obj *value) static PyObject * -Split(char *list) +Split(const char *list) { int argc; - char **argv; + const char **argv; PyObject *v; if (list == NULL) { @@ -432,7 +419,7 @@ static PyObject * SplitObj(PyObject *arg) { if (PyTuple_Check(arg)) { - int i, size; + Py_ssize_t i, size; PyObject *elem, *newelem, *result; size = PyTuple_Size(arg); @@ -448,7 +435,7 @@ SplitObj(PyObject *arg) return NULL; } if (!result) { - int k; + Py_ssize_t k; if (newelem == elem) { Py_DECREF(newelem); continue; @@ -468,9 +455,29 @@ SplitObj(PyObject *arg) return result; /* Fall through, returning arg. */ } + else if (PyList_Check(arg)) { + Py_ssize_t i, size; + PyObject *elem, *newelem, *result; + + size = PyList_GET_SIZE(arg); + result = PyTuple_New(size); + if (!result) + return NULL; + /* Recursively invoke SplitObj for all list items. */ + for(i = 0; i < size; i++) { + elem = PyList_GET_ITEM(arg, i); + newelem = SplitObj(elem); + if (!newelem) { + Py_XDECREF(result); + return NULL; + } + PyTuple_SetItem(result, i, newelem); + } + return result; + } else if (PyUnicode_Check(arg)) { int argc; - char **argv; + const char **argv; char *list = PyUnicode_AsUTF8(arg); if (list == NULL || @@ -485,7 +492,7 @@ SplitObj(PyObject *arg) } else if (PyBytes_Check(arg)) { int argc; - char **argv; + const char **argv; char *list = PyBytes_AsString(arg); if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { @@ -552,8 +559,9 @@ static void EnableEventHook(void); /* Forward */ static void DisableEventHook(void); /* Forward */ static TkappObject * -Tkapp_New(char *screenName, char *className, - int interactive, int wantobjects, int wantTk, int sync, char *use) +Tkapp_New(const char *screenName, const char *className, + int interactive, int wantobjects, int wantTk, int sync, + const char *use) { TkappObject *v; char *argv0; @@ -610,7 +618,7 @@ Tkapp_New(char *screenName, char *className, Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY); /* This is used to get the application class for Tk 4.1 and up */ - argv0 = (char*)attemptckalloc(strlen(className) + 1); + argv0 = (char*)PyMem_Malloc(strlen(className) + 1); if (!argv0) { PyErr_NoMemory(); Py_DECREF(v); @@ -621,7 +629,7 @@ Tkapp_New(char *screenName, char *className, if (Py_ISUPPER(Py_CHARMASK(argv0[0]))) argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0])); Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY); - ckfree(argv0); + PyMem_Free(argv0); if (! wantTk) { Tcl_SetVar(v->interp, @@ -637,14 +645,14 @@ Tkapp_New(char *screenName, char *className, /* some initial arguments need to be in argv */ if (sync || use) { char *args; - int len = 0; + Py_ssize_t len = 0; if (sync) len += sizeof "-sync"; if (use) - len += strlen(use) + sizeof "-use "; + len += strlen(use) + sizeof "-use "; /* never overflows */ - args = (char*)attemptckalloc(len); + args = (char*)PyMem_Malloc(len); if (!args) { PyErr_NoMemory(); Py_DECREF(v); @@ -662,7 +670,7 @@ Tkapp_New(char *screenName, char *className, } Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY); - ckfree(args); + PyMem_Free(args); } if (Tcl_AppInit(v->interp) != TCL_OK) { @@ -929,9 +937,14 @@ AsObj(PyObject *value) { Tcl_Obj *result; - if (PyBytes_Check(value)) + if (PyBytes_Check(value)) { + if (PyBytes_GET_SIZE(value) >= INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "bytes object is too long"); + return NULL; + } return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value), - PyBytes_GET_SIZE(value)); + (int)PyBytes_GET_SIZE(value)); + } if (PyBool_Check(value)) return Tcl_NewBooleanObj(PyObject_IsTrue(value)); @@ -970,24 +983,28 @@ AsObj(PyObject *value) if (PyFloat_Check(value)) return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); - if (PyTuple_Check(value)) { + if (PyTuple_Check(value) || PyList_Check(value)) { Tcl_Obj **argv; Py_ssize_t size, i; - size = PyTuple_Size(value); + size = PySequence_Fast_GET_SIZE(value); if (size == 0) return Tcl_NewListObj(0, NULL); if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) { - PyErr_SetString(PyExc_OverflowError, "tuple is too long"); + PyErr_SetString(PyExc_OverflowError, + PyTuple_Check(value) ? "tuple is too long" : + "list is too long"); return NULL; } - argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *)); - if(!argv) - return 0; + argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *)); + if (!argv) { + PyErr_NoMemory(); + return NULL; + } for (i = 0; i < size; i++) - argv[i] = AsObj(PyTuple_GetItem(value,i)); - result = Tcl_NewListObj(PyTuple_Size(value), argv); - ckfree(FREECAST argv); + argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i)); + result = Tcl_NewListObj((int)size, argv); + PyMem_Free(argv); return result; } @@ -1012,9 +1029,9 @@ AsObj(PyObject *value) } kind = PyUnicode_KIND(value); if (kind == sizeof(Tcl_UniChar)) - return Tcl_NewUnicodeObj(inbuf, size); + return Tcl_NewUnicodeObj(inbuf, (int)size); allocsize = ((size_t)size) * sizeof(Tcl_UniChar); - outbuf = (Tcl_UniChar*)attemptckalloc(allocsize); + outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize); /* Else overflow occurred, and we take the next exit */ if (!outbuf) { PyErr_NoMemory(); @@ -1031,14 +1048,14 @@ AsObj(PyObject *value) "character U+%x is above the range " "(U+0000-U+FFFF) allowed by Tcl", ch); - ckfree(FREECAST outbuf); + PyMem_Free(outbuf); return NULL; } #endif outbuf[i] = ch; } - result = Tcl_NewUnicodeObj(outbuf, size); - ckfree(FREECAST outbuf); + result = Tcl_NewUnicodeObj(outbuf, (int)size); + PyMem_Free(outbuf); return result; } @@ -1067,7 +1084,6 @@ fromBoolean(PyObject* tkapp, Tcl_Obj *value) return PyBool_FromLong(boolValue); } -#ifdef TCL_WIDE_INT_TYPE static PyObject* fromWideIntObj(PyObject* tkapp, Tcl_Obj *value) { @@ -1084,7 +1100,6 @@ fromWideIntObj(PyObject* tkapp, Tcl_Obj *value) } return NULL; } -#endif #ifdef HAVE_LIBTOMMAMTH static PyObject* @@ -1157,7 +1172,6 @@ FromObj(PyObject* tkapp, Tcl_Obj *value) fall through to wideInt handling. */ } -#ifdef TCL_WIDE_INT_TYPE if (value->typePtr == app->IntType || value->typePtr == app->WideIntType) { result = fromWideIntObj(tkapp, value); @@ -1167,7 +1181,6 @@ FromObj(PyObject* tkapp, Tcl_Obj *value) /* If there is an error in the wideInt conversion, fall through to bignum handling. */ } -#endif #ifdef HAVE_LIBTOMMAMTH if (value->typePtr == app->IntType || @@ -1258,7 +1271,7 @@ Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc) for (i = 0; i < objc; i++) Tcl_DecrRefCount(objv[i]); if (objv != objStore) - ckfree(FREECAST objv); + PyMem_Free(objv); } /* Convert Python objects to Tcl objects. This must happen in the @@ -1272,7 +1285,7 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) if (args == NULL) /* do nothing */; - else if (!PyTuple_Check(args)) { + else if (!(PyTuple_Check(args) || PyList_Check(args))) { objv[0] = AsObj(args); if (objv[0] == 0) goto finally; @@ -1280,14 +1293,16 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) Tcl_IncrRefCount(objv[0]); } else { - objc = PyTuple_Size(args); + objc = PySequence_Fast_GET_SIZE(args); if (objc > ARGSZ) { if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) { - PyErr_SetString(PyExc_OverflowError, "tuple is too long"); + PyErr_SetString(PyExc_OverflowError, + PyTuple_Check(args) ? "tuple is too long" : + "list is too long"); return NULL; } - objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *)); + objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *)); if (objv == NULL) { PyErr_NoMemory(); objc = 0; @@ -1296,7 +1311,7 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) } for (i = 0; i < objc; i++) { - PyObject *v = PyTuple_GetItem(args, i); + PyObject *v = PySequence_Fast_GET_ITEM(args, i); if (v == Py_None) { objc = i; break; @@ -1311,10 +1326,10 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) Tcl_IncrRefCount(objv[i]); } } - *pobjc = objc; + *pobjc = (int)objc; return objv; finally: - Tkapp_CallDeallocArgs(objv, objStore, objc); + Tkapp_CallDeallocArgs(objv, objStore, (int)objc); return NULL; } @@ -1596,8 +1611,8 @@ varname_converter(PyObject *in, void *_out) return 0; } s = PyBytes_AsString(in); - if (strlen(s) != PyBytes_Size(in)) { - PyErr_SetString(PyExc_ValueError, "null byte in bytes object"); + if (strlen(s) != (size_t)PyBytes_Size(in)) { + PyErr_SetString(PyExc_ValueError, "embedded null byte"); return 0; } *out = s; @@ -1613,8 +1628,8 @@ varname_converter(PyObject *in, void *_out) PyErr_SetString(PyExc_OverflowError, "string is too long"); return 0; } - if (strlen(s) != size) { - PyErr_SetString(PyExc_ValueError, "null character in string"); + if (strlen(s) != (size_t)size) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); return 0; } *out = s; @@ -1667,7 +1682,6 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) #ifdef WITH_THREAD TkappObject *self = (TkappObject*)selfptr; if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) { - TkappObject *self = (TkappObject*)selfptr; VarEvent *ev; PyObject *res, *exc_type, *exc_val; Tcl_Condition cond = NULL; @@ -1866,12 +1880,8 @@ static PyObject * Tkapp_GetInt(PyObject *self, PyObject *args) { char *s; -#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH) Tcl_Obj *value; PyObject *result; -#else - int intValue; -#endif if (PyTuple_Size(args) == 1) { PyObject* o = PyTuple_GetItem(args, 0); @@ -1883,7 +1893,6 @@ Tkapp_GetInt(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s:getint", &s)) return NULL; CHECK_STRING_LENGTH(s); -#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH) value = Tcl_NewStringObj(s, -1); if (value == NULL) return Tkinter_Error(self); @@ -1901,10 +1910,6 @@ Tkapp_GetInt(PyObject *self, PyObject *args) Tcl_DecrRefCount(value); if (result != NULL || PyErr_Occurred()) return result; -#else - if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK) - return PyLong_FromLong(intValue); -#endif return Tkinter_Error(self); } @@ -2059,7 +2064,7 @@ Tkapp_SplitList(PyObject *self, PyObject *args) { char *list; int argc; - char **argv; + const char **argv; PyObject *arg, *v; int i; @@ -2088,6 +2093,9 @@ Tkapp_SplitList(PyObject *self, PyObject *args) Py_INCREF(arg); return arg; } + if (PyList_Check(arg)) { + return PySequence_Tuple(arg); + } if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list)) return NULL; @@ -2149,7 +2157,7 @@ Tkapp_Split(PyObject *self, PyObject *args) } return v; } - if (PyTuple_Check(arg)) + if (PyTuple_Check(arg) || PyList_Check(arg)) return SplitObj(arg); if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list)) @@ -2183,7 +2191,7 @@ PythonCmd_Error(Tcl_Interp *interp) * function or method. */ static int -PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) +PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]) { PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData; PyObject *func, *arg, *res; @@ -2920,20 +2928,20 @@ static PyType_Spec Tkapp_Type_spec = { typedef struct { PyObject* tuple; - int size; /* current size */ - int maxsize; /* allocated size */ + Py_ssize_t size; /* current size */ + Py_ssize_t maxsize; /* allocated size */ } FlattenContext; static int -_bump(FlattenContext* context, int size) +_bump(FlattenContext* context, Py_ssize_t size) { /* expand tuple to hold (at least) size new items. return true if successful, false if an exception was raised */ - int maxsize = context->maxsize * 2; + Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */ if (maxsize < context->size + size) - maxsize = context->size + size; + maxsize = context->size + size; /* never overflows */ context->maxsize = maxsize; @@ -2945,41 +2953,21 @@ _flatten1(FlattenContext* context, PyObject* item, int depth) { /* add tuple or list to argument tuple (recursively) */ - int i, size; + Py_ssize_t i, size; if (depth > 1000) { PyErr_SetString(PyExc_ValueError, "nesting too deep in _flatten"); return 0; - } else if (PyList_Check(item)) { - size = PyList_GET_SIZE(item); + } else if (PyTuple_Check(item) || PyList_Check(item)) { + size = PySequence_Fast_GET_SIZE(item); /* preallocate (assume no nesting) */ if (context->size + size > context->maxsize && !_bump(context, size)) return 0; /* copy items to output tuple */ for (i = 0; i < size; i++) { - PyObject *o = PyList_GET_ITEM(item, i); - if (PyList_Check(o) || PyTuple_Check(o)) { - if (!_flatten1(context, o, depth + 1)) - return 0; - } else if (o != Py_None) { - if (context->size + 1 > context->maxsize && - !_bump(context, 1)) - return 0; - Py_INCREF(o); - PyTuple_SET_ITEM(context->tuple, - context->size++, o); - } - } - } else if (PyTuple_Check(item)) { - /* same, for tuples */ - size = PyTuple_GET_SIZE(item); - if (context->size + size > context->maxsize && - !_bump(context, size)) - return 0; - for (i = 0; i < size; i++) { - PyObject *o = PyTuple_GET_ITEM(item, i); + PyObject *o = PySequence_Fast_GET_ITEM(item, i); if (PyList_Check(o) || PyTuple_Check(o)) { if (!_flatten1(context, o, depth + 1)) return 0; @@ -3037,7 +3025,7 @@ Tkinter_Create(PyObject *self, PyObject *args) try getting rid of it. */ char *className = NULL; int interactive = 0; - int wantobjects = 0; + int wantobjects = 1; int wantTk = 1; /* If false, then Tk_Init() doesn't get called */ int sync = 0; /* pass -sync to wish */ char *use = NULL; /* pass -use to wish */ |