summaryrefslogtreecommitdiffstats
path: root/src/if_python.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2004-06-13 20:20:40 +0000
committerBram Moolenaar <Bram@vim.org>2004-06-13 20:20:40 +0000
commit071d4279d6ab81b7187b48f3a0fc61e587b6db6c (patch)
tree221cbe3c40e043163c06f61c52a7ba2eb41e12ce /src/if_python.c
parentb4210b3bc14e2918f153a7307530fbe6eba659e1 (diff)
updated for version 7.0001v7.0001
Diffstat (limited to 'src/if_python.c')
-rw-r--r--src/if_python.c2807
1 files changed, 2807 insertions, 0 deletions
diff --git a/src/if_python.c b/src/if_python.c
new file mode 100644
index 0000000000..21c4365203
--- /dev/null
+++ b/src/if_python.c
@@ -0,0 +1,2807 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * Python extensions by Paul Moore.
+ * Changes for Unix by David Leonard.
+ *
+ * This consists of four parts:
+ * 1. Python interpreter main program
+ * 2. Python output stream: writes output via [e]msg().
+ * 3. Implementation of the Vim module for Python
+ * 4. Utility functions for handling the interface between Vim and Python.
+ */
+
+#include "vim.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+
+/* Python.h defines _POSIX_THREADS itself (if needed) */
+#ifdef _POSIX_THREADS
+# undef _POSIX_THREADS
+#endif
+
+#if defined(_WIN32) && defined (HAVE_FCNTL_H)
+# undef HAVE_FCNTL_H
+#endif
+
+#ifdef _DEBUG
+# undef _DEBUG
+#endif
+
+#ifdef HAVE_STDARG_H
+# undef HAVE_STDARG_H /* Python's config.h defines it as well. */
+#endif
+
+#include <Python.h>
+#if defined(MACOS) && !defined(MACOS_X_UNIX)
+# include "macglue.h"
+# include <CodeFragments.h>
+#endif
+#undef main /* Defined in python.h - aargh */
+#undef HAVE_FCNTL_H /* Clash with os_win32.h */
+
+#if !defined(FEAT_PYTHON) && defined(PROTO)
+/* Use this to be able to generate prototypes without python being used. */
+# define PyObject int
+# define PyThreadState int
+# define PyTypeObject int
+struct PyMethodDef { int a; };
+# define PySequenceMethods int
+#endif
+
+/* Parser flags */
+#define single_input 256
+#define file_input 257
+#define eval_input 258
+
+#if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x020300F0
+ /* Python 2.3: can invoke ":python" recursively. */
+# define PY_CAN_RECURSE
+#endif
+
+#if defined(DYNAMIC_PYTHON) || defined(PROTO)
+# ifndef DYNAMIC_PYTHON
+# define HINSTANCE int /* for generating prototypes */
+# endif
+
+/*
+ * Wrapper defines
+ */
+# define PyArg_Parse dll_PyArg_Parse
+# define PyArg_ParseTuple dll_PyArg_ParseTuple
+# define PyDict_SetItemString dll_PyDict_SetItemString
+# define PyErr_BadArgument dll_PyErr_BadArgument
+# define PyErr_Clear dll_PyErr_Clear
+# define PyErr_NoMemory dll_PyErr_NoMemory
+# define PyErr_Occurred dll_PyErr_Occurred
+# define PyErr_SetNone dll_PyErr_SetNone
+# define PyErr_SetString dll_PyErr_SetString
+# define PyEval_InitThreads dll_PyEval_InitThreads
+# define PyEval_RestoreThread dll_PyEval_RestoreThread
+# define PyEval_SaveThread dll_PyEval_SaveThread
+# ifdef PY_CAN_RECURSE
+# define PyGILState_Ensure dll_PyGILState_Ensure
+# define PyGILState_Release dll_PyGILState_Release
+# endif
+# define PyInt_AsLong dll_PyInt_AsLong
+# define PyInt_FromLong dll_PyInt_FromLong
+# define PyInt_Type (*dll_PyInt_Type)
+# define PyList_GetItem dll_PyList_GetItem
+# define PyList_New dll_PyList_New
+# define PyList_SetItem dll_PyList_SetItem
+# define PyList_Size dll_PyList_Size
+# define PyList_Type (*dll_PyList_Type)
+# define PyImport_ImportModule dll_PyImport_ImportModule
+# define PyDict_GetItemString dll_PyDict_GetItemString
+# define PyModule_GetDict dll_PyModule_GetDict
+# define PyRun_SimpleString dll_PyRun_SimpleString
+# define PyString_AsString dll_PyString_AsString
+# define PyString_FromString dll_PyString_FromString
+# define PyString_FromStringAndSize dll_PyString_FromStringAndSize
+# define PyString_Size dll_PyString_Size
+# define PyString_Type (*dll_PyString_Type)
+# define PySys_SetObject dll_PySys_SetObject
+# define PySys_SetArgv dll_PySys_SetArgv
+# define PyType_Type (*dll_PyType_Type)
+# define Py_BuildValue dll_Py_BuildValue
+# define Py_FindMethod dll_Py_FindMethod
+# define Py_InitModule4 dll_Py_InitModule4
+# define Py_Initialize dll_Py_Initialize
+# define _PyObject_New dll__PyObject_New
+# define _Py_NoneStruct (*dll__Py_NoneStruct)
+# define PyObject_Init dll__PyObject_Init
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
+# define PyType_IsSubtype dll_PyType_IsSubtype
+# endif
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
+# define PyObject_Malloc dll_PyObject_Malloc
+# define PyObject_Free dll_PyObject_Free
+# endif
+
+/*
+ * Pointers for dynamic link
+ */
+static int(*dll_PyArg_Parse)(PyObject *, char *, ...);
+static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...);
+static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
+static int(*dll_PyErr_BadArgument)(void);
+static void(*dll_PyErr_Clear)(void);
+static PyObject*(*dll_PyErr_NoMemory)(void);
+static PyObject*(*dll_PyErr_Occurred)(void);
+static void(*dll_PyErr_SetNone)(PyObject *);
+static void(*dll_PyErr_SetString)(PyObject *, const char *);
+static void(*dll_PyEval_InitThreads)(void);
+static void(*dll_PyEval_RestoreThread)(PyThreadState *);
+static PyThreadState*(*dll_PyEval_SaveThread)(void);
+# ifdef PY_CAN_RECURSE
+static PyGILState_STATE (*dll_PyGILState_Ensure)(void);
+static void (*dll_PyGILState_Release)(PyGILState_STATE);
+#endif
+static long(*dll_PyInt_AsLong)(PyObject *);
+static PyObject*(*dll_PyInt_FromLong)(long);
+static PyTypeObject* dll_PyInt_Type;
+static PyObject*(*dll_PyList_GetItem)(PyObject *, int);
+static PyObject*(*dll_PyList_New)(int size);
+static int(*dll_PyList_SetItem)(PyObject *, int, PyObject *);
+static int(*dll_PyList_Size)(PyObject *);
+static PyTypeObject* dll_PyList_Type;
+static PyObject*(*dll_PyImport_ImportModule)(const char *);
+static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *);
+static PyObject*(*dll_PyModule_GetDict)(PyObject *);
+static int(*dll_PyRun_SimpleString)(char *);
+static char*(*dll_PyString_AsString)(PyObject *);
+static PyObject*(*dll_PyString_FromString)(const char *);
+static PyObject*(*dll_PyString_FromStringAndSize)(const char *, int);
+static int(*dll_PyString_Size)(PyObject *);
+static PyTypeObject* dll_PyString_Type;
+static int(*dll_PySys_SetObject)(char *, PyObject *);
+static int(*dll_PySys_SetArgv)(int, char **);
+static PyTypeObject* dll_PyType_Type;
+static PyObject*(*dll_Py_BuildValue)(char *, ...);
+static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *);
+static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int);
+static void(*dll_Py_Initialize)(void);
+static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *);
+static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *);
+static PyObject* dll__Py_NoneStruct;
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
+static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
+# endif
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
+static void* (*dll_PyObject_Malloc)(size_t);
+static void (*dll_PyObject_Free)(void*);
+# endif
+
+static HINSTANCE hinstPython = 0; /* Instance of python.dll */
+
+/* Imported exception objects */
+static PyObject *imp_PyExc_AttributeError;
+static PyObject *imp_PyExc_IndexError;
+static PyObject *imp_PyExc_KeyboardInterrupt;
+static PyObject *imp_PyExc_TypeError;
+static PyObject *imp_PyExc_ValueError;
+
+# define PyExc_AttributeError imp_PyExc_AttributeError
+# define PyExc_IndexError imp_PyExc_IndexError
+# define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt
+# define PyExc_TypeError imp_PyExc_TypeError
+# define PyExc_ValueError imp_PyExc_ValueError
+
+/*
+ * Table of name to function pointer of python.
+ */
+# define PYTHON_PROC FARPROC
+static struct
+{
+ char *name;
+ PYTHON_PROC *ptr;
+} python_funcname_table[] =
+{
+ {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse},
+ {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple},
+ {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString},
+ {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument},
+ {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear},
+ {"PyErr_NoMemory", (PYTHON_PROC*)&dll_PyErr_NoMemory},
+ {"PyErr_Occurred", (PYTHON_PROC*)&dll_PyErr_Occurred},
+ {"PyErr_SetNone", (PYTHON_PROC*)&dll_PyErr_SetNone},
+ {"PyErr_SetString", (PYTHON_PROC*)&dll_PyErr_SetString},
+ {"PyEval_InitThreads", (PYTHON_PROC*)&dll_PyEval_InitThreads},
+ {"PyEval_RestoreThread", (PYTHON_PROC*)&dll_PyEval_RestoreThread},
+ {"PyEval_SaveThread", (PYTHON_PROC*)&dll_PyEval_SaveThread},
+# ifdef PY_CAN_RECURSE
+ {"PyGILState_Ensure", (PYTHON_PROC*)&dll_PyGILState_Ensure},
+ {"PyGILState_Release", (PYTHON_PROC*)&dll_PyGILState_Release},
+# endif
+ {"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong},
+ {"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong},
+ {"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type},
+ {"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem},
+ {"PyList_New", (PYTHON_PROC*)&dll_PyList_New},
+ {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem},
+ {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size},
+ {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type},
+ {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule},
+ {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString},
+ {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict},
+ {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString},
+ {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
+ {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
+ {"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize},
+ {"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size},
+ {"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type},
+ {"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject},
+ {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv},
+ {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type},
+ {"Py_BuildValue", (PYTHON_PROC*)&dll_Py_BuildValue},
+ {"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod},
+ {"Py_InitModule4", (PYTHON_PROC*)&dll_Py_InitModule4},
+ {"Py_Initialize", (PYTHON_PROC*)&dll_Py_Initialize},
+ {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New},
+ {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init},
+ {"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct},
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
+ {"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype},
+# endif
+# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
+ {"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc},
+ {"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free},
+# endif
+ {"", NULL},
+};
+
+/*
+ * Free python.dll
+ */
+ static void
+end_dynamic_python(void)
+{
+ if (hinstPython)
+ {
+ FreeLibrary(hinstPython);
+ hinstPython = 0;
+ }
+}
+
+/*
+ * Load library and get all pointers.
+ * Parameter 'libname' provides name of DLL.
+ * Return OK or FAIL.
+ */
+ static int
+python_runtime_link_init(char *libname, int verbose)
+{
+ int i;
+
+ if (hinstPython)
+ return OK;
+ hinstPython = LoadLibrary(libname);
+ if (!hinstPython)
+ {
+ if (verbose)
+ EMSG2(_(e_loadlib), libname);
+ return FAIL;
+ }
+
+ for (i = 0; python_funcname_table[i].ptr; ++i)
+ {
+ if ((*python_funcname_table[i].ptr = GetProcAddress(hinstPython,
+ python_funcname_table[i].name)) == NULL)
+ {
+ FreeLibrary(hinstPython);
+ hinstPython = 0;
+ if (verbose)
+ EMSG2(_(e_loadfunc), python_funcname_table[i].name);
+ return FAIL;
+ }
+ }
+ return OK;
+}
+
+/*
+ * If python is enabled (there is installed python on Windows system) return
+ * TRUE, else FALSE.
+ */
+ int
+python_enabled(verbose)
+ int verbose;
+{
+ return python_runtime_link_init(DYNAMIC_PYTHON_DLL, verbose) == OK;
+}
+
+/* Load the standard Python exceptions - don't import the symbols from the
+ * DLL, as this can cause errors (importing data symbols is not reliable).
+ */
+static void get_exceptions __ARGS((void));
+
+ static void
+get_exceptions()
+{
+ PyObject *exmod = PyImport_ImportModule("exceptions");
+ PyObject *exdict = PyModule_GetDict(exmod);
+ imp_PyExc_AttributeError = PyDict_GetItemString(exdict, "AttributeError");
+ imp_PyExc_IndexError = PyDict_GetItemString(exdict, "IndexError");
+ imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
+ imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
+ imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
+ Py_XINCREF(imp_PyExc_AttributeError);
+ Py_XINCREF(imp_PyExc_IndexError);
+ Py_XINCREF(imp_PyExc_KeyboardInterrupt);
+ Py_XINCREF(imp_PyExc_TypeError);
+ Py_XINCREF(imp_PyExc_ValueError);
+ Py_XDECREF(exmod);
+}
+#endif /* DYNAMIC_PYTHON */
+
+/******************************************************
+ * Internal function prototypes.
+ */
+
+static void DoPythonCommand(exarg_T *, const char *);
+static int RangeStart;
+static int RangeEnd;
+
+static void PythonIO_Flush(void);
+static int PythonIO_Init(void);
+static int PythonMod_Init(void);
+
+/* Utility functions for the vim/python interface
+ * ----------------------------------------------
+ */
+static PyObject *GetBufferLine(buf_T *, int);
+static PyObject *GetBufferLineList(buf_T *, int, int);
+
+static int SetBufferLine(buf_T *, int, PyObject *, int *);
+static int SetBufferLineList(buf_T *, int, int, PyObject *, int *);
+static int InsertBufferLines(buf_T *, int, PyObject *, int *);
+
+static PyObject *LineToString(const char *);
+static char *StringToLine(PyObject *);
+
+static int VimErrorCheck(void);
+
+#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
+
+/******************************************************
+ * 1. Python interpreter main program.
+ */
+
+static int initialised = 0;
+
+#if PYTHON_API_VERSION < 1007 /* Python 1.4 */
+typedef PyObject PyThreadState;
+#endif /* Python 1.4 */
+
+#ifndef PY_CAN_RECURSE
+static PyThreadState* saved_python_thread = NULL;
+
+/*
+ * Suspend a thread of the Python interpreter, other threads are allowed to
+ * run.
+ */
+static void Python_SaveThread(void)
+{
+ saved_python_thread = PyEval_SaveThread();
+}
+
+/*
+ * Restore a thread of the Python interpreter, waits for other threads to
+ * block.
+ */
+static void Python_RestoreThread(void)
+{
+ PyEval_RestoreThread(saved_python_thread);
+ saved_python_thread = NULL;
+}
+#endif
+
+/*
+ * obtain a lock on the Vim data structures
+ */
+static void Python_Lock_Vim(void)
+{
+}
+
+/*
+ * release a lock on the Vim data structures
+ */
+static void Python_Release_Vim(void)
+{
+}
+
+ void
+python_end()
+{
+#ifdef DYNAMIC_PYTHON
+ end_dynamic_python();
+#endif
+}
+
+ static int
+Python_Init(void)
+{
+ if (!initialised)
+ {
+#ifdef DYNAMIC_PYTHON
+ if (!python_enabled(TRUE))
+ {
+ EMSG(_("E263: Sorry, this command is disabled, the Python library could not be loaded."));
+ goto fail;
+ }
+#endif
+
+#if !defined(MACOS) || defined(MACOS_X_UNIX)
+ Py_Initialize();
+#else
+ PyMac_Initialize();
+#endif
+ /* initialise threads */
+ PyEval_InitThreads();
+
+#ifdef DYNAMIC_PYTHON
+ get_exceptions();
+#endif
+
+ if (PythonIO_Init())
+ goto fail;
+
+ if (PythonMod_Init())
+ goto fail;
+
+#ifndef PY_CAN_RECURSE
+ /* the first python thread is vim's */
+ Python_SaveThread();
+#endif
+
+ initialised = 1;
+ }
+
+ return 0;
+
+fail:
+ /* We call PythonIO_Flush() here to print any Python errors.
+ * This is OK, as it is possible to call this function even
+ * if PythonIO_Init() has not completed successfully (it will
+ * not do anything in this case).
+ */
+ PythonIO_Flush();
+ return -1;
+}
+
+/*
+ * External interface
+ */
+ static void
+DoPythonCommand(exarg_T *eap, const char *cmd)
+{
+#ifdef PY_CAN_RECURSE
+ PyGILState_STATE pygilstate;
+#else
+ static int recursive = 0;
+#endif
+#if defined(MACOS) && !defined(MACOS_X_UNIX)
+ GrafPtr oldPort;
+#endif
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ char *saved_locale;
+#endif
+
+#ifndef PY_CAN_RECURSE
+ if (recursive)
+ {
+ EMSG(_("E659: Cannot invoke Python recursively"));
+ return;
+ }
+ ++recursive;
+#endif
+
+#if defined(MACOS) && !defined(MACOS_X_UNIX)
+ GetPort(&oldPort);
+ /* Check if the Python library is available */
+ if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress)
+ goto theend;
+#endif
+ if (Python_Init())
+ goto theend;
+
+ RangeStart = eap->line1;
+ RangeEnd = eap->line2;
+ Python_Release_Vim(); /* leave vim */
+
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ /* Python only works properly when the LC_NUMERIC locale is "C". */
+ saved_locale = setlocale(LC_NUMERIC, NULL);
+ if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0)
+ saved_locale = NULL;
+ else
+ {
+ /* Need to make a copy, value may change when setting new locale. */
+ saved_locale = (char *)vim_strsave((char_u *)saved_locale);
+ (void)setlocale(LC_NUMERIC, "C");
+ }
+#endif
+
+#ifdef PY_CAN_RECURSE
+ pygilstate = PyGILState_Ensure();
+#else
+ Python_RestoreThread(); /* enter python */
+#endif
+
+ PyRun_SimpleString((char *)(cmd));
+
+#ifdef PY_CAN_RECURSE
+ PyGILState_Release(pygilstate);
+#else
+ Python_SaveThread(); /* leave python */
+#endif
+
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+ if (saved_locale != NULL)
+ {
+ (void)setlocale(LC_NUMERIC, saved_locale);
+ vim_free(saved_locale);
+ }
+#endif
+
+ Python_Lock_Vim(); /* enter vim */
+ PythonIO_Flush();
+#if defined(MACOS) && !defined(MACOS_X_UNIX)
+ SetPort(oldPort);
+#endif
+
+theend:
+#ifndef PY_CAN_RECURSE
+ --recursive;
+#endif
+ return; /* keeps lint happy */
+}
+
+/*
+ * ":python"
+ */
+ void
+ex_python(exarg_T *eap)
+{
+ char_u *script;
+
+ script = script_get(eap, eap->arg);
+ if (!eap->skip)
+ {
+ if (script == NULL)
+ DoPythonCommand(eap, (char *)eap->arg);
+ else
+ DoPythonCommand(eap, (char *)script);
+ }
+ vim_free(script);
+}
+
+#define BUFFER_SIZE 1024
+
+/*
+ * ":pyfile"
+ */
+ void
+ex_pyfile(exarg_T *eap)
+{
+ static char buffer[BUFFER_SIZE];
+ const char *file = (char *)eap->arg;
+ char *p;
+
+ /* Have to do it like this. PyRun_SimpleFile requires you to pass a
+ * stdio file pointer, but Vim and the Python DLL are compiled with
+ * different options under Windows, meaning that stdio pointers aren't
+ * compatible between the two. Yuk.
+ *
+ * Put the string "execfile('file')" into buffer. But, we need to
+ * escape any backslashes or single quotes in the file name, so that
+ * Python won't mangle the file name.
+ */
+ strcpy(buffer, "execfile('");
+ p = buffer + 10; /* size of "execfile('" */
+
+ while (*file && p < buffer + (BUFFER_SIZE - 3))
+ {
+ if (*file == '\\' || *file == '\'')
+ *p++ = '\\';
+ *p++ = *file++;
+ }
+
+ /* If we didn't finish the file name, we hit a buffer overflow */
+ if (*file != '\0')
+ return;
+
+ /* Put in the terminating "')" and a null */
+ *p++ = '\'';
+ *p++ = ')';
+ *p++ = '\0';
+
+ /* Execute the file */
+ DoPythonCommand(eap, buffer);
+}
+
+/******************************************************
+ * 2. Python output stream: writes output via [e]msg().
+ */
+
+/* Implementation functions
+ */
+
+static PyObject *OutputGetattr(PyObject *, char *);
+static int OutputSetattr(PyObject *, char *, PyObject *);
+
+static PyObject *OutputWrite(PyObject *, PyObject *);
+static PyObject *OutputWritelines(PyObject *, PyObject *);
+
+typedef void (*writefn)(char_u *);
+static void writer(writefn fn, char_u *str, int n);
+
+/* Output object definition
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+ long softspace;
+ long error;
+} OutputObject;
+
+static struct PyMethodDef OutputMethods[] = {
+ /* name, function, calling, documentation */
+ {"write", OutputWrite, 1, "" },
+ {"writelines", OutputWritelines, 1, "" },
+ { NULL, NULL, 0, NULL }
+};
+
+static PyTypeObject OutputType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "message",
+ sizeof(OutputObject),
+ 0,
+
+ (destructor) 0,
+ (printfunc) 0,
+ (getattrfunc) OutputGetattr,
+ (setattrfunc) OutputSetattr,
+ (cmpfunc) 0,
+ (reprfunc) 0,
+
+ 0, /* as number */
+ 0, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0,
+ (ternaryfunc) 0,
+ (reprfunc) 0
+};
+
+/*************/
+
+ static PyObject *
+OutputGetattr(PyObject *self, char *name)
+{
+ if (strcmp(name, "softspace") == 0)
+ return PyInt_FromLong(((OutputObject *)(self))->softspace);
+
+ return Py_FindMethod(OutputMethods, self, name);
+}
+
+ static int
+OutputSetattr(PyObject *self, char *name, PyObject *val)
+{
+ if (val == NULL) {
+ PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes"));
+ return -1;
+ }
+
+ if (strcmp(name, "softspace") == 0)
+ {
+ if (!PyInt_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
+ return -1;
+ }
+
+ ((OutputObject *)(self))->softspace = PyInt_AsLong(val);
+ return 0;
+ }
+
+ PyErr_SetString(PyExc_AttributeError, _("invalid attribute"));
+ return -1;
+}
+
+/*************/
+
+ static PyObject *
+OutputWrite(PyObject *self, PyObject *args)
+{
+ int len;
+ char *str;
+ int error = ((OutputObject *)(self))->error;
+
+ if (!PyArg_ParseTuple(args, "s#", &str, &len))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ writer((writefn)(error ? emsg : msg), (char_u *)str, len);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+ static PyObject *
+OutputWritelines(PyObject *self, PyObject *args)
+{
+ int n;
+ int i;
+ PyObject *list;
+ int error = ((OutputObject *)(self))->error;
+
+ if (!PyArg_ParseTuple(args, "O", &list))
+ return NULL;
+ Py_INCREF(list);
+
+ if (!PyList_Check(list)) {
+ PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ n = PyList_Size(list);
+
+ for (i = 0; i < n; ++i)
+ {
+ PyObject *line = PyList_GetItem(list, i);
+ char *str;
+ int len;
+
+ if (!PyArg_Parse(line, "s#", &str, &len)) {
+ PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ writer((writefn)(error ? emsg : msg), (char_u *)str, len);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+ }
+
+ Py_DECREF(list);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/* Output buffer management
+ */
+
+static char_u *buffer = NULL;
+static int buffer_len = 0;
+static int buffer_size = 0;
+
+static writefn old_fn = NULL;
+
+ static void
+buffer_ensure(int n)
+{
+ int new_size;
+ char_u *new_buffer;
+
+ if (n < buffer_size)
+ return;
+
+ new_size = buffer_size;
+ while (new_size < n)
+ new_size += 80;
+
+ if (new_size != buffer_size)
+ {
+ new_buffer = alloc((unsigned)new_size);
+ if (new_buffer == NULL)
+ return;
+
+ if (buffer)
+ {
+ memcpy(new_buffer, buffer, buffer_len);
+ vim_free(buffer);
+ }
+
+ buffer = new_buffer;
+ buffer_size = new_size;
+ }
+}
+
+ static void
+PythonIO_Flush(void)
+{
+ if (old_fn && buffer_len)
+ {
+ buffer[buffer_len] = 0;
+ old_fn(buffer);
+ }
+
+ buffer_len = 0;
+}
+
+ static void
+writer(writefn fn, char_u *str, int n)
+{
+ char_u *ptr;
+
+ if (fn != old_fn && old_fn != NULL)
+ PythonIO_Flush();
+
+ old_fn = fn;
+
+ while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
+ {
+ int len = ptr - str;
+
+ buffer_ensure(buffer_len + len + 1);
+
+ memcpy(buffer + buffer_len, str, len);
+ buffer_len += len;
+ buffer[buffer_len] = 0;
+ fn(buffer);
+ str = ptr + 1;
+ n -= len + 1;
+ buffer_len = 0;
+ }
+
+ /* Put the remaining text into the buffer for later printing */
+ buffer_ensure(buffer_len + n + 1);
+ memcpy(buffer + buffer_len, str, n);
+ buffer_len += n;
+}
+
+/***************/
+
+static OutputObject Output =
+{
+ PyObject_HEAD_INIT(&OutputType)
+ 0,
+ 0
+};
+
+static OutputObject Error =
+{
+ PyObject_HEAD_INIT(&OutputType)
+ 0,
+ 1
+};
+
+ static int
+PythonIO_Init(void)
+{
+ /* Fixups... */
+ OutputType.ob_type = &PyType_Type;
+
+ PySys_SetObject("stdout", (PyObject *)(&Output));
+ PySys_SetObject("stderr", (PyObject *)(&Error));
+
+ if (PyErr_Occurred())
+ {
+ EMSG(_("E264: Python: Error initialising I/O objects"));
+ return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************
+ * 3. Implementation of the Vim module for Python
+ */
+
+/* Vim module - Implementation functions
+ * -------------------------------------
+ */
+
+static PyObject *VimError;
+
+static PyObject *VimCommand(PyObject *, PyObject *);
+static PyObject *VimEval(PyObject *, PyObject *);
+
+/* Window type - Implementation functions
+ * --------------------------------------
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+ win_T *win;
+}
+WindowObject;
+
+#define INVALID_WINDOW_VALUE ((win_T *)(-1))
+
+#define WindowType_Check(obj) ((obj)->ob_type == &WindowType)
+
+static PyObject *WindowNew(win_T *);
+
+static void WindowDestructor(PyObject *);
+static PyObject *WindowGetattr(PyObject *, char *);
+static int WindowSetattr(PyObject *, char *, PyObject *);
+static PyObject *WindowRepr(PyObject *);
+
+/* Buffer type - Implementation functions
+ * --------------------------------------
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+ buf_T *buf;
+}
+BufferObject;
+
+#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
+
+#define BufferType_Check(obj) ((obj)->ob_type == &BufferType)
+
+static PyObject *BufferNew (buf_T *);
+
+static void BufferDestructor(PyObject *);
+static PyObject *BufferGetattr(PyObject *, char *);
+static PyObject *BufferRepr(PyObject *);
+
+static int BufferLength(PyObject *);
+static PyObject *BufferItem(PyObject *, int);
+static PyObject *BufferSlice(PyObject *, int, int);
+static int BufferAssItem(PyObject *, int, PyObject *);
+static int BufferAssSlice(PyObject *, int, int, PyObject *);
+
+static PyObject *BufferAppend(PyObject *, PyObject *);
+static PyObject *BufferMark(PyObject *, PyObject *);
+static PyObject *BufferRange(PyObject *, PyObject *);
+
+/* Line range type - Implementation functions
+ * --------------------------------------
+ */
+
+typedef struct
+{
+ PyObject_HEAD
+ BufferObject *buf;
+ int start;
+ int end;
+}
+RangeObject;
+
+#define RangeType_Check(obj) ((obj)->ob_type == &RangeType)
+
+static PyObject *RangeNew(buf_T *, int, int);
+
+static void RangeDestructor(PyObject *);
+static PyObject *RangeGetattr(PyObject *, char *);
+static PyObject *RangeRepr(PyObject *);
+
+static int RangeLength(PyObject *);
+static PyObject *RangeItem(PyObject *, int);
+static PyObject *RangeSlice(PyObject *, int, int);
+static int RangeAssItem(PyObject *, int, PyObject *);
+static int RangeAssSlice(PyObject *, int, int, PyObject *);
+
+static PyObject *RangeAppend(PyObject *, PyObject *);
+
+/* Window list type - Implementation functions
+ * -------------------------------------------
+ */
+
+static int WinListLength(PyObject *);
+static PyObject *WinListItem(PyObject *, int);
+
+/* Buffer list type - Implementation functions
+ * -------------------------------------------
+ */
+
+static int BufListLength(PyObject *);
+static PyObject *BufListItem(PyObject *, int);
+
+/* Current objects type - Implementation functions
+ * -----------------------------------------------
+ */
+
+static PyObject *CurrentGetattr(PyObject *, char *);
+static int CurrentSetattr(PyObject *, char *, PyObject *);
+
+/* Vim module - Definitions
+ */
+
+static struct PyMethodDef VimMethods[] = {
+ /* name, function, calling, documentation */
+ {"command", VimCommand, 1, "" },
+ {"eval", VimEval, 1, "" },
+ { NULL, NULL, 0, NULL }
+};
+
+/* Vim module - Implementation
+ */
+/*ARGSUSED*/
+ static PyObject *
+VimCommand(PyObject *self, PyObject *args)
+{
+ char *cmd;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "s", &cmd))
+ return NULL;
+
+ PyErr_Clear();
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+
+ do_cmdline_cmd((char_u *)cmd);
+ update_screen(VALID);
+
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ if (VimErrorCheck())
+ result = NULL;
+ else
+ result = Py_None;
+
+ Py_XINCREF(result);
+ return result;
+}
+
+/*ARGSUSED*/
+ static PyObject *
+VimEval(PyObject *self, PyObject *args)
+{
+#ifdef FEAT_EVAL
+ char *expr;
+ char *str;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "s", &expr))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ str = (char *)eval_to_string((char_u *)expr, NULL);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ if (str == NULL)
+ {
+ PyErr_SetVim(_("invalid expression"));
+ return NULL;
+ }
+
+ result = Py_BuildValue("s", str);
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ vim_free(str);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ return result;
+#else
+ PyErr_SetVim(_("expressions disabled at compile time"));
+ return NULL;
+#endif
+}
+
+/* Common routines for buffers and line ranges
+ * -------------------------------------------
+ */
+ static int
+CheckBuffer(BufferObject *this)
+{
+ if (this->buf == INVALID_BUFFER_VALUE)
+ {
+ PyErr_SetVim(_("attempt to refer to deleted buffer"));
+ return -1;
+ }
+
+ return 0;
+}
+
+ static PyObject *
+RBItem(BufferObject *self, int n, int start, int end)
+{
+ if (CheckBuffer(self))
+ return NULL;
+
+ if (n < 0 || n > end - start)
+ {
+ PyErr_SetString(PyExc_IndexError, _("line number out of range"));
+ return NULL;
+ }
+
+ return GetBufferLine(self->buf, n+start);
+}
+
+ static PyObject *
+RBSlice(BufferObject *self, int lo, int hi, int start, int end)
+{
+ int size;
+
+ if (CheckBuffer(self))
+ return NULL;
+
+ 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;
+
+ return GetBufferLineList(self->buf, lo+start, hi+start);
+}
+
+ static int
+RBAssItem(BufferObject *self, int n, PyObject *val, int start, int end, int *new_end)
+{
+ int len_change;
+
+ if (CheckBuffer(self))
+ return -1;
+
+ if (n < 0 || n > end - start)
+ {
+ PyErr_SetString(PyExc_IndexError, _("line number out of range"));
+ return -1;
+ }
+
+ if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
+ return -1;
+
+ if (new_end)
+ *new_end = end + len_change;
+
+ return 0;
+}
+
+ static int
+RBAssSlice(BufferObject *self, int lo, int hi, PyObject *val, int start, int end, int *new_end)
+{
+ int size;
+ int 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 PyObject *
+RBAppend(BufferObject *self, PyObject *args, int start, int end, int *new_end)
+{
+ PyObject *lines;
+ int len_change;
+ int max;
+ int n;
+
+ if (CheckBuffer(self))
+ return NULL;
+
+ max = n = end - start + 1;
+