# HG changeset patch # User Bram Moolenaar # Date 1369153178 -7200 # Node ID 8fe768bc1234fc817db3cda61ae9e9dabf4ae958 # Parent a711e3771a028c8c69cb8e2625fc8f069bbf3261 updated for version 7.3.991 Problem: More can be shared by Python 2 and 3. Solution: Move more stuff to if_py_both. (ZyX) diff --git a/src/if_py_both.h b/src/if_py_both.h --- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -30,6 +30,9 @@ typedef int Py_ssize_t; /* Python 2.4 a #define INVALID_WINDOW_VALUE ((win_T *)(-1)) #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1)) +typedef void (*rangeinitializer)(void *); +typedef void (*runner)(const char *, void *, PyGILState_STATE *); + static int ConvertFromPyObject(PyObject *, typval_T *); static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *); static PyObject *WindowNew(win_T *, tabpage_T *); @@ -39,6 +42,8 @@ static PyObject *LineToString(const char static PyInt RangeStart; static PyInt RangeEnd; +static PyObject *globals; + /* * obtain a lock on the Vim data structures */ @@ -1296,7 +1301,7 @@ FunctionDestructor(PyObject *self) FunctionObject *this = (FunctionObject *) (self); func_unref(this->name); - PyMem_Del(this->name); + PyMem_Free(this->name); DESTRUCTOR_FINISH(self); } @@ -3432,6 +3437,126 @@ CurrentSetattr(PyObject *self UNUSED, ch } static void +init_range_cmd(exarg_T *eap) +{ + RangeStart = eap->line1; + RangeEnd = eap->line2; +} + + static void +init_range_eval(typval_T *rettv UNUSED) +{ + RangeStart = (PyInt) curwin->w_cursor.lnum; + RangeEnd = RangeStart; +} + + static void +run_cmd(const char *cmd, void *arg UNUSED, PyGILState_STATE *pygilstate UNUSED) +{ + PyRun_SimpleString((char *) cmd); +} + +static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n "; +static int code_hdr_len = 30; + + static void +run_do(const char *cmd, void *arg UNUSED, PyGILState_STATE *pygilstate) +{ + PyInt lnum; + size_t len; + char *code; + int status; + PyObject *pyfunc, *pymain; + + if (u_save(RangeStart - 1, RangeEnd + 1) != OK) + { + EMSG(_("cannot save undo information")); + return; + } + + len = code_hdr_len + STRLEN(cmd); + code = PyMem_New(char, len + 1); + memcpy(code, code_hdr, code_hdr_len); + STRCPY(code + code_hdr_len, cmd); + status = PyRun_SimpleString(code); + PyMem_Free(code); + + if (status) + { + EMSG(_("failed to run the code")); + return; + } + + status = 0; + pymain = PyImport_AddModule("__main__"); + pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC); + PyGILState_Release(*pygilstate); + + for (lnum = RangeStart; lnum <= RangeEnd; ++lnum) + { + PyObject *line, *linenr, *ret; + + *pygilstate = PyGILState_Ensure(); + if (!(line = GetBufferLine(curbuf, lnum))) + goto err; + if (!(linenr = PyInt_FromLong((long) lnum))) + { + Py_DECREF(line); + goto err; + } + ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL); + Py_DECREF(line); + Py_DECREF(linenr); + if (!ret) + goto err; + + if (ret != Py_None) + if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL) + goto err; + + Py_XDECREF(ret); + PythonIO_Flush(); + PyGILState_Release(*pygilstate); + } + goto out; +err: + *pygilstate = PyGILState_Ensure(); + PyErr_PrintEx(0); + PythonIO_Flush(); + status = 1; +out: + if (!status) + *pygilstate = PyGILState_Ensure(); + Py_DECREF(pyfunc); + PyObject_SetAttrString(pymain, DOPY_FUNC, NULL); + if (status) + return; + check_cursor(); + update_curbuf(NOT_VALID); +} + + static void +run_eval(const char *cmd, typval_T *rettv, PyGILState_STATE *pygilstate UNUSED) +{ + PyObject *r; + + r = PyRun_String((char *) cmd, Py_eval_input, globals, globals); + if (r == NULL) + { + if (PyErr_Occurred() && !msg_silent) + PyErr_PrintEx(0); + EMSG(_("E858: Eval did not return a valid python object")); + } + else + { + if (ConvertFromPyObject(r, rettv) == -1) + EMSG(_("E859: Failed to convert returned python object to vim value")); + Py_DECREF(r); + } + PyErr_Clear(); +} + + static void set_ref_in_py(const int copyID) { pylinkedlist_T *cur; diff --git a/src/if_python.c b/src/if_python.c --- a/src/if_python.c +++ b/src/if_python.c @@ -659,8 +659,6 @@ static PyObject *FunctionGetattr(PyObjec * Internal function prototypes. */ -static PyObject *globals; - static void PythonIO_Flush(void); static int PythonIO_Init(void); static int PythonMod_Init(void); @@ -828,7 +826,7 @@ fail: * External interface */ static void -DoPythonCommand(exarg_T *eap, const char *cmd, typval_T *rettv) +DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg) { #ifndef PY_CAN_RECURSE static int recursive = 0; @@ -861,16 +859,8 @@ DoPythonCommand(exarg_T *eap, const char if (Python_Init()) goto theend; - if (rettv == NULL) - { - RangeStart = eap->line1; - RangeEnd = eap->line2; - } - else - { - RangeStart = (PyInt) curwin->w_cursor.lnum; - RangeEnd = RangeStart; - } + init_range(arg); + Python_Release_Vim(); /* leave vim */ #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) @@ -892,27 +882,7 @@ DoPythonCommand(exarg_T *eap, const char Python_RestoreThread(); /* enter python */ #endif - if (rettv == NULL) - PyRun_SimpleString((char *)(cmd)); - else - { - PyObject *r; - - r = PyRun_String((char *)(cmd), Py_eval_input, globals, globals); - if (r == NULL) - { - if (PyErr_Occurred() && !msg_silent) - PyErr_PrintEx(0); - EMSG(_("E858: Eval did not return a valid python object")); - } - else - { - if (ConvertFromPyObject(r, rettv) == -1) - EMSG(_("E859: Failed to convert returned python object to vim value")); - Py_DECREF(r); - } - PyErr_Clear(); - } + run((char *) cmd, arg, &pygilstate); #ifdef PY_CAN_RECURSE PyGILState_Release(pygilstate); @@ -952,10 +922,10 @@ ex_python(exarg_T *eap) script = script_get(eap, eap->arg); if (!eap->skip) { - if (script == NULL) - DoPythonCommand(eap, (char *)eap->arg, NULL); - else - DoPythonCommand(eap, (char *)script, NULL); + DoPyCommand(script == NULL ? (char *) eap->arg : (char *) script, + (rangeinitializer) init_range_cmd, + (runner) run_cmd, + (void *) eap); } vim_free(script); } @@ -1001,94 +971,19 @@ ex_pyfile(exarg_T *eap) *p++ = '\0'; /* Execute the file */ - DoPythonCommand(eap, buffer, NULL); + DoPyCommand(buffer, + (rangeinitializer) init_range_cmd, + (runner) run_cmd, + (void *) eap); } void ex_pydo(exarg_T *eap) { - linenr_T i; - const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n "; - const char *s = (const char *) eap->arg; - size_t len; - char *code; - int status; - PyObject *pyfunc, *pymain; - PyGILState_STATE pygilstate; - - if (Python_Init()) - return; - - if (u_save(eap->line1 - 1, eap->line2 + 1) != OK) - { - EMSG(_("cannot save undo information")); - return; - } - len = strlen(code_hdr) + strlen(s); - code = malloc(len + 1); - STRCPY(code, code_hdr); - STRNCAT(code, s, len + 1); - pygilstate = PyGILState_Ensure(); - status = PyRun_SimpleString(code); - vim_free(code); - if (status) - { - EMSG(_("failed to run the code")); - return; - } - status = 0; /* good */ - pymain = PyImport_AddModule("__main__"); - pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC); - PyGILState_Release(pygilstate); - - for (i = eap->line1; i <= eap->line2; i++) - { - const char *line; - PyObject *pyline, *pylinenr, *pyret; - - line = (char *)ml_get(i); - pygilstate = PyGILState_Ensure(); - pyline = PyString_FromStringAndSize(line, strlen(line)); - pylinenr = PyLong_FromLong(i); - pyret = PyObject_CallFunctionObjArgs(pyfunc, pyline, pylinenr, NULL); - Py_DECREF(pyline); - Py_DECREF(pylinenr); - if (!pyret) - { - PyErr_PrintEx(0); - PythonIO_Flush(); - status = 1; - goto out; - } - - if (pyret && pyret != Py_None) - { - if (!PyString_Check(pyret)) - { - EMSG(_("E863: return value must be an instance of str")); - Py_XDECREF(pyret); - status = 1; - goto out; - } - ml_replace(i, (char_u *) PyString_AsString(pyret), 1); - changed(); -#ifdef SYNTAX_HL - syn_changed(i); /* recompute syntax hl. for this line */ -#endif - } - Py_XDECREF(pyret); - PythonIO_Flush(); - PyGILState_Release(pygilstate); - } - pygilstate = PyGILState_Ensure(); -out: - Py_DECREF(pyfunc); - PyObject_SetAttrString(pymain, DOPY_FUNC, NULL); - PyGILState_Release(pygilstate); - if (status) - return; - check_cursor(); - update_curbuf(NOT_VALID); + DoPyCommand((char *)eap->arg, + (rangeinitializer) init_range_cmd, + (runner)run_do, + (void *)eap); } /****************************************************** @@ -1525,7 +1420,10 @@ FunctionGetattr(PyObject *self, char *na void do_pyeval (char_u *str, typval_T *rettv) { - DoPythonCommand(NULL, (char *) str, rettv); + DoPyCommand((char *) str, + (rangeinitializer) init_range_eval, + (runner) run_eval, + (void *) rettv); switch(rettv->v_type) { case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break; diff --git a/src/if_python3.c b/src/if_python3.c --- a/src/if_python3.c +++ b/src/if_python3.c @@ -703,8 +703,6 @@ static struct PyModuleDef vimmodule; * Internal function prototypes. */ -static PyObject *globals; - static int PythonIO_Init(void); static PyObject *Py3Init_vim(void); @@ -827,7 +825,7 @@ fail: * External interface */ static void -DoPy3Command(exarg_T *eap, const char *cmd, typval_T *rettv) +DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg) { #if defined(MACOS) && !defined(MACOS_X_UNIX) GrafPtr oldPort; @@ -848,16 +846,8 @@ DoPy3Command(exarg_T *eap, const char *c if (Python3_Init()) goto theend; - if (rettv == NULL) - { - RangeStart = eap->line1; - RangeEnd = eap->line2; - } - else - { - RangeStart = (PyInt) curwin->w_cursor.lnum; - RangeEnd = RangeStart; - } + init_range(arg); + Python_Release_Vim(); /* leave vim */ #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) @@ -881,28 +871,8 @@ DoPy3Command(exarg_T *eap, const char *c (char *)ENC_OPT, CODEC_ERROR_HANDLER); cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", CODEC_ERROR_HANDLER); Py_XDECREF(cmdstr); - if (rettv == NULL) - PyRun_SimpleString(PyBytes_AsString(cmdbytes)); - else - { - PyObject *r; - r = PyRun_String(PyBytes_AsString(cmdbytes), Py_eval_input, - globals, globals); - if (r == NULL) - { - if (PyErr_Occurred() && !msg_silent) - PyErr_PrintEx(0); - EMSG(_("E860: Eval did not return a valid python 3 object")); - } - else - { - if (ConvertFromPyObject(r, rettv) == -1) - EMSG(_("E861: Failed to convert returned python 3 object to vim value")); - Py_DECREF(r); - } - PyErr_Clear(); - } + run(PyBytes_AsString(cmdbytes), arg, &pygilstate); Py_XDECREF(cmdbytes); PyGILState_Release(pygilstate); @@ -936,10 +906,10 @@ ex_py3(exarg_T *eap) script = script_get(eap, eap->arg); if (!eap->skip) { - if (script == NULL) - DoPy3Command(eap, (char *)eap->arg, NULL); - else - DoPy3Command(eap, (char *)script, NULL); + DoPyCommand(script == NULL ? (char *) eap->arg : (char *) script, + (rangeinitializer) init_range_cmd, + (runner) run_cmd, + (void *) eap); } vim_free(script); } @@ -1000,101 +970,19 @@ ex_py3file(exarg_T *eap) /* Execute the file */ - DoPy3Command(eap, buffer, NULL); + DoPyCommand(buffer, + (rangeinitializer) init_range_cmd, + (runner) run_cmd, + (void *) eap); } void ex_py3do(exarg_T *eap) { - linenr_T i; - const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n "; - const char *s = (const char *) eap->arg; - size_t len; - char *code; - int status; - PyObject *pyfunc, *pymain; - PyGILState_STATE pygilstate; - - if (Python3_Init()) - goto theend; - - if (u_save(eap->line1 - 1, eap->line2 + 1) != OK) - { - EMSG(_("cannot save undo information")); - return; - } - len = strlen(code_hdr) + strlen(s); - code = malloc(len + 1); - STRCPY(code, code_hdr); - STRNCAT(code, s, len + 1); - pygilstate = PyGILState_Ensure(); - status = PyRun_SimpleString(code); - vim_free(code); - if (status) - { - EMSG(_("failed to run the code")); - return; - } - status = 0; /* good */ - pymain = PyImport_AddModule("__main__"); - pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC); - PyGILState_Release(pygilstate); - - for (i = eap->line1; i <= eap->line2; i++) - { - const char *line; - PyObject *pyline, *pylinenr, *pyret, *pybytes; - - line = (char *)ml_get(i); - pygilstate = PyGILState_Ensure(); - pyline = PyUnicode_Decode(line, strlen(line), - (char *)ENC_OPT, CODEC_ERROR_HANDLER); - pylinenr = PyLong_FromLong(i); - pyret = PyObject_CallFunctionObjArgs(pyfunc, pyline, pylinenr, NULL); - Py_DECREF(pyline); - Py_DECREF(pylinenr); - if (!pyret) - { - PyErr_PrintEx(0); - PythonIO_Flush(); - status = 1; - goto out; - } - - if (pyret && pyret != Py_None) - { - if (!PyUnicode_Check(pyret)) - { - EMSG(_("E863: return value must be an instance of str")); - Py_XDECREF(pyret); - status = 1; - goto out; - } - pybytes = PyUnicode_AsEncodedString(pyret, - (char *)ENC_OPT, CODEC_ERROR_HANDLER); - ml_replace(i, (char_u *) PyBytes_AsString(pybytes), 1); - Py_DECREF(pybytes); - changed(); -#ifdef SYNTAX_HL - syn_changed(i); /* recompute syntax hl. for this line */ -#endif - } - Py_XDECREF(pyret); - PythonIO_Flush(); - PyGILState_Release(pygilstate); - } - pygilstate = PyGILState_Ensure(); -out: - Py_DECREF(pyfunc); - PyObject_SetAttrString(pymain, DOPY_FUNC, NULL); - PyGILState_Release(pygilstate); - if (status) - return; - check_cursor(); - update_curbuf(NOT_VALID); - -theend: - return; + DoPyCommand((char *)eap->arg, + (rangeinitializer)init_range_cmd, + (runner)run_do, + (void *)eap); } /****************************************************** @@ -1790,7 +1678,10 @@ LineToString(const char *str) void do_py3eval (char_u *str, typval_T *rettv) { - DoPy3Command(NULL, (char *) str, rettv); + DoPyCommand((char *) str, + (rangeinitializer) init_range_eval, + (runner) run_eval, + (void *) rettv); switch(rettv->v_type) { case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break; diff --git a/src/testdir/test87.ok b/src/testdir/test87.ok --- a/src/testdir/test87.ok +++ b/src/testdir/test87.ok @@ -59,10 +59,10 @@ ll:[1] ['c', 1] ['d', ['e']] 0.0 -"\0": Vim(let):E861: -{"\0": 1}: Vim(let):E861: +"\0": Vim(let):E859: +{"\0": 1}: Vim(let):E859: undefined_name: Vim(let):Trace -vim: Vim(let):E861: +vim: Vim(let):E859: [1] [1, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 1] Abc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 991, +/**/ 990, /**/ 989,