1
0
forked from aniani/vim

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)
This commit is contained in:
Bram Moolenaar
2013-05-21 18:19:38 +02:00
parent b09d983c78
commit b52f4c02e6
5 changed files with 171 additions and 255 deletions

View File

@@ -30,6 +30,9 @@ typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
#define INVALID_WINDOW_VALUE ((win_T *)(-1)) #define INVALID_WINDOW_VALUE ((win_T *)(-1))
#define INVALID_TABPAGE_VALUE ((tabpage_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 *);
static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *); static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
static PyObject *WindowNew(win_T *, tabpage_T *); static PyObject *WindowNew(win_T *, tabpage_T *);
@@ -39,6 +42,8 @@ static PyObject *LineToString(const char *);
static PyInt RangeStart; static PyInt RangeStart;
static PyInt RangeEnd; static PyInt RangeEnd;
static PyObject *globals;
/* /*
* obtain a lock on the Vim data structures * obtain a lock on the Vim data structures
*/ */
@@ -1296,7 +1301,7 @@ FunctionDestructor(PyObject *self)
FunctionObject *this = (FunctionObject *) (self); FunctionObject *this = (FunctionObject *) (self);
func_unref(this->name); func_unref(this->name);
PyMem_Del(this->name); PyMem_Free(this->name);
DESTRUCTOR_FINISH(self); DESTRUCTOR_FINISH(self);
} }
@@ -3431,6 +3436,126 @@ CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
} }
} }
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 static void
set_ref_in_py(const int copyID) set_ref_in_py(const int copyID)
{ {

View File

@@ -659,8 +659,6 @@ static PyObject *FunctionGetattr(PyObject *, char *);
* Internal function prototypes. * Internal function prototypes.
*/ */
static PyObject *globals;
static void PythonIO_Flush(void); static void PythonIO_Flush(void);
static int PythonIO_Init(void); static int PythonIO_Init(void);
static int PythonMod_Init(void); static int PythonMod_Init(void);
@@ -828,7 +826,7 @@ fail:
* External interface * External interface
*/ */
static void 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 #ifndef PY_CAN_RECURSE
static int recursive = 0; static int recursive = 0;
@@ -861,16 +859,8 @@ DoPythonCommand(exarg_T *eap, const char *cmd, typval_T *rettv)
if (Python_Init()) if (Python_Init())
goto theend; goto theend;
if (rettv == NULL) init_range(arg);
{
RangeStart = eap->line1;
RangeEnd = eap->line2;
}
else
{
RangeStart = (PyInt) curwin->w_cursor.lnum;
RangeEnd = RangeStart;
}
Python_Release_Vim(); /* leave vim */ Python_Release_Vim(); /* leave vim */
#if defined(HAVE_LOCALE_H) || defined(X_LOCALE) #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
@@ -892,27 +882,7 @@ DoPythonCommand(exarg_T *eap, const char *cmd, typval_T *rettv)
Python_RestoreThread(); /* enter python */ Python_RestoreThread(); /* enter python */
#endif #endif
if (rettv == NULL) run((char *) cmd, arg, &pygilstate);
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();
}
#ifdef PY_CAN_RECURSE #ifdef PY_CAN_RECURSE
PyGILState_Release(pygilstate); PyGILState_Release(pygilstate);
@@ -952,10 +922,10 @@ ex_python(exarg_T *eap)
script = script_get(eap, eap->arg); script = script_get(eap, eap->arg);
if (!eap->skip) if (!eap->skip)
{ {
if (script == NULL) DoPyCommand(script == NULL ? (char *) eap->arg : (char *) script,
DoPythonCommand(eap, (char *)eap->arg, NULL); (rangeinitializer) init_range_cmd,
else (runner) run_cmd,
DoPythonCommand(eap, (char *)script, NULL); (void *) eap);
} }
vim_free(script); vim_free(script);
} }
@@ -1001,94 +971,19 @@ ex_pyfile(exarg_T *eap)
*p++ = '\0'; *p++ = '\0';
/* Execute the file */ /* Execute the file */
DoPythonCommand(eap, buffer, NULL); DoPyCommand(buffer,
(rangeinitializer) init_range_cmd,
(runner) run_cmd,
(void *) eap);
} }
void void
ex_pydo(exarg_T *eap) ex_pydo(exarg_T *eap)
{ {
linenr_T i; DoPyCommand((char *)eap->arg,
const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n "; (rangeinitializer) init_range_cmd,
const char *s = (const char *) eap->arg; (runner)run_do,
size_t len; (void *)eap);
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);
} }
/****************************************************** /******************************************************
@@ -1525,7 +1420,10 @@ FunctionGetattr(PyObject *self, char *name)
void void
do_pyeval (char_u *str, typval_T *rettv) 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) switch(rettv->v_type)
{ {
case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break; case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break;

View File

@@ -703,8 +703,6 @@ static struct PyModuleDef vimmodule;
* Internal function prototypes. * Internal function prototypes.
*/ */
static PyObject *globals;
static int PythonIO_Init(void); static int PythonIO_Init(void);
static PyObject *Py3Init_vim(void); static PyObject *Py3Init_vim(void);
@@ -827,7 +825,7 @@ fail:
* External interface * External interface
*/ */
static void 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) #if defined(MACOS) && !defined(MACOS_X_UNIX)
GrafPtr oldPort; GrafPtr oldPort;
@@ -848,16 +846,8 @@ DoPy3Command(exarg_T *eap, const char *cmd, typval_T *rettv)
if (Python3_Init()) if (Python3_Init())
goto theend; goto theend;
if (rettv == NULL) init_range(arg);
{
RangeStart = eap->line1;
RangeEnd = eap->line2;
}
else
{
RangeStart = (PyInt) curwin->w_cursor.lnum;
RangeEnd = RangeStart;
}
Python_Release_Vim(); /* leave vim */ Python_Release_Vim(); /* leave vim */
#if defined(HAVE_LOCALE_H) || defined(X_LOCALE) #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
@@ -881,28 +871,8 @@ DoPy3Command(exarg_T *eap, const char *cmd, typval_T *rettv)
(char *)ENC_OPT, CODEC_ERROR_HANDLER); (char *)ENC_OPT, CODEC_ERROR_HANDLER);
cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", CODEC_ERROR_HANDLER); cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", CODEC_ERROR_HANDLER);
Py_XDECREF(cmdstr); Py_XDECREF(cmdstr);
if (rettv == NULL)
PyRun_SimpleString(PyBytes_AsString(cmdbytes));
else
{
PyObject *r;
r = PyRun_String(PyBytes_AsString(cmdbytes), Py_eval_input, run(PyBytes_AsString(cmdbytes), arg, &pygilstate);
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();
}
Py_XDECREF(cmdbytes); Py_XDECREF(cmdbytes);
PyGILState_Release(pygilstate); PyGILState_Release(pygilstate);
@@ -936,10 +906,10 @@ ex_py3(exarg_T *eap)
script = script_get(eap, eap->arg); script = script_get(eap, eap->arg);
if (!eap->skip) if (!eap->skip)
{ {
if (script == NULL) DoPyCommand(script == NULL ? (char *) eap->arg : (char *) script,
DoPy3Command(eap, (char *)eap->arg, NULL); (rangeinitializer) init_range_cmd,
else (runner) run_cmd,
DoPy3Command(eap, (char *)script, NULL); (void *) eap);
} }
vim_free(script); vim_free(script);
} }
@@ -1000,101 +970,19 @@ ex_py3file(exarg_T *eap)
/* Execute the file */ /* Execute the file */
DoPy3Command(eap, buffer, NULL); DoPyCommand(buffer,
(rangeinitializer) init_range_cmd,
(runner) run_cmd,
(void *) eap);
} }
void void
ex_py3do(exarg_T *eap) ex_py3do(exarg_T *eap)
{ {
linenr_T i; DoPyCommand((char *)eap->arg,
const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n "; (rangeinitializer)init_range_cmd,
const char *s = (const char *) eap->arg; (runner)run_do,
size_t len; (void *)eap);
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;
} }
/****************************************************** /******************************************************
@@ -1790,7 +1678,10 @@ LineToString(const char *str)
void void
do_py3eval (char_u *str, typval_T *rettv) 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) switch(rettv->v_type)
{ {
case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break; case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break;

View File

@@ -59,10 +59,10 @@ ll:[1]
['c', 1] ['c', 1]
['d', ['e']] ['d', ['e']]
0.0 0.0
"\0": Vim(let):E861: "\0": Vim(let):E859:
{"\0": 1}: Vim(let):E861: {"\0": 1}: Vim(let):E859:
undefined_name: Vim(let):Trace undefined_name: Vim(let):Trace
vim: Vim(let):E861: vim: Vim(let):E859:
[1] [1]
[1, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 1] [1, 10, 11, 10, 11, 10, 11, 10, 11, 10, 11, 10, 1]
Abc Abc

View File

@@ -728,6 +728,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
991,
/**/ /**/
990, 990,
/**/ /**/