diff options
author | Bram Moolenaar <Bram@vim.org> | 2012-06-29 12:54:53 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2012-06-29 12:54:53 +0200 |
commit | db91395312a02527ed973c8376d8e26e5b63ff53 (patch) | |
tree | 90f069389936dc2f2c8eb9ae8885ed68d1c336fb /src/if_py_both.h | |
parent | a7014df97532a4171276aa7e3b878e80e88e513c (diff) | |
download | vim-git-db91395312a02527ed973c8376d8e26e5b63ff53.tar.gz |
updated for version 7.3.569v7.3.569
Problem: Evaluating Vim expression in Python is insufficient.
Solution: Add vim.bindeval(). Also add pyeval() and py3eval(). (ZyX)
Diffstat (limited to 'src/if_py_both.h')
-rw-r--r-- | src/if_py_both.h | 1087 |
1 files changed, 1078 insertions, 9 deletions
diff --git a/src/if_py_both.h b/src/if_py_both.h index cbfbaa767..f627f67af 100644 --- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -1,4 +1,4 @@ -/* vi:set ts=8 sts=4 sw=4: +/* vi:set ts=8 sts=4 sw=4 noet: * * VIM - Vi IMproved by Bram Moolenaar * @@ -105,7 +105,8 @@ OutputWritelines(PyObject *self, PyObject *args) return NULL; Py_INCREF(list); - if (!PyList_Check(list)) { + if (!PyList_Check(list)) + { PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings")); Py_DECREF(list); return NULL; @@ -119,7 +120,8 @@ OutputWritelines(PyObject *self, PyObject *args) char *str = NULL; PyInt len; - if (!PyArg_Parse(line, "et#", ENC_OPT, &str, &len)) { + if (!PyArg_Parse(line, "et#", ENC_OPT, &str, &len)) + { PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings")); Py_DECREF(list); return NULL; @@ -297,7 +299,7 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict) { PyObject *result; PyObject *newObj; - char ptrBuf[NUMBUFLEN]; + char ptrBuf[sizeof(void *) * 2 + 3]; /* Avoid infinite recursion */ if (depth > 100) @@ -312,9 +314,9 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict) if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL) || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL)) { - sprintf(ptrBuf, PRINTF_DECIMAL_LONG_U, - our_tv->v_type == VAR_LIST ? (long_u)our_tv->vval.v_list - : (long_u)our_tv->vval.v_dict); + sprintf(ptrBuf, "%p", + our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list + : (void *)our_tv->vval.v_dict); result = PyDict_GetItemString(lookupDict, ptrBuf); if (result != NULL) { @@ -445,6 +447,57 @@ VimEval(PyObject *self UNUSED, PyObject *args UNUSED) #endif } +static PyObject *ConvertToPyObject(typval_T *); + + static PyObject * +VimEvalPy(PyObject *self UNUSED, PyObject *args UNUSED) +{ +#ifdef FEAT_EVAL + char *expr; + typval_T *our_tv; + PyObject *result; + + if (!PyArg_ParseTuple(args, "s", &expr)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + Python_Lock_Vim(); + our_tv = eval_expr((char_u *)expr, NULL); + + Python_Release_Vim(); + Py_END_ALLOW_THREADS + + if (our_tv == NULL) + { + PyErr_SetVim(_("invalid expression")); + return NULL; + } + + result = ConvertToPyObject(our_tv); + Py_BEGIN_ALLOW_THREADS + Python_Lock_Vim(); + free_tv(our_tv); + Python_Release_Vim(); + Py_END_ALLOW_THREADS + + return result; +#else + PyErr_SetVim(_("expressions disabled at compile time")); + return NULL; +#endif +} + + static PyObject * +VimStrwidth(PyObject *self UNUSED, PyObject *args) +{ + char *expr; + + if (!PyArg_ParseTuple(args, "s", &expr)) + return NULL; + + return PyLong_FromLong(mb_string2cells((char_u *)expr, STRLEN(expr))); +} + /* * Vim module - Definitions */ @@ -453,6 +506,8 @@ static struct PyMethodDef VimMethods[] = { /* name, function, calling, documentation */ {"command", VimCommand, 1, "Execute a Vim ex-mode command" }, {"eval", VimEval, 1, "Evaluate an expression using Vim evaluator" }, + {"bindeval", VimEvalPy, 1, "Like eval(), but returns objects attached to vim ones"}, + {"strwidth", VimStrwidth, 1, "Screen string width, counts <Tab> as having width 1"}, { NULL, NULL, 0, NULL } }; @@ -460,8 +515,7 @@ typedef struct { PyObject_HEAD buf_T *buf; -} -BufferObject; +} BufferObject; #define INVALID_BUFFER_VALUE ((buf_T *)(-1)) @@ -505,6 +559,768 @@ typedef struct win_T *win; } WindowObject; +static int ConvertFromPyObject(PyObject *, typval_T *); +static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *); + +typedef struct pylinkedlist_S { + struct pylinkedlist_S *pll_next; + struct pylinkedlist_S *pll_prev; + PyObject *pll_obj; +} pylinkedlist_T; + +static pylinkedlist_T *lastdict = NULL; +static pylinkedlist_T *lastlist = NULL; + + static void +pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last) +{ + if (ref->pll_prev == NULL) + { + if (ref->pll_next == NULL) + { + *last = NULL; + return; + } + } + else + ref->pll_prev->pll_next = ref->pll_next; + + if (ref->pll_next == NULL) + *last = ref->pll_prev; + else + ref->pll_next->pll_prev = ref->pll_prev; +} + + static void +pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last) +{ + if (*last == NULL) + ref->pll_prev = NULL; + else + { + (*last)->pll_next = ref; + ref->pll_prev = *last; + } + ref->pll_next = NULL; + ref->pll_obj = self; + *last = ref; +} + +static PyTypeObject DictionaryType; + +typedef struct +{ + PyObject_HEAD + dict_T *dict; + pylinkedlist_T ref; +} DictionaryObject; + + static PyObject * +DictionaryNew(dict_T *dict) +{ + DictionaryObject *self; + + self = PyObject_NEW(DictionaryObject, &DictionaryType); + if (self == NULL) + return NULL; + self->dict = dict; + ++dict->dv_refcount; + + pyll_add((PyObject *)(self), &self->ref, &lastdict); + + return (PyObject *)(self); +} + + static int +pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + dict_T *d; + char_u *key; + dictitem_T *di; + PyObject *keyObject; + PyObject *valObject; + Py_ssize_t iter = 0; + + d = dict_alloc(); + if (d == NULL) + { + PyErr_NoMemory(); + return -1; + } + + tv->v_type = VAR_DICT; + tv->vval.v_dict = d; + + while (PyDict_Next(obj, &iter, &keyObject, &valObject)) + { + DICTKEY_DECL + + if (keyObject == NULL) + return -1; + if (valObject == NULL) + return -1; + + DICTKEY_GET(-1) + + di = dictitem_alloc(key); + + DICTKEY_UNREF + + if (di == NULL) + { + PyErr_NoMemory(); + return -1; + } + di->di_tv.v_lock = 0; + + if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1) + { + vim_free(di); + return -1; + } + if (dict_add(d, di) == FAIL) + { + vim_free(di); + PyErr_SetVim(_("failed to add key to dictionary")); + return -1; + } + } + return 0; +} + + static int +pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + dict_T *d; + char_u *key; + dictitem_T *di; + PyObject *list; + PyObject *litem; + PyObject *keyObject; + PyObject *valObject; + Py_ssize_t lsize; + + d = dict_alloc(); + if (d == NULL) + { + PyErr_NoMemory(); + return -1; + } + + tv->v_type = VAR_DICT; + tv->vval.v_dict = d; + + list = PyMapping_Items(obj); + lsize = PyList_Size(list); + while (lsize--) + { + DICTKEY_DECL + + litem = PyList_GetItem(list, lsize); + if (litem == NULL) + { + Py_DECREF(list); + return -1; + } + + keyObject = PyTuple_GetItem(litem, 0); + if (keyObject == NULL) + { + Py_DECREF(list); + Py_DECREF(litem); + return -1; + } + + DICTKEY_GET(-1) + + valObject = PyTuple_GetItem(litem, 1); + if (valObject == NULL) + { + Py_DECREF(list); + Py_DECREF(litem); + return -1; + } + + di = dictitem_alloc(key); + + DICTKEY_UNREF + + if (di == NULL) + { + Py_DECREF(list); + Py_DECREF(litem); + PyErr_NoMemory(); + return -1; + } + di->di_tv.v_lock = 0; + + if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1) + { + vim_free(di); + Py_DECREF(list); + Py_DECREF(litem); + return -1; + } + if (dict_add(d, di) == FAIL) + { + vim_free(di); + Py_DECREF(list); + Py_DECREF(litem); + PyErr_SetVim(_("failed to add key to dictionary")); + return -1; + } + Py_DECREF(litem); + } + Py_DECREF(list); + return 0; +} + + static PyInt +DictionaryLength(PyObject *self) +{ + return ((PyInt) ((((DictionaryObject *)(self))->dict->dv_hashtab.ht_used))); +} + + static PyObject * +DictionaryItem(PyObject *self, PyObject *keyObject) +{ + char_u *key; + dictitem_T *val; + DICTKEY_DECL + + DICTKEY_GET(NULL) + + val = dict_find(((DictionaryObject *) (self))->dict, key, -1); + + DICTKEY_UNREF + + return ConvertToPyObject(&val->di_tv); +} + + static PyInt +DictionaryAssItem(PyObject *self, PyObject *keyObject, PyObject *valObject) +{ + char_u *key; + typval_T tv; + dict_T *d = ((DictionaryObject *)(self))->dict; + dictitem_T *di; + DICTKEY_DECL + + if (d->dv_lock) + { + PyErr_SetVim(_("dict is locked")); + return -1; + } + + DICTKEY_GET(-1) + + di = dict_find(d, key, -1); + + if (valObject == NULL) + { + if (di == NULL) + { + PyErr_SetString(PyExc_IndexError, _("no such key in dictionary")); + return -1; + } + hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key); + hash_remove(&d->dv_hashtab, hi); + dictitem_free(di); + return 0; + } + + if (ConvertFromPyObject(valObject, &tv) == -1) + { + return -1; + } + + if (di == NULL) + { + di = dictitem_alloc(key); + if (di == NULL) + { + PyErr_NoMemory(); + return -1; + } + di->di_tv.v_lock = 0; + + if (dict_add(d, di) == FAIL) + { + vim_free(di); + PyErr_SetVim(_("failed to add key to dictionary")); + return -1; + } + } + else + clear_tv(&di->di_tv); + + DICTKEY_UNREF + + copy_tv(&tv, &di->di_tv); + return 0; +} + + static PyObject * +DictionaryListKeys(PyObject *self) +{ + dict_T *dict = ((DictionaryObject *)(self))->dict; + long_u todo = dict->dv_hashtab.ht_used; + Py_ssize_t i = 0; + PyObject *r; + hashitem_T *hi; + + r = PyList_New(todo); + for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi) + { + if (!HASHITEM_EMPTY(hi)) + { + PyList_SetItem(r, i, PyBytes_FromString((char *)(hi->hi_key))); + --todo; + ++i; + } + } + return r; +} + +static struct PyMethodDef DictionaryMethods[] = { + {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL } +}; + +static PyTypeObject ListType; + +typedef struct +{ + PyObject_HEAD + list_T *list; + pylinkedlist_T ref; +} ListObject; + + static PyObject * +ListNew(list_T *list) +{ + ListObject *self; + + self = PyObject_NEW(ListObject, &ListType); + if (self == NULL) + return NULL; + self->list = list; + ++list->lv_refcount; + + pyll_add((PyObject *)(self), &self->ref, &lastlist); + + return (PyObject *)(self); +} + + static int +list_py_concat(list_T *l, PyObject *obj, PyObject *lookupDict) +{ + Py_ssize_t i; + Py_ssize_t lsize = PySequence_Size(obj); + PyObject *litem; + listitem_T *li; + + for(i=0; i<lsize; i++) + { + li = listitem_alloc(); + if (li == NULL) + { + PyErr_NoMemory(); + return -1; + } + li->li_tv.v_lock = 0; + + litem = PySequence_GetItem(obj, i); + if (litem == NULL) + return -1; + if (_ConvertFromPyObject(litem, &li->li_tv, lookupDict) == -1) + return -1; + + list_append(l, li); + } + return 0; +} + + static int +pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + list_T *l; + + l = list_alloc(); + if (l == NULL) + { + PyErr_NoMemory(); + return -1; + } + + tv->v_type = VAR_LIST; + tv->vval.v_list = l; + + if (list_py_concat(l, obj, lookupDict) == -1) + return -1; + + return 0; +} + + static int +pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + PyObject *iterator = PyObject_GetIter(obj); + PyObject *item; + list_T *l; + listitem_T *li; + + l = list_alloc(); + + if (l == NULL) + { + PyErr_NoMemory(); + return -1; + } + + tv->vval.v_list = l; + tv->v_type = VAR_LIST; + + + if (iterator == NULL) + return -1; + + while ((item = PyIter_Next(obj))) + { + li = listitem_alloc(); + if (li == NULL) + { + PyErr_NoMemory(); + return -1; + } + li->li_tv.v_lock = 0; + + if (_ConvertFromPyObject(item, &li->li_tv, lookupDict) == -1) + return -1; + + list_append(l, li); + + Py_DECREF(item); + } + + Py_DECREF(iterator); + return 0; +} + + static PyInt +ListLength(PyObject *self) +{ + return ((PyInt) (((ListObject *) (self))->list->lv_len)); +} + + static PyObject * +ListItem(PyObject *self, Py_ssize_t index) +{ + listitem_T *li; + + if (index>=ListLength(self)) + { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + li = list_find(((ListObject *) (self))->list, (long) index); + if (li == NULL) + { + PyErr_SetVim(_("internal error: failed to get vim list item")); + return NULL; + } + return ConvertToPyObject(&li->li_tv); +} + +#define PROC_RANGE \ + if (last < 0) {\ + if (last < -size) \ + last = 0; \ + else \ + last += size; \ + } \ + if (first < 0) \ + first = 0; \ + if (first > size) \ + first = size; \ + if (last > size) \ + last = size; + + static PyObject * +ListSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last) +{ + PyInt i; + PyInt size = ListLength(self); + PyInt n; + PyObject *list; + int reversed = 0; + + PROC_RANGE + if (first >= last) + first = last; + + n = last-first; + list = PyList_New(n); + if (list == NULL) + return NULL; + + for (i = 0; i < n; ++i) + { + PyObject *item = ListItem(self, i); + if (item == NULL) + { + Py_DECREF(list); + return NULL; + } + + if ((PyList_SetItem(list, ((reversed)?(n-i-1):(i)), item))) + { + Py_DECREF(item); + Py_DECREF(list); + return NULL; + } + } + + return list; +} + + static int +ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj) +{ + typval_T tv; + list_T *l = ((ListObject *) (self))->list; + listitem_T *li; + Py_ssize_t length = ListLength(self); + + if (l->lv_lock) + { + PyErr_SetVim(_("list is locked")); + return -1; + } + if (index>length || (index==length && obj==NULL)) + { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return -1; + } + + if (obj == NULL) + { + li = list_find(l, (long) index); + list_remove(l, li, li); + clear_tv(&li->li_tv); + vim_free(li); + return 0; + } + + if (ConvertFromPyObject(obj, &tv) == -1) + return -1; + + if (index == length) + { + if (list_append_tv(l, &tv) == FAIL) + { + PyErr_SetVim(_("Failed to add item to list")); + return -1; + } + } + else + { + li = list_find(l, (long) index); + clear_tv(&li->li_tv); + copy_tv(&tv, &li->li_tv); + } + return 0; +} + + static int +ListAssSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj) +{ + PyInt size = ListLength(self); + Py_ssize_t i; + Py_ssize_t lsize; + PyObject *litem; + listitem_T *li; + listitem_T *next; + typval_T v; + list_T *l = ((ListObject *) (self))->list; + + if (l->lv_lock) + { + PyErr_SetVim(_("list is locked")); + return -1; + } + + PROC_RANGE + + if (first == size) + li = NULL; + else + { + li = list_find(l, (long) first); + if (li == NULL) + { + PyErr_SetVim(_("internal error: no vim list item")); + return -1; + } + if (last > first) + { + i = last - first; + while (i-- && li != NULL) + { + next = li->li_next; + listitem_remove(l, li); + li = next; + } + } + } + + if (obj == NULL) + return 0; + + if (!PyList_Check(obj)) + { + PyErr_SetString(PyExc_TypeError, _("can only assign lists to slice")); + return -1; + } + + lsize = PyList_Size(obj); + + for(i=0; i<lsize; i++) + { + litem = PyList_GetItem(obj, i); + if (litem == NULL) + return -1; + if (ConvertFromPyObject(litem, &v) == -1) + return -1; + if (list_insert_tv(l, &v, li) == FAIL) + { + PyErr_SetVim(_("internal error: failed to add item to list")); + return -1; + } + } + return 0; +} + + static PyObject * +ListConcatInPlace(PyObject *self, PyObject *obj) +{ + list_T *l = ((ListObject *) (self))->list; + PyObject *lookup_dict; + + if (l->lv_lock) + { + PyErr_SetVim(_("list is locked")); + return NULL; + } + + if (!PySequence_Check(obj)) + { + PyErr_SetString(PyExc_TypeError, _("can only concatenate with lists")); + return NULL; + } + + lookup_dict = PyDict_New(); + if (list_py_concat(l, obj, lookup_dict) == -1) + { + Py_DECREF(lookup_dict); + return NULL; + } + Py_DECREF(lookup_dict); + + Py_INCREF(self); + return self; +} + +static struct PyMethodDef ListMethods[] = { + {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""}, + { NULL, NULL, 0, NULL } +}; + +typedef struct +{ + PyObject_HEAD + char_u *name; +} FunctionObject; + +static PyTypeObject FunctionType; + + static PyObject * +FunctionNew(char_u *name) +{ + FunctionObject *self; + + self = PyObject_NEW(FunctionObject, &FunctionType); + if (self == NULL) + return NULL; + self->name = PyMem_New(char_u, STRLEN(name) + 1); + if (self->name == NULL) + { + PyErr_NoMemory(); + return NULL; + } + STRCPY(self->name, name); + func_ref(name); + return (PyObject *)(self); +} + + static PyObject * +FunctionCall(PyObject *self, PyObject *argsObject, PyObject *kwargs) +{ + FunctionObject *this = (FunctionObject *)(self); + char_u *name = this->name; + typval_T args; + typval_T selfdicttv; + typval_T rettv; + dict_T *selfdict = NULL; + PyObject *selfdictObject; + PyObject *result; + int error; + + if (ConvertFromPyObject(argsObject, &args) == -1) + return NULL; + + if (kwargs != NULL) + { + selfdictObject = PyDict_GetItemString(kwargs, "self"); + if (selfdictObject != NULL) + { + if (!PyDict_Check(selfdictObject)) + { + PyErr_SetString(PyExc_TypeError, _("'self' argument must be a dictionary")); + clear_tv(&args); + return NULL; + } + if (ConvertFromPyObject(selfdictObject, &selfdicttv) == -1) + return NULL; + selfdict = selfdicttv.vval.v_dict; + } + } + + error = func_call(name, &args, selfdict, &rettv); + if (error != OK) + { + result = NULL; + PyErr_SetVim(_("failed to run function")); + } + else + result = ConvertToPyObject(&rettv); + + /* FIXME Check what should really be cleared. */ + clear_tv(&args); + clear_tv(&rettv); + /* + * if (selfdict!=NULL) + * clear_tv(selfdicttv); + */ + + return result; +} + +static struct PyMethodDef FunctionMethods[] = { + {"__call__", (PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""}, + { NULL, NULL, 0, NULL } +}; + #define INVALID_WINDOW_VALUE ((win_T *)(-1)) static int @@ -1567,3 +2383,256 @@ static struct PyMethodDef RangeMethods[] = { { NULL, NULL, 0, NULL } }; + static void +set_ref_in_py(const int copyID) +{ + pylinkedlist_T *cur; + dict_T *dd; + list_T *ll; + + if (lastdict != NULL) + for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev) + { + dd = ((DictionaryObject *) (cur->pll_obj))->dict; + if (dd->dv_copyID != copyID) + { + dd->dv_copyID = copyID; + set_ref_in_ht(&dd->dv_hashtab, copyID); + } + } + + if (lastlist != NULL) + for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev) + { + ll = ((ListObject *) (cur->pll_obj))->list; + if (ll->lv_copyID != copyID) + { + ll->lv_copyID = copyID; + set_ref_in_list(ll, copyID); + } + } +} + + static int +set_string_copy(char_u *str, typval_T *tv) +{ + tv->vval.v_string = vim_strsave(str); + if (tv->vval.v_string == NULL) + { + PyErr_NoMemory(); + return -1; + } + return 0; +} + +#ifdef FEAT_EVAL +typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *); + + static int +convert_dl(PyObject *obj, typval_T *tv, + pytotvfunc py_to_tv, PyObject *lookupDict) +{ + PyObject *capsule; + char hexBuf[sizeof(void *) * 2 + 3]; + + sprintf(hexBuf, "%p", obj); + + capsule = PyDict_GetItemString(lookupDict, hexBuf); + if (capsule == NULL) + { + capsule = PyCapsule_New(tv, NULL, NULL); + PyDict_SetItemString(lookupDict, hexBuf, capsule); + Py_DECREF(capsule); + if (py_to_tv(obj, tv, lookupDict) == -1) + { + tv->v_type = VAR_UNKNOWN; + return -1; + } + /* As we are not using copy_tv which increments reference count we must + * do it ourself. */ + switch(tv->v_type) + { + case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break; + case VAR_LIST: ++tv->vval.v_list->lv_refcount; break; + } + } + else + { + typval_T *v = PyCapsule_GetPointer(capsule, NULL); + copy_tv(v, tv); + } + return 0; +} + + static int +ConvertFromPyObject(PyObject *obj, typval_T *tv) +{ + PyObject *lookup_dict; + int r; + + lookup_dict = PyDict_New(); + r = _ConvertFromPyObject(obj, tv, lookup_dict); + Py_DECREF(lookup_dict); + return r; +} + + static int +_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + if (obj->ob_type == &DictionaryType) + { + tv->v_type = VAR_DICT; + tv->vval.v_dict = (((DictionaryObject *)(obj))->dict); + ++tv->vval.v_dict->dv_refcount; + } + else if (obj->ob_type == &ListType) + { + tv->v_type = VAR_LIST; + tv->vval.v_list = (((ListObject *)(obj))->list); + ++tv->vval.v_list->lv_refcount; + } + else if (obj->ob_type == &FunctionType) + { + if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1) + return -1; + + tv->v_type = VAR_FUNC; + func_ref(tv->vval.v_string); + } +#if PY_MAJOR_VERSION >= 3 + else if (PyBytes_Check(obj)) + { + char_u *result = (char_u *) PyBytes_AsString(obj); + + if (result == NULL) + return -1; + + if (set_string_copy(result, tv) == -1) + return -1; + + tv->v_type = VAR_STRING; + } + else if (PyUnicode_Check(obj)) + { + PyObject *bytes; + char_u *result; + + bytes = PyString_AsBytes(obj); + if (bytes == NULL) + return -1; + + result = (char_u *) PyBytes_AsString(bytes); + if (result == NULL) + return -1; + + if (set_string_copy(result, tv) == -1) + { + Py_XDECREF(bytes); + return -1; + } + Py_XDECREF(bytes); + + tv->v_type = VAR_STRING; + } +#else + else if (PyUnicode_Check(obj)) + { + PyObject *bytes; + char_u *result; + + bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL); + if (bytes == NULL) + return -1; + + result=(char_u *) PyString_AsString(bytes); + if (result == NULL) + return -1; + + if (set_string_copy(result, tv) == -1) + { + Py_XDECREF(bytes); + return -1; + } + Py_XDECREF(bytes); + + tv->v_type = VAR_STRING; + } + else if (PyString_Check(obj)) + { + char_u *result = (char_u *) PyString_AsString(obj); + + if (result == NULL) + return -1; + + if (set_string_copy(result, tv) == -1) + return -1; + + tv->v_type = VAR_STRING; + } + else if (PyInt_Check(obj)) + { + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj); + } +#endif + else if (PyLong_Check(obj)) + { + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj); + } + else if (PyDict_Check(obj)) + return convert_dl(obj, tv, pydict_to_tv, lookupDict); +#ifdef FEAT_FLOAT + else if (PyFloat_Check(obj)) + { + tv->v_type = VAR_FLOAT; + tv->vval.v_float = (float_T) PyFloat_AsDouble(obj); + } +#endif + else if (PyIter_Check(obj)) + return convert_dl(obj, tv, pyiter_to_tv, lookupDict); + else if (PySequence_Check(obj)) + return convert_dl(obj, tv, pyseq_to_tv, lookupDict); + else if (PyMapping_Check(obj)) + return convert_dl(obj, tv, pymap_to_tv, lookupDict); + else + { + PyErr_SetString(PyExc_TypeError, _("unable to convert to vim structure")); + return -1; + } + return 0; +} + + static PyObject * +ConvertToPyObject(typval_T *tv) +{ + if (tv == NULL) + { + PyErr_SetVim(_("NULL reference passed")); + return NULL; + } + switch (tv->v_type) + { + case VAR_STRING: + return PyBytes_FromString((char *) tv->vval.v_string); + case VAR_NUMBER: + return PyLong_FromLong((long) tv->vval.v_number); +#ifdef FEAT_FLOAT + case VAR_FLOAT: + return PyFloat_FromDouble((double) tv->vval.v_float); +#endif + case VAR_LIST: + return ListNew(tv->vval.v_list); + case VAR_DICT: + return DictionaryNew(tv->vval.v_dict); + case VAR_FUNC: + return FunctionNew(tv->vval.v_string); + case VAR_UNKNOWN: + Py_INCREF(Py_None); + return Py_None; + default: + PyErr_SetVim(_("internal error: invalid value type")); + return NULL; + } +} +#endif |