To: vim_dev@googlegroups.com Subject: Patch 7.3.937 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.3.937 Problem: More can be shared between Python 2 and 3. Solution: Move code to if_py_both.h. (ZyX) Files: src/if_python.c, src/if_python3.c, src/if_py_both.h *** ../vim-7.3.936/src/if_python.c 2013-05-06 04:21:35.000000000 +0200 --- src/if_python.c 2013-05-12 18:31:20.000000000 +0200 *************** *** 619,624 **** --- 619,627 ---- #define DESTRUCTOR_FINISH(self) Py_DECREF(self); + #define WIN_PYTHON_REF(win) win->w_python_ref + #define BUF_PYTHON_REF(buf) buf->b_python_ref + static PyObject *OutputGetattr(PyObject *, char *); static PyObject *BufferGetattr(PyObject *, char *); static PyObject *WindowGetattr(PyObject *, char *); *************** *** 1054,1095 **** */ static PyObject * - BufferNew(buf_T *buf) - { - /* We need to handle deletion of buffers underneath us. - * If we add a "b_python_ref" field to the buf_T structure, - * then we can get at it in buf_freeall() in vim. We then - * need to create only ONE Python object per buffer - if - * we try to create a second, just INCREF the existing one - * and return it. The (single) Python object referring to - * the buffer is stored in "b_python_ref". - * Question: what to do on a buf_freeall(). We'll probably - * have to either delete the Python object (DECREF it to - * zero - a bad idea, as it leaves dangling refs!) or - * set the buf_T * value to an invalid value (-1?), which - * means we need checks in all access functions... Bah. - */ - - BufferObject *self; - - if (buf->b_python_ref != NULL) - { - self = buf->b_python_ref; - Py_INCREF(self); - } - else - { - self = PyObject_NEW(BufferObject, &BufferType); - if (self == NULL) - return NULL; - self->buf = buf; - buf->b_python_ref = self; - } - - return (PyObject *)(self); - } - - static PyObject * BufferGetattr(PyObject *self, char *name) { PyObject *r; --- 1057,1062 ---- *************** *** 1107,1136 **** /******************/ static PyInt - BufferLength(PyObject *self) - { - /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ - if (CheckBuffer((BufferObject *)(self))) - return -1; /* ??? */ - - return (((BufferObject *)(self))->buf->b_ml.ml_line_count); - } - - static PyObject * - BufferItem(PyObject *self, PyInt n) - { - return RBItem((BufferObject *)(self), n, 1, - (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); - } - - static PyObject * - BufferSlice(PyObject *self, PyInt lo, PyInt hi) - { - return RBSlice((BufferObject *)(self), lo, hi, 1, - (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); - } - - static PyInt BufferAssItem(PyObject *self, PyInt n, PyObject *val) { return RBAsItem((BufferObject *)(self), n, val, 1, --- 1074,1079 ---- *************** *** 1217,1256 **** */ static PyObject * - WindowNew(win_T *win) - { - /* We need to handle deletion of windows underneath us. - * If we add a "w_python_ref" field to the win_T structure, - * then we can get at it in win_free() in vim. We then - * need to create only ONE Python object per window - if - * we try to create a second, just INCREF the existing one - * and return it. The (single) Python object referring to - * the window is stored in "w_python_ref". - * On a win_free() we set the Python object's win_T* field - * to an invalid value. We trap all uses of a window - * object, and reject them if the win_T* field is invalid. - */ - - WindowObject *self; - - if (win->w_python_ref) - { - self = win->w_python_ref; - Py_INCREF(self); - } - else - { - self = PyObject_NEW(WindowObject, &WindowType); - if (self == NULL) - return NULL; - self->win = win; - win->w_python_ref = self; - } - - return (PyObject *)(self); - } - - static PyObject * WindowGetattr(PyObject *self, char *name) { PyObject *r; --- 1160,1165 ---- *************** *** 1289,1299 **** void python_buffer_free(buf_T *buf) { ! if (buf->b_python_ref != NULL) { ! BufferObject *bp = buf->b_python_ref; bp->buf = INVALID_BUFFER_VALUE; ! buf->b_python_ref = NULL; } } --- 1198,1208 ---- void python_buffer_free(buf_T *buf) { ! if (BUF_PYTHON_REF(buf) != NULL) { ! BufferObject *bp = BUF_PYTHON_REF(buf); bp->buf = INVALID_BUFFER_VALUE; ! BUF_PYTHON_REF(buf) = NULL; } } *************** *** 1301,1311 **** void python_window_free(win_T *win) { ! if (win->w_python_ref != NULL) { ! WindowObject *wp = win->w_python_ref; wp->win = INVALID_WINDOW_VALUE; ! win->w_python_ref = NULL; } } #endif --- 1210,1220 ---- void python_window_free(win_T *win) { ! if (WIN_PYTHON_REF(win) != NULL) { ! WindowObject *wp = WIN_PYTHON_REF(win); wp->win = INVALID_WINDOW_VALUE; ! WIN_PYTHON_REF(win) = NULL; } } #endif *** ../vim-7.3.936/src/if_python3.c 2013-05-06 04:21:35.000000000 +0200 --- src/if_python3.c 2013-05-12 18:31:20.000000000 +0200 *************** *** 621,626 **** --- 621,629 ---- #define DESTRUCTOR_FINISH(self) Py_TYPE(self)->tp_free((PyObject*)self); + #define WIN_PYTHON_REF(win) win->w_python3_ref + #define BUF_PYTHON_REF(buf) buf->b_python3_ref + static void call_PyObject_Free(void *p) { *************** *** 1067,1112 **** }; ! /* Buffer object - Definitions */ static PyObject * - BufferNew(buf_T *buf) - { - /* We need to handle deletion of buffers underneath us. - * If we add a "b_python3_ref" field to the buf_T structure, - * then we can get at it in buf_freeall() in vim. We then - * need to create only ONE Python object per buffer - if - * we try to create a second, just INCREF the existing one - * and return it. The (single) Python object referring to - * the buffer is stored in "b_python3_ref". - * Question: what to do on a buf_freeall(). We'll probably - * have to either delete the Python object (DECREF it to - * zero - a bad idea, as it leaves dangling refs!) or - * set the buf_T * value to an invalid value (-1?), which - * means we need checks in all access functions... Bah. - */ - - BufferObject *self; - - if (buf->b_python3_ref != NULL) - { - self = buf->b_python3_ref; - Py_INCREF(self); - } - else - { - self = PyObject_NEW(BufferObject, &BufferType); - buf->b_python3_ref = self; - if (self == NULL) - return NULL; - self->buf = buf; - } - - return (PyObject *)(self); - } - - static PyObject * BufferGetattro(PyObject *self, PyObject*nameobj) { PyObject *r; --- 1070,1079 ---- }; ! /* Buffer object */ static PyObject * BufferGetattro(PyObject *self, PyObject*nameobj) { PyObject *r; *************** *** 1132,1160 **** /******************/ - static Py_ssize_t - BufferLength(PyObject *self) - { - if (CheckBuffer((BufferObject *)(self))) - return -1; - - return (Py_ssize_t)(((BufferObject *)(self))->buf->b_ml.ml_line_count); - } - - static PyObject * - BufferItem(PyObject *self, Py_ssize_t n) - { - return RBItem((BufferObject *)(self), n, 1, - (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count); - } - - static PyObject * - BufferSlice(PyObject *self, Py_ssize_t lo, Py_ssize_t hi) - { - return RBSlice((BufferObject *)(self), lo, hi, 1, - (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count); - } - static PyObject * BufferSubscript(PyObject *self, PyObject* idx) { --- 1099,1104 ---- *************** *** 1342,1381 **** */ static PyObject * - WindowNew(win_T *win) - { - /* We need to handle deletion of windows underneath us. - * If we add a "w_python3_ref" field to the win_T structure, - * then we can get at it in win_free() in vim. We then - * need to create only ONE Python object per window - if - * we try to create a second, just INCREF the existing one - * and return it. The (single) Python object referring to - * the window is stored in "w_python3_ref". - * On a win_free() we set the Python object's win_T* field - * to an invalid value. We trap all uses of a window - * object, and reject them if the win_T* field is invalid. - */ - - WindowObject *self; - - if (win->w_python3_ref) - { - self = win->w_python3_ref; - Py_INCREF(self); - } - else - { - self = PyObject_NEW(WindowObject, &WindowType); - if (self == NULL) - return NULL; - self->win = win; - win->w_python3_ref = self; - } - - return (PyObject *)(self); - } - - static PyObject * WindowGetattro(PyObject *self, PyObject *nameobj) { PyObject *r; --- 1286,1291 ---- *************** *** 1575,1585 **** void python3_buffer_free(buf_T *buf) { ! if (buf->b_python3_ref != NULL) { ! BufferObject *bp = buf->b_python3_ref; bp->buf = INVALID_BUFFER_VALUE; ! buf->b_python3_ref = NULL; } } --- 1485,1495 ---- void python3_buffer_free(buf_T *buf) { ! if (BUF_PYTHON_REF(buf) != NULL) { ! BufferObject *bp = BUF_PYTHON_REF(buf); bp->buf = INVALID_BUFFER_VALUE; ! BUF_PYTHON_REF(buf) = NULL; } } *************** *** 1587,1597 **** void python3_window_free(win_T *win) { ! if (win->w_python3_ref != NULL) { ! WindowObject *wp = win->w_python3_ref; wp->win = INVALID_WINDOW_VALUE; ! win->w_python3_ref = NULL; } } #endif --- 1497,1507 ---- void python3_window_free(win_T *win) { ! if (WIN_PYTHON_REF(win) != NULL) { ! WindowObject *wp = WIN_PYTHON_REF(win); wp->win = INVALID_WINDOW_VALUE; ! WIN_PYTHON_REF(win) = NULL; } } #endif *** ../vim-7.3.936/src/if_py_both.h 2013-05-06 06:26:10.000000000 +0200 --- src/if_py_both.h 2013-05-12 18:31:20.000000000 +0200 *************** *** 1782,1792 **** --- 1782,1832 ---- return 0; } + /* Window object + */ + static int WindowSetattr(PyObject *, char *, PyObject *); static PyObject *WindowRepr(PyObject *); static PyTypeObject WindowType; static PyObject * + WindowNew(win_T *win) + { + /* We need to handle deletion of windows underneath us. + * If we add a "w_python*_ref" field to the win_T structure, + * then we can get at it in win_free() in vim. We then + * need to create only ONE Python object per window - if + * we try to create a second, just INCREF the existing one + * and return it. The (single) Python object referring to + * the window is stored in "w_python*_ref". + * On a win_free() we set the Python object's win_T* field + * to an invalid value. We trap all uses of a window + * object, and reject them if the win_T* field is invalid. + * + * Python2 and Python3 get different fields and different objects: + * w_python_ref and w_python3_ref fields respectively. + */ + + WindowObject *self; + + if (WIN_PYTHON_REF(win)) + { + self = WIN_PYTHON_REF(win); + Py_INCREF(self); + } + else + { + self = PyObject_NEW(WindowObject, &WindowType); + if (self == NULL) + return NULL; + self->win = win; + WIN_PYTHON_REF(win) = self; + } + + return (PyObject *)(self); + } + + static PyObject * WindowAttr(WindowObject *this, char *name) { if (strcmp(name, "buffer") == 0) *************** *** 1809,1815 **** return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow, (PyObject *) this); else if (strcmp(name,"__members__") == 0) ! return Py_BuildValue("[sssss]", "buffer", "cursor", "height", "vars", "options"); else return NULL; --- 1849,1855 ---- return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow, (PyObject *) this); else if (strcmp(name,"__members__") == 0) ! return Py_BuildValue("[ssssss]", "buffer", "cursor", "height", "vars", "options"); else return NULL; *************** *** 1821,1831 **** WindowObject *this = (WindowObject *)(self); if (this->win && this->win != INVALID_WINDOW_VALUE) ! #if PY_MAJOR_VERSION >= 3 ! this->win->w_python3_ref = NULL; ! #else ! this->win->w_python_ref = NULL; ! #endif DESTRUCTOR_FINISH(self); } --- 1861,1867 ---- WindowObject *this = (WindowObject *)(self); if (this->win && this->win != INVALID_WINDOW_VALUE) ! WIN_PYTHON_REF(this->win) = NULL; DESTRUCTOR_FINISH(self); } *************** *** 2756,2771 **** BufferObject *this = (BufferObject *)(self); if (this->buf && this->buf != INVALID_BUFFER_VALUE) ! #if PY_MAJOR_VERSION >= 3 ! this->buf->b_python3_ref = NULL; ! #else ! this->buf->b_python_ref = NULL; ! #endif DESTRUCTOR_FINISH(self); } static PyObject * BufferAttr(BufferObject *this, char *name) { if (strcmp(name, "name") == 0) --- 2792,2842 ---- BufferObject *this = (BufferObject *)(self); if (this->buf && this->buf != INVALID_BUFFER_VALUE) ! BUF_PYTHON_REF(this->buf) = NULL; DESTRUCTOR_FINISH(self); } static PyObject * + BufferNew(buf_T *buf) + { + /* We need to handle deletion of buffers underneath us. + * If we add a "b_python*_ref" field to the buf_T structure, + * then we can get at it in buf_freeall() in vim. We then + * need to create only ONE Python object per buffer - if + * we try to create a second, just INCREF the existing one + * and return it. The (single) Python object referring to + * the buffer is stored in "b_python*_ref". + * Question: what to do on a buf_freeall(). We'll probably + * have to either delete the Python object (DECREF it to + * zero - a bad idea, as it leaves dangling refs!) or + * set the buf_T * value to an invalid value (-1?), which + * means we need checks in all access functions... Bah. + * + * Python2 and Python3 get different fields and different objects: + * b_python_ref and b_python3_ref fields respectively. + */ + + BufferObject *self; + + if (BUF_PYTHON_REF(buf) != NULL) + { + self = BUF_PYTHON_REF(buf); + Py_INCREF(self); + } + else + { + self = PyObject_NEW(BufferObject, &BufferType); + if (self == NULL) + return NULL; + self->buf = buf; + BUF_PYTHON_REF(buf) = self; + } + + return (PyObject *)(self); + } + + static PyObject * BufferAttr(BufferObject *this, char *name) { if (strcmp(name, "name") == 0) *************** *** 2783,2788 **** --- 2854,2883 ---- return NULL; } + static PyInt + BufferLength(PyObject *self) + { + /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ + if (CheckBuffer((BufferObject *)(self))) + return -1; /* ??? */ + + return (PyInt)(((BufferObject *)(self))->buf->b_ml.ml_line_count); + } + + static PyObject * + BufferItem(PyObject *self, PyInt n) + { + return RBItem((BufferObject *)(self), n, 1, + (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count); + } + + static PyObject * + BufferSlice(PyObject *self, PyInt lo, PyInt hi) + { + return RBSlice((BufferObject *)(self), lo, hi, 1, + (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count); + } + static PyObject * BufferAppend(PyObject *self, PyObject *args) { *** ../vim-7.3.936/src/version.c 2013-05-12 14:10:41.000000000 +0200 --- src/version.c 2013-05-12 18:44:01.000000000 +0200 *************** *** 730,731 **** --- 730,733 ---- { /* Add new patch number below this line */ + /**/ + 937, /**/ -- ARTHUR: Well, I can't just call you `Man'. DENNIS: Well, you could say `Dennis'. ARTHUR: Well, I didn't know you were called `Dennis.' DENNIS: Well, you didn't bother to find out, did you? The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///