diff src/if_python.c @ 2894:fe9c7da98b5e v7.3.220

updated for version 7.3.220 Problem: Python 3: vim.error is a 'str' instead of an 'Exception' object, so 'except' or 'raise' it causes a 'SystemError' exception. Buffer objects do not support slice assignment. When exchanging text between Vim and Python, multibyte texts become gabage or cause Unicode Expceptions, etc. 'py3file' tries to read in the file as Unicode, sometimes causes UnicodeDecodeException Solution: Fix the problems. (lilydjwg)
author Bram Moolenaar <bram@vim.org>
date Sun, 19 Jun 2011 00:27:51 +0200
parents 329a9676040c
children e4f3fa1a474e
line wrap: on
line diff
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -56,6 +56,10 @@
 
 static void init_structs(void);
 
+/* No-op conversion functions, use with care! */
+#define PyString_AsBytes(obj) (obj)
+#define PyString_FreeBytes(obj)
+
 #if !defined(FEAT_PYTHON) && defined(PROTO)
 /* Use this to be able to generate prototypes without python being used. */
 # define PyObject Py_ssize_t
@@ -129,6 +133,7 @@ struct PyMethodDef { Py_ssize_t a; };
  */
 # define PyArg_Parse dll_PyArg_Parse
 # define PyArg_ParseTuple dll_PyArg_ParseTuple
+# define PyMem_Free dll_PyMem_Free
 # define PyDict_SetItemString dll_PyDict_SetItemString
 # define PyErr_BadArgument dll_PyErr_BadArgument
 # define PyErr_Clear dll_PyErr_Clear
@@ -189,6 +194,7 @@ struct PyMethodDef { Py_ssize_t a; };
  */
 static int(*dll_PyArg_Parse)(PyObject *, char *, ...);
 static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...);
+static int(*dll_PyMem_Free)(void *);
 static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
 static int(*dll_PyErr_BadArgument)(void);
 static void(*dll_PyErr_Clear)(void);
@@ -271,6 +277,7 @@ static struct
 {
     {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse},
     {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple},
+    {"PyMem_Free", (PYTHON_PROC*)&dll_PyMem_Free},
     {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString},
     {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument},
     {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear},
@@ -833,44 +840,6 @@ static PyInt RangeAssSlice(PyObject *, P
 static PyObject *CurrentGetattr(PyObject *, char *);
 static int CurrentSetattr(PyObject *, char *, PyObject *);
 
-/* Common routines for buffers and line ranges
- * -------------------------------------------
- */
-
-    static PyInt
-RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
-{
-    PyInt size;
-    PyInt len_change;
-
-    /* Self must be a valid buffer */
-    if (CheckBuffer(self))
-	return -1;
-
-    /* Sort out the slice range */
-    size = end - start + 1;
-
-    if (lo < 0)
-	lo = 0;
-    else if (lo > size)
-	lo = size;
-    if (hi < 0)
-	hi = 0;
-    if (hi < lo)
-	hi = lo;
-    else if (hi > size)
-	hi = size;
-
-    if (SetBufferLineList(self->buf, lo + start, hi + start,
-						    val, &len_change) == FAIL)
-	return -1;
-
-    if (new_end)
-	*new_end = end + len_change;
-
-    return 0;
-}
-
 static PySequenceMethods BufferAsSeq = {
     (PyInquiry)		BufferLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0, /* BufferConcat, */	     /* sq_concat,    x+y      */
@@ -1038,7 +1007,7 @@ BufferAssItem(PyObject *self, PyInt n, P
     static PyInt
 BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
 {
-    return RBAssSlice((BufferObject *)(self), lo, hi, val, 1,
+    return RBAsSlice((BufferObject *)(self), lo, hi, val, 1,
 		      (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count,
 		      NULL);
 }
@@ -1088,7 +1057,7 @@ RangeAssItem(PyObject *self, PyInt n, Py
     static PyInt
 RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
 {
-    return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val,
+    return RBAsSlice(((RangeObject *)(self))->buf, lo, hi, val,
 		      ((RangeObject *)(self))->start,
 		      ((RangeObject *)(self))->end,
 		      &((RangeObject *)(self))->end);
@@ -1435,194 +1404,6 @@ PythonMod_Init(void)
  * 4. Utility functions for handling the interface between Vim and Python.
  */
 
-/* Replace a range of lines in the specified buffer. The line numbers are in
- * Vim format (1-based). The range is from lo up to, but not including, hi.
- * The replacement lines are given as a Python list of string objects. The
- * list is checked for validity and correct format. Errors are returned as a
- * value of FAIL.  The return value is OK on success.
- * If OK is returned and len_change is not NULL, *len_change
- * is set to the change in the buffer length.
- */
-    static int
-SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
-{
-    /* First of all, we check the thpe of the supplied Python object.
-     * There are three cases:
-     *	  1. NULL, or None - this is a deletion.
-     *	  2. A list	   - this is a replacement.
-     *	  3. Anything else - this is an error.
-     */
-    if (list == Py_None || list == NULL)
-    {
-	PyInt	i;
-	PyInt	n = (int)(hi - lo);
-	buf_T	*savebuf = curbuf;
-
-	PyErr_Clear();
-	curbuf = buf;
-
-	if (u_savedel((linenr_T)lo, (long)n) == FAIL)
-	    PyErr_SetVim(_("cannot save undo information"));
-	else
-	{
-	    for (i = 0; i < n; ++i)
-	    {
-		if (ml_delete((linenr_T)lo, FALSE) == FAIL)
-		{
-		    PyErr_SetVim(_("cannot delete line"));
-		    break;
-		}
-	    }
-	    if (buf == curwin->w_buffer)
-		py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
-	    deleted_lines_mark((linenr_T)lo, (long)i);
-	}
-
-	curbuf = savebuf;
-
-	if (PyErr_Occurred() || VimErrorCheck())
-	    return FAIL;
-
-	if (len_change)
-	    *len_change = -n;
-
-	return OK;
-    }
-    else if (PyList_Check(list))
-    {
-	PyInt	i;
-	PyInt	new_len = PyList_Size(list);
-	PyInt	old_len = hi - lo;
-	PyInt	extra = 0;	/* lines added to text, can be negative */
-	char	**array;
-	buf_T	*savebuf;
-
-	if (new_len == 0)	/* avoid allocating zero bytes */
-	    array = NULL;
-	else
-	{
-	    array = (char **)alloc((unsigned)(new_len * sizeof(char *)));
-	    if (array == NULL)
-	    {
-		PyErr_NoMemory();
-		return FAIL;
-	    }
-	}
-
-	for (i = 0; i < new_len; ++i)
-	{
-	    PyObject *line = PyList_GetItem(list, i);
-
-	    array[i] = StringToLine(line);
-	    if (array[i] == NULL)
-	    {
-		while (i)
-		    vim_free(array[--i]);
-		vim_free(array);
-		return FAIL;
-	    }
-	}
-
-	savebuf = curbuf;
-
-	PyErr_Clear();
-	curbuf = buf;
-
-	if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
-	    PyErr_SetVim(_("cannot save undo information"));
-
-	/* If the size of the range is reducing (ie, new_len < old_len) we
-	 * need to delete some old_len. We do this at the start, by
-	 * repeatedly deleting line "lo".
-	 */
-	if (!PyErr_Occurred())
-	{
-	    for (i = 0; i < old_len - new_len; ++i)
-		if (ml_delete((linenr_T)lo, FALSE) == FAIL)
-		{
-		    PyErr_SetVim(_("cannot delete line"));
-		    break;
-		}
-	    extra -= i;
-	}
-
-	/* For as long as possible, replace the existing old_len with the
-	 * new old_len. This is a more efficient operation, as it requires
-	 * less memory allocation and freeing.
-	 */
-	if (!PyErr_Occurred())
-	{
-	    for (i = 0; i < old_len && i < new_len; ++i)
-		if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
-								      == FAIL)
-		{
-		    PyErr_SetVim(_("cannot replace line"));
-		    break;
-		}
-	}
-	else
-	    i = 0;
-
-	/* Now we may need to insert the remaining new old_len. If we do, we
-	 * must free the strings as we finish with them (we can't pass the
-	 * responsibility to vim in this case).
-	 */
-	if (!PyErr_Occurred())
-	{
-	    while (i < new_len)
-	    {
-		if (ml_append((linenr_T)(lo + i - 1),
-					(char_u *)array[i], 0, FALSE) == FAIL)
-		{
-		    PyErr_SetVim(_("cannot insert line"));
-		    break;
-		}
-		vim_free(array[i]);
-		++i;
-		++extra;
-	    }
-	}
-
-	/* Free any left-over old_len, as a result of an error */
-	while (i < new_len)
-	{
-	    vim_free(array[i]);
-	    ++i;
-	}
-
-	/* Free the array of old_len. All of its contents have now
-	 * been dealt with (either freed, or the responsibility passed
-	 * to vim.
-	 */
-	vim_free(array);
-
-	/* Adjust marks. Invalidate any which lie in the
-	 * changed range, and move any in the remainder of the buffer.
-	 */
-	mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
-						  (long)MAXLNUM, (long)extra);
-	changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
-
-	if (buf == curwin->w_buffer)
-	    py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
-
-	curbuf = savebuf;
-
-	if (PyErr_Occurred() || VimErrorCheck())
-	    return FAIL;
-
-	if (len_change)
-	    *len_change = new_len - old_len;
-
-	return OK;
-    }
-    else
-    {
-	PyErr_BadArgument();
-	return FAIL;
-    }
-}
-
 /* Convert a Vim line into a Python string.
  * All internal newlines are replaced by null characters.
  *