updated for version 7.0183
diff --git a/src/if_python.c b/src/if_python.c
index d58f7cf..c1b3bf8 100644
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -1082,35 +1082,137 @@
return result;
}
+/*
+ * Function to translate a typval_T into a PyObject; this will recursively
+ * translate lists/dictionaries into their Python equivalents.
+ *
+ * The depth parameter is too avoid infinite recursion, set it to 1 when
+ * you call VimToPython.
+ */
+ static PyObject *
+VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
+{
+ PyObject *result;
+ PyObject *newObj;
+ char ptrBuf[NUMBUFLEN];
+
+ /* Avoid infinite recursion */
+ if (depth > 100)
+ {
+ Py_INCREF(Py_None);
+ result = Py_None;
+ return result;
+ }
+
+ /* Check if we run into a recursive loop. The item must be in lookupDict
+ * then and we can use it again. */
+ sprintf(ptrBuf, "%ld", (long)our_tv);
+ result = PyDict_GetItemString(lookupDict, ptrBuf);
+ if (result != NULL)
+ Py_INCREF(result);
+ else if (our_tv->v_type == VAR_STRING)
+ {
+ result = Py_BuildValue("s", our_tv->vval.v_string);
+ PyDict_SetItemString(lookupDict, ptrBuf, result);
+ }
+ else if (our_tv->v_type == VAR_NUMBER)
+ {
+ char buf[NUMBUFLEN];
+
+ /* For backwards compatibility numbers are stored as strings. */
+ sprintf(buf, "%ld", (long)our_tv->vval.v_number);
+ result = Py_BuildValue("s", buf);
+ PyDict_SetItemString(lookupDict, ptrBuf, result);
+ }
+ else if (our_tv->v_type == VAR_LIST)
+ {
+ list_T *list = our_tv->vval.v_list;
+ listitem_T *curr;
+
+ result = PyList_New(0);
+ PyDict_SetItemString(lookupDict, ptrBuf, result);
+
+ if (list != NULL)
+ {
+ for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
+ {
+ newObj = VimToPython(&curr->li_tv, depth + 1, lookupDict);
+ PyList_Append(result, newObj);
+ Py_DECREF(newObj);
+ }
+ }
+ }
+ else if (our_tv->v_type == VAR_DICT)
+ {
+ result = PyDict_New();
+ PyDict_SetItemString(lookupDict, ptrBuf, result);
+
+ if (our_tv->vval.v_dict != NULL)
+ {
+ hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
+ int todo = ht->ht_used;
+ hashitem_T *hi;
+ dictitem_T *di;
+
+ for (hi = ht->ht_array; todo > 0; ++hi)
+ {
+ if (!HASHITEM_EMPTY(hi))
+ {
+ --todo;
+
+ di = dict_lookup(hi);
+ newObj = VimToPython(&di->di_tv, depth + 1, lookupDict);
+ PyDict_SetItemString(result, (char *)hi->hi_key, newObj);
+ Py_DECREF(newObj);
+ }
+ }
+ }
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+
+ return result;
+}
+
/*ARGSUSED*/
static PyObject *
VimEval(PyObject *self, PyObject *args)
{
#ifdef FEAT_EVAL
char *expr;
- char *str;
+ typval_T *our_tv;
PyObject *result;
+ PyObject *lookup_dict;
if (!PyArg_ParseTuple(args, "s", &expr))
return NULL;
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
- str = (char *)eval_to_string((char_u *)expr, NULL);
+ our_tv = eval_expr((char_u *)expr, NULL);
+
Python_Release_Vim();
Py_END_ALLOW_THREADS
- if (str == NULL)
+ if (our_tv == NULL)
{
PyErr_SetVim(_("invalid expression"));
return NULL;
}
- result = Py_BuildValue("s", str);
+ /* Convert the Vim type into a Python type. Create a dictionary that's
+ * used to check for recursive loops. */
+ lookup_dict = PyDict_New();
+ result = VimToPython(our_tv, 1, lookup_dict);
+ Py_DECREF(lookup_dict);
+
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
- vim_free(str);
+ free_tv(our_tv);
Python_Release_Vim();
Py_END_ALLOW_THREADS