blob: ed66254ff3bca1a540dcb160a2b3f4f09b159899 [file] [log] [blame]
Bram Moolenaardb913952012-06-29 12:54:53 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar170bf1a2010-07-24 23:51:45 +02002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020010 * Python extensions by Paul Moore, David Leonard, Roland Puntaier, Nikolay
11 * Pavlov.
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020012 *
13 * Common code for if_python.c and if_python3.c.
14 */
15
Bram Moolenaarc1a995d2012-08-08 16:05:07 +020016#if PY_VERSION_HEX < 0x02050000
Bram Moolenaar9bf703d2019-11-30 19:44:38 +010017typedef int Py_ssize_t; // Python 2.4 and earlier don't have this type.
Bram Moolenaarc1a995d2012-08-08 16:05:07 +020018#endif
19
Bram Moolenaard518f952020-01-01 15:04:17 +010020// Use values that are known to work, others may make Vim crash.
21#define ENC_OPT (enc_utf8 ? "utf-8" : enc_dbcs ? "euc-jp" : (char *)p_enc)
Bram Moolenaard620aa92013-05-17 16:40:06 +020022#define DOPY_FUNC "_vim_pydo"
Bram Moolenaar91805fc2011-06-26 04:01:44 +020023
Bram Moolenaarc09a6d62013-06-10 21:27:29 +020024static const char *vim_special_path = "_vim_path_";
25
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020026#define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020027#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020028#define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str)
Bram Moolenaar063a46b2014-01-14 16:36:51 +010029#define PyErr_FORMAT(exc, str, arg) PyErr_Format(exc, _(str), arg)
30#define PyErr_FORMAT2(exc, str, arg1, arg2) PyErr_Format(exc, _(str), arg1,arg2)
31#define PyErr_VIM_FORMAT(str, arg) PyErr_FORMAT(VimError, str, arg)
Bram Moolenaarc476e522013-06-23 13:46:40 +020032
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +020033#ifdef USE_LIMITED_API
34// Limited Python API. Need to call only exposed functions and remap macros.
35// PyTypeObject is an opaque struct.
36
37typedef struct {
38 lenfunc sq_length;
39 binaryfunc sq_concat;
40 ssizeargfunc sq_repeat;
41 ssizeargfunc sq_item;
42 void *was_sq_slice;
43 ssizeobjargproc sq_ass_item;
44 void *was_sq_ass_slice;
45 objobjproc sq_contains;
46
47 binaryfunc sq_inplace_concat;
48 ssizeargfunc sq_inplace_repeat;
49} PySequenceMethods;
50
51typedef struct {
52 lenfunc mp_length;
53 binaryfunc mp_subscript;
54 objobjargproc mp_ass_subscript;
55} PyMappingMethods;
56
57// This struct emulates the concrete _typeobject struct to allow the code to
58// work the same way in both limited and full Python APIs.
59struct typeobject_wrapper {
60 const char *tp_name;
61 Py_ssize_t tp_basicsize;
62 unsigned long tp_flags;
63
64 // When adding new slots below, also need to make sure we add ADD_TP_SLOT
65 // call in AddHeapType for it.
66
67 destructor tp_dealloc;
68 reprfunc tp_repr;
69
70 PySequenceMethods *tp_as_sequence;
71 PyMappingMethods *tp_as_mapping;
72
73 ternaryfunc tp_call;
74 getattrofunc tp_getattro;
75 setattrofunc tp_setattro;
76
77 const char *tp_doc;
78
79 traverseproc tp_traverse;
80
81 inquiry tp_clear;
82
83 getiterfunc tp_iter;
84 iternextfunc tp_iternext;
85
86 struct PyMethodDef *tp_methods;
87 struct _typeobject *tp_base;
88 allocfunc tp_alloc;
89 newfunc tp_new;
90 freefunc tp_free;
91};
92
93# define DEFINE_PY_TYPE_OBJECT(type) \
94 static struct typeobject_wrapper type; \
95 static PyTypeObject* type##Ptr = NULL
96
97// PyObject_HEAD_INIT_TYPE and PyObject_FINISH_INIT_TYPE need to come in pairs
98// We first initialize with NULL because the type is not allocated until
99// init_types() is called later. It's in FINISH_INIT_TYPE where we fill the
100// type in with the newly allocated type.
101# define PyObject_HEAD_INIT_TYPE(type) PyObject_HEAD_INIT(NULL)
102# define PyObject_FINISH_INIT_TYPE(obj, type) obj.ob_base.ob_type = type##Ptr
103
104# define Py_TYPE_GET_TP_ALLOC(type) ((allocfunc)PyType_GetSlot(type, Py_tp_alloc))
105# define Py_TYPE_GET_TP_METHODS(type) ((PyMethodDef *)PyType_GetSlot(type, Py_tp_methods))
106
107// PyObject_NEW is not part of stable ABI, but PyObject_Malloc/Init are.
Yee Cheng Chinf7f746b2023-09-30 12:28:50 +0200108static PyObject* Vim_PyObject_New(PyTypeObject *type, size_t objsize)
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200109{
110 PyObject *obj = (PyObject *)PyObject_Malloc(objsize);
111 if (obj == NULL)
Yegappan Lakshmanand4e4ecb2023-08-27 18:35:45 +0200112 return PyErr_NoMemory();
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200113 return PyObject_Init(obj, type);
114}
115# undef PyObject_NEW
116# define PyObject_NEW(type, typeobj) ((type *)Vim_PyObject_New(typeobj, sizeof(type)))
117
118// This is a somewhat convoluted because limited API doesn't expose an easy way
119// to get the tp_name field, and so we have to manually reconstruct it as
120// "__module__.__name__" (with __module__ omitted for builtins to emulate
121// Python behavior). Also, some of the more convenient functions like
122// PyUnicode_AsUTF8AndSize and PyType_GetQualName() are not available until
123// late Python 3 versions, and won't be available if you set Py_LIMITED_API too
124// low.
125# define PyErr_FORMAT_TYPE(msg, obj) \
126 do { \
127 PyObject* qualname = PyObject_GetAttrString((PyObject*)(obj)->ob_type, "__qualname__"); \
128 if (qualname == NULL) \
129 { \
130 PyErr_FORMAT(PyExc_TypeError, msg, "(NULL)"); \
131 break; \
132 } \
133 PyObject* module = PyObject_GetAttrString((PyObject*)(obj)->ob_type, "__module__"); \
134 PyObject* full; \
135 if (module == NULL || PyUnicode_CompareWithASCIIString(module, "builtins") == 0 \
136 || PyUnicode_CompareWithASCIIString(module, "__main__") == 0) \
137 { \
138 full = qualname; \
139 Py_INCREF(full); \
140 } \
141 else \
142 full = PyUnicode_FromFormat("%U.%U", module, qualname); \
143 PyObject* full_bytes = PyUnicode_AsUTF8String(full); \
144 const char* full_str = PyBytes_AsString(full_bytes); \
145 full_str = full_str == NULL ? "(NULL)" : full_str; \
146 PyErr_FORMAT(PyExc_TypeError, msg, full_str); \
147 Py_DECREF(qualname); \
148 Py_XDECREF(module); \
149 Py_XDECREF(full); \
150 Py_XDECREF(full_bytes); \
Christian Brabandt75dc1ed2023-08-20 23:19:24 +0200151 } while (0)
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200152
153# define PyList_GET_ITEM(list, i) PyList_GetItem(list, i)
154# define PyList_GET_SIZE(o) PyList_Size(o)
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200155
156// PyList_SET_ITEM and PyList_SetItem have slightly different behaviors. The
157// former will leave the old item dangling, and the latter will decref on it.
158// Since we only use this on new lists, this difference doesn't matter.
159# define PyList_SET_ITEM(list, i, item) PyList_SetItem(list, i, item)
160
Yegappan Lakshmanan038be272025-03-26 18:46:21 +0100161# define PyTuple_GET_ITEM(o, pos) PyTuple_GetItem(o, pos)
162# define PyTuple_GET_SIZE(o) PyTuple_Size(o)
163
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200164# if Py_LIMITED_API < 0x03080000
165// PyIter_check only became part of stable ABI in 3.8, and there is no easy way
166// to check for it in the API. We simply return false as a compromise. This
167// does mean we should avoid compiling with stable ABI < 3.8.
168# undef PyIter_Check
169# define PyIter_Check(obj) (FALSE)
170# endif
171
Yee Cheng Chinf7f746b2023-09-30 12:28:50 +0200172static PyTypeObject* AddHeapType(struct typeobject_wrapper* type_object)
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200173{
174 PyType_Spec type_spec;
175 type_spec.name = type_object->tp_name;
176 type_spec.basicsize = type_object->tp_basicsize;
177 type_spec.itemsize = 0;
178 type_spec.flags = type_object->tp_flags;
179
180 // We just need to statically allocate a large enough buffer that can hold
181 // all slots. We need to leave a null-terminated slot at the end.
182 PyType_Slot slots[40] = { {0, NULL} };
183 size_t slot_i = 0;
184
185# define ADD_TP_SLOT(slot_name) \
186 if (slot_i >= 40) return NULL; /* this should never happen */ \
187 if (type_object->slot_name != NULL) \
188 { \
189 slots[slot_i].slot = Py_##slot_name; \
190 slots[slot_i].pfunc = (void*)type_object->slot_name; \
191 ++slot_i; \
192 }
193# define ADD_TP_SUB_SLOT(sub_slot, slot_name) \
194 if (slot_i >= 40) return NULL; /* this should never happen */ \
195 if (type_object->sub_slot != NULL && type_object->sub_slot->slot_name != NULL) \
196 { \
197 slots[slot_i].slot = Py_##slot_name; \
198 slots[slot_i].pfunc = (void*)type_object->sub_slot->slot_name; \
199 ++slot_i; \
200 }
201
202 ADD_TP_SLOT(tp_dealloc)
203 ADD_TP_SLOT(tp_repr)
204 ADD_TP_SLOT(tp_call)
205 ADD_TP_SLOT(tp_getattro)
206 ADD_TP_SLOT(tp_setattro)
207 ADD_TP_SLOT(tp_doc)
208 ADD_TP_SLOT(tp_traverse)
209 ADD_TP_SLOT(tp_clear)
210 ADD_TP_SLOT(tp_iter)
211 ADD_TP_SLOT(tp_iternext)
212 ADD_TP_SLOT(tp_methods)
213 ADD_TP_SLOT(tp_base)
214 ADD_TP_SLOT(tp_alloc)
215 ADD_TP_SLOT(tp_new)
216 ADD_TP_SLOT(tp_free)
217
218 ADD_TP_SUB_SLOT(tp_as_sequence, sq_length)
219 ADD_TP_SUB_SLOT(tp_as_sequence, sq_concat)
220 ADD_TP_SUB_SLOT(tp_as_sequence, sq_repeat)
221 ADD_TP_SUB_SLOT(tp_as_sequence, sq_item)
222 ADD_TP_SUB_SLOT(tp_as_sequence, sq_ass_item)
223 ADD_TP_SUB_SLOT(tp_as_sequence, sq_contains)
224 ADD_TP_SUB_SLOT(tp_as_sequence, sq_inplace_concat)
225 ADD_TP_SUB_SLOT(tp_as_sequence, sq_inplace_repeat)
226
227 ADD_TP_SUB_SLOT(tp_as_mapping, mp_length)
228 ADD_TP_SUB_SLOT(tp_as_mapping, mp_subscript)
229 ADD_TP_SUB_SLOT(tp_as_mapping, mp_ass_subscript)
230# undef ADD_TP_SLOT
231# undef ADD_TP_SUB_SLOT
232
233 type_spec.slots = slots;
234
235 PyObject* newtype = PyType_FromSpec(&type_spec);
236 return (PyTypeObject*)newtype;
237}
238
239// Add a heap type, since static types do not work in limited API
240// Each PYTYPE_READY is paired with PYTYPE_CLEANUP.
241//
242// Note that we don't call Py_DECREF(type##Ptr) in clean up. The reason for
243// that in 3.7, it's possible to de-allocate a heap type before all instances
244// are cleared, leading to a crash, whereas in 3.8 the semantics were changed
245// and instances hold strong references to types. Since these types are
246// designed to be static, just keep them around to avoid having to write
247// version-specific handling. Vim does not re-start the Python runtime so there
248// will be no long-term leak.
249# define PYTYPE_READY(type) \
250 type##Ptr = AddHeapType(&(type)); \
251 if (type##Ptr == NULL) \
252 return -1;
253# define PYTYPE_CLEANUP(type) \
254 type##Ptr = NULL;
255
256// Limited API does not provide PyRun_* functions. Need to implement manually
257// using PyCompile and PyEval.
Yee Cheng Chinf7f746b2023-09-30 12:28:50 +0200258static PyObject* Vim_PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200259{
260 // Just pass "" for filename for now.
261 PyObject* compiled = Py_CompileString(str, "", start);
262 if (compiled == NULL)
263 return NULL;
264
265 PyObject* eval_result = PyEval_EvalCode(compiled, globals, locals);
266 Py_DECREF(compiled);
267 return eval_result;
268}
Yee Cheng Chinf7f746b2023-09-30 12:28:50 +0200269static int Vim_PyRun_SimpleString(const char *str)
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200270{
271 // This function emulates CPython's implementation.
272 PyObject* m = PyImport_AddModule("__main__");
273 if (m == NULL)
Yegappan Lakshmanand4e4ecb2023-08-27 18:35:45 +0200274 return -1;
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200275 PyObject* d = PyModule_GetDict(m);
276 PyObject* output = Vim_PyRun_String(str, Py_file_input, d, d);
277 if (output == NULL)
278 {
279 PyErr_PrintEx(TRUE);
280 return -1;
281 }
282 Py_DECREF(output);
283 return 0;
284}
285#define PyRun_String Vim_PyRun_String
286#define PyRun_SimpleString Vim_PyRun_SimpleString
287
288#else // !defined(USE_LIMITED_API)
289
290// Full Python API. Can make use of structs and macros directly.
291# define DEFINE_PY_TYPE_OBJECT(type) \
292 static PyTypeObject type; \
293 static PyTypeObject* type##Ptr = &type
294# define PyObject_HEAD_INIT_TYPE(type) PyObject_HEAD_INIT(&type)
295
296# define Py_TYPE_GET_TP_ALLOC(type) type->tp_alloc
297# define Py_TYPE_GET_TP_METHODS(type) type->tp_methods
298
299# define Py_TYPE_NAME(obj) ((obj)->ob_type->tp_name == NULL \
Bram Moolenaarc476e522013-06-23 13:46:40 +0200300 ? "(NULL)" \
kylo2529dac9b12022-03-27 20:05:17 +0100301 : (obj)->ob_type->tp_name)
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200302# define PyErr_FORMAT_TYPE(msg, obj) \
303 PyErr_FORMAT(PyExc_TypeError, msg, \
304 Py_TYPE_NAME(obj))
305
306// Add a static type
307# define PYTYPE_READY(type) \
308 if (PyType_Ready(type##Ptr)) \
309 return -1;
310
311#endif
312
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200313
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200314#define RAISE_NO_EMPTY_KEYS PyErr_SET_STRING(PyExc_ValueError, \
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200315 N_("empty keys are not allowed"))
316#define RAISE_LOCKED_DICTIONARY PyErr_SET_VIM(N_("dictionary is locked"))
317#define RAISE_LOCKED_LIST PyErr_SET_VIM(N_("list is locked"))
318#define RAISE_UNDO_FAIL PyErr_SET_VIM(N_("cannot save undo information"))
319#define RAISE_DELETE_LINE_FAIL PyErr_SET_VIM(N_("cannot delete line"))
320#define RAISE_INSERT_LINE_FAIL PyErr_SET_VIM(N_("cannot insert line"))
321#define RAISE_REPLACE_LINE_FAIL PyErr_SET_VIM(N_("cannot replace line"))
Bram Moolenaarc476e522013-06-23 13:46:40 +0200322#define RAISE_KEY_ADD_FAIL(key) \
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200323 PyErr_VIM_FORMAT(N_("failed to add key '%s' to dictionary"), key)
Bram Moolenaarc476e522013-06-23 13:46:40 +0200324#define RAISE_INVALID_INDEX_TYPE(idx) \
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200325 PyErr_FORMAT_TYPE(N_("index must be int or slice, not %s"), idx);
Bram Moolenaar35eacd72013-05-30 22:06:33 +0200326
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200327#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
328#define INVALID_WINDOW_VALUE ((win_T *)(-1))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +0200329#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200330
Bram Moolenaarb52f4c02013-05-21 18:19:38 +0200331typedef void (*rangeinitializer)(void *);
Ben Jacksonea19e782024-11-06 21:50:05 +0100332typedef void (*runner)(const char *, dict_T *, void *
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +0200333#ifdef PY_CAN_RECURSE
334 , PyGILState_STATE *
335#endif
336 );
Bram Moolenaarb52f4c02013-05-21 18:19:38 +0200337
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200338static int ConvertFromPyObject(PyObject *, typval_T *);
339static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
Bram Moolenaara9922d62013-05-30 13:01:18 +0200340static int ConvertFromPyMapping(PyObject *, typval_T *);
Bram Moolenaar8110a092016-04-14 15:56:09 +0200341static int ConvertFromPySequence(PyObject *, typval_T *);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +0200342static PyObject *WindowNew(win_T *, tabpage_T *);
343static PyObject *BufferNew (buf_T *);
344static PyObject *LineToString(const char *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200345
346static PyInt RangeStart;
347static PyInt RangeEnd;
348
Bram Moolenaarb52f4c02013-05-21 18:19:38 +0200349static PyObject *globals;
350
Bram Moolenaarf4258302013-06-02 18:20:17 +0200351static PyObject *py_chdir;
352static PyObject *py_fchdir;
353static PyObject *py_getcwd;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200354static PyObject *vim_module;
355static PyObject *vim_special_path_object;
Bram Moolenaarf4258302013-06-02 18:20:17 +0200356
Bram Moolenaar79a494d2018-07-22 04:30:21 +0200357#if PY_VERSION_HEX >= 0x030700f0
358static PyObject *py_find_spec;
359#else
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200360static PyObject *py_load_module;
Bram Moolenaar79a494d2018-07-22 04:30:21 +0200361#endif
Ken Takata073cb022024-07-28 17:08:15 +0200362#if PY_VERSION_HEX < 0x30c00a7
Bram Moolenaarb999ba22019-02-14 13:28:45 +0100363static PyObject *py_find_module;
Ken Takata073cb022024-07-28 17:08:15 +0200364#endif
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200365
366static PyObject *VimError;
367
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200368/*
369 * obtain a lock on the Vim data structures
370 */
371 static void
372Python_Lock_Vim(void)
373{
374}
375
376/*
377 * release a lock on the Vim data structures
378 */
379 static void
380Python_Release_Vim(void)
381{
382}
383
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200384/*
385 * The "todecref" argument holds a pointer to PyObject * that must be
386 * DECREF'ed after returned char_u * is no longer needed or NULL if all what
387 * was needed to generate returned value is object.
388 *
389 * Use Py_XDECREF to decrement reference count.
390 */
391 static char_u *
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200392StringToChars(PyObject *obj, PyObject **todecref)
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200393{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200394 char_u *str;
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200395
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200396 if (PyBytes_Check(obj))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200397 {
398
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200399 if (PyBytes_AsStringAndSize(obj, (char **) &str, NULL) == -1
400 || str == NULL)
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200401 return NULL;
402
403 *todecref = NULL;
404 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200405 else if (PyUnicode_Check(obj))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200406 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200407 PyObject *bytes;
408
Bram Moolenaar2e2f52a2020-12-21 16:03:02 +0100409 if (!(bytes = PyUnicode_AsEncodedString(obj, ENC_OPT,
410 ERRORS_ENCODE_ARG)))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200411 return NULL;
412
Bram Moolenaar2e2f52a2020-12-21 16:03:02 +0100413 if (PyBytes_AsStringAndSize(bytes, (char **) &str, NULL) == -1
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200414 || str == NULL)
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200415 {
416 Py_DECREF(bytes);
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200417 return NULL;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200418 }
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200419
420 *todecref = bytes;
421 }
422 else
423 {
Bram Moolenaarc476e522013-06-23 13:46:40 +0200424#if PY_MAJOR_VERSION < 3
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200425 PyErr_FORMAT_TYPE(N_("expected str() or unicode() instance, but got %s"),
426 obj);
Bram Moolenaarc476e522013-06-23 13:46:40 +0200427#else
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200428 PyErr_FORMAT_TYPE(N_("expected bytes() or str() instance, but got %s"),
429 obj);
Bram Moolenaarc476e522013-06-23 13:46:40 +0200430#endif
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200431 return NULL;
432 }
433
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200434 return (char_u *) str;
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200435}
436
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200437#define NUMBER_LONG 1
438#define NUMBER_INT 2
439#define NUMBER_NATURAL 4
440#define NUMBER_UNSIGNED 8
441
442 static int
443NumberToLong(PyObject *obj, long *result, int flags)
444{
445#if PY_MAJOR_VERSION < 3
446 if (PyInt_Check(obj))
447 {
448 *result = PyInt_AsLong(obj);
449 if (PyErr_Occurred())
450 return -1;
451 }
452 else
453#endif
454 if (PyLong_Check(obj))
455 {
456 *result = PyLong_AsLong(obj);
457 if (PyErr_Occurred())
458 return -1;
459 }
460 else if (PyNumber_Check(obj))
461 {
462 PyObject *num;
463
464 if (!(num = PyNumber_Long(obj)))
465 return -1;
466
467 *result = PyLong_AsLong(num);
468
469 Py_DECREF(num);
470
471 if (PyErr_Occurred())
472 return -1;
473 }
474 else
475 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200476#if PY_MAJOR_VERSION < 3
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200477 PyErr_FORMAT_TYPE(
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200478 N_("expected int(), long() or something supporting "
Bram Moolenaarc1c3d682013-06-24 21:21:58 +0200479 "coercing to long(), but got %s"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200480 obj);
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200481#else
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200482 PyErr_FORMAT_TYPE(
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200483 N_("expected int() or something supporting coercing to int(), "
Bram Moolenaarc1c3d682013-06-24 21:21:58 +0200484 "but got %s"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200485 obj);
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200486#endif
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200487 return -1;
488 }
489
490 if (flags & NUMBER_INT)
491 {
492 if (*result > INT_MAX)
493 {
494 PyErr_SET_STRING(PyExc_OverflowError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200495 N_("value is too large to fit into C int type"));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200496 return -1;
497 }
498 else if (*result < INT_MIN)
499 {
500 PyErr_SET_STRING(PyExc_OverflowError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200501 N_("value is too small to fit into C int type"));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200502 return -1;
503 }
504 }
505
506 if (flags & NUMBER_NATURAL)
507 {
508 if (*result <= 0)
509 {
510 PyErr_SET_STRING(PyExc_ValueError,
Bram Moolenaar4de6a212014-03-08 16:13:44 +0100511 N_("number must be greater than zero"));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200512 return -1;
513 }
514 }
515 else if (flags & NUMBER_UNSIGNED)
516 {
517 if (*result < 0)
518 {
519 PyErr_SET_STRING(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200520 N_("number must be greater or equal to zero"));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200521 return -1;
522 }
523 }
524
525 return 0;
526}
527
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200528 static int
529add_string(PyObject *list, char *s)
530{
531 PyObject *string;
532
533 if (!(string = PyString_FromString(s)))
534 return -1;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200535
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200536 if (PyList_Append(list, string))
537 {
538 Py_DECREF(string);
539 return -1;
540 }
541
542 Py_DECREF(string);
543 return 0;
544}
545
546 static PyObject *
547ObjectDir(PyObject *self, char **attributes)
548{
549 PyMethodDef *method;
550 char **attr;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200551 PyObject *ret;
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200552
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200553 if (!(ret = PyList_New(0)))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200554 return NULL;
555
556 if (self)
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200557 for (method = Py_TYPE_GET_TP_METHODS(self->ob_type) ; method->ml_name != NULL ; ++method)
Bram Moolenaar41009372013-07-01 22:03:04 +0200558 if (add_string(ret, (char *)method->ml_name))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200559 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200560 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200561 return NULL;
562 }
563
564 for (attr = attributes ; *attr ; ++attr)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200565 if (add_string(ret, *attr))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200566 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200567 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200568 return NULL;
569 }
570
571#if PY_MAJOR_VERSION < 3
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200572 if (add_string(ret, "__members__"))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200573 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200574 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200575 return NULL;
576 }
577#endif
578
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200579 return ret;
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200580}
581
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100582// Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200583
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100584// Function to write a line, points to either msg() or emsg().
Bram Moolenaarefc0d942020-10-11 18:05:02 +0200585typedef int (*writefn)(char *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200586
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200587DEFINE_PY_TYPE_OBJECT(OutputType);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200588
589typedef struct
590{
591 PyObject_HEAD
592 long softspace;
593 long error;
594} OutputObject;
595
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200596static char *OutputAttrs[] = {
597 "softspace",
598 NULL
599};
600
601 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +0200602OutputDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200603{
604 return ObjectDir(self, OutputAttrs);
605}
606
Bram Moolenaar77045652012-09-21 13:46:06 +0200607 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +0200608OutputSetattr(PyObject *self_obj, char *name, PyObject *valObject)
Bram Moolenaar77045652012-09-21 13:46:06 +0200609{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +0200610 OutputObject *self = (OutputObject*)self_obj;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200611 if (valObject == NULL)
Bram Moolenaar77045652012-09-21 13:46:06 +0200612 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200613 PyErr_SET_STRING(PyExc_AttributeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200614 N_("can't delete OutputObject attributes"));
Bram Moolenaar77045652012-09-21 13:46:06 +0200615 return -1;
616 }
617
618 if (strcmp(name, "softspace") == 0)
619 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200620 if (NumberToLong(valObject, &(self->softspace), NUMBER_UNSIGNED))
Bram Moolenaar77045652012-09-21 13:46:06 +0200621 return -1;
Bram Moolenaar77045652012-09-21 13:46:06 +0200622 return 0;
623 }
624
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200625 PyErr_FORMAT(PyExc_AttributeError, N_("invalid attribute: %s"), name);
Bram Moolenaar77045652012-09-21 13:46:06 +0200626 return -1;
627}
628
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100629// Buffer IO, we write one whole line at a time.
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200630static garray_T io_ga = {0, 0, 1, 80, NULL};
631static writefn old_fn = NULL;
632
633 static void
634PythonIO_Flush(void)
635{
636 if (old_fn != NULL && io_ga.ga_len > 0)
637 {
Bram Moolenaarefc0d942020-10-11 18:05:02 +0200638 ((char *)io_ga.ga_data)[io_ga.ga_len] = NUL;
Boris Staletic83a06702024-10-14 20:28:39 +0200639 // We don't know what emsg_severe should be here, so ... hope?
Bram Moolenaarefc0d942020-10-11 18:05:02 +0200640 old_fn((char *)io_ga.ga_data);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200641 }
642 io_ga.ga_len = 0;
643}
644
645 static void
Boris Staletic83a06702024-10-14 20:28:39 +0200646writer(writefn fn, char_u *str, PyInt n, int severe)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200647{
648 char_u *ptr;
649
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100650 // Flush when switching output function.
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200651 if (fn != old_fn)
652 PythonIO_Flush();
653 old_fn = fn;
654
Bram Moolenaarb98678a2019-10-19 15:18:44 +0200655 // Write each NL separated line. Text after the last NL is kept for
656 // writing later.
657 // For normal messages: Do not output when "got_int" was set. This avoids
658 // a loop gone crazy flooding the terminal with messages. Also for when
659 // "q" is pressed at the more-prompt.
660 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL
661 && (fn == (writefn)emsg || !got_int))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200662 {
663 PyInt len = ptr - str;
664
665 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
666 break;
667
668 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
669 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
Boris Staletic83a06702024-10-14 20:28:39 +0200670 emsg_severe = severe;
Bram Moolenaarefc0d942020-10-11 18:05:02 +0200671 fn((char *)io_ga.ga_data);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200672 str = ptr + 1;
673 n -= len + 1;
674 io_ga.ga_len = 0;
675 }
676
Bram Moolenaarb98678a2019-10-19 15:18:44 +0200677 // Put the remaining text into io_ga for later printing.
678 if (n > 0 && (fn == (writefn)emsg || !got_int)
679 && ga_grow(&io_ga, (int)(n + 1)) == OK)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200680 {
681 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
682 io_ga.ga_len += (int)n;
683 }
684}
685
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200686 static int
687write_output(OutputObject *self, PyObject *string)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200688{
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200689 Py_ssize_t len = 0;
690 char *str = NULL;
691 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200692
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200693 if (!PyArg_Parse(string, "et#", ENC_OPT, &str, &len))
694 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200695
696 Py_BEGIN_ALLOW_THREADS
697 Python_Lock_Vim();
Boris Staletic83a06702024-10-14 20:28:39 +0200698 writer((writefn)(error ? emsg : msg), (char_u *)str, len, error);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200699 Python_Release_Vim();
700 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200701 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200702
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200703 return 0;
704}
705
706 static PyObject *
707OutputWrite(OutputObject *self, PyObject *string)
708{
709 if (write_output(self, string))
710 return NULL;
711
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200712 Py_INCREF(Py_None);
713 return Py_None;
714}
715
716 static PyObject *
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200717OutputWritelines(OutputObject *self, PyObject *seq)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200718{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200719 PyObject *iterator;
720 PyObject *item;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200721
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200722 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200723 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200724
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200725 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200726 {
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200727 if (write_output(self, item))
Bram Moolenaardb913952012-06-29 12:54:53 +0200728 {
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200729 Py_DECREF(iterator);
730 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200731 return NULL;
732 }
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200733 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200734 }
735
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200736 Py_DECREF(iterator);
737
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100738 // Iterator may have finished due to an exception
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200739 if (PyErr_Occurred())
740 return NULL;
741
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200742 Py_INCREF(Py_None);
743 return Py_None;
744}
745
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100746 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +0200747AlwaysNone(PyObject *self UNUSED, PyObject *args UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100748{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100749 // do nothing
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100750 Py_INCREF(Py_None);
751 return Py_None;
752}
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +0200753#define ALWAYS_NONE AlwaysNone(NULL, NULL)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100754
Bram Moolenaard4247472015-11-02 13:28:59 +0100755 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +0200756AlwaysFalse(PyObject *self UNUSED, PyObject *args UNUSED)
Bram Moolenaard4247472015-11-02 13:28:59 +0100757{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100758 // do nothing
Bram Moolenaare7427f42015-11-10 13:24:20 +0100759 PyObject *ret = Py_False;
760 Py_INCREF(ret);
761 return ret;
Bram Moolenaard4247472015-11-02 13:28:59 +0100762}
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +0200763#define ALWAYS_FALSE AlwaysFalse(NULL, NULL)
Bram Moolenaard4247472015-11-02 13:28:59 +0100764
765 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +0200766AlwaysTrue(PyObject *self UNUSED, PyObject *args UNUSED)
Bram Moolenaard4247472015-11-02 13:28:59 +0100767{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100768 // do nothing
Bram Moolenaare7427f42015-11-10 13:24:20 +0100769 PyObject *ret = Py_True;
770 Py_INCREF(ret);
771 return ret;
Bram Moolenaard4247472015-11-02 13:28:59 +0100772}
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +0200773#define ALWAYS_TRUE AlwaysTrue(NULL, NULL)
Bram Moolenaard4247472015-11-02 13:28:59 +0100774
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200775/***************/
776
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200777static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100778 // name, function, calling, doc
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200779 {"write", (PyCFunction)OutputWrite, METH_O, ""},
780 {"writelines", (PyCFunction)OutputWritelines, METH_O, ""},
Bram Moolenaard4247472015-11-02 13:28:59 +0100781 {"flush", (PyCFunction)AlwaysNone, METH_NOARGS, ""},
782 {"close", (PyCFunction)AlwaysNone, METH_NOARGS, ""},
783 {"isatty", (PyCFunction)AlwaysFalse, METH_NOARGS, ""},
784 {"readable", (PyCFunction)AlwaysFalse, METH_NOARGS, ""},
785 {"seekable", (PyCFunction)AlwaysFalse, METH_NOARGS, ""},
786 {"writable", (PyCFunction)AlwaysTrue, METH_NOARGS, ""},
Bram Moolenaar6d4431e2016-04-21 20:00:56 +0200787 {"closed", (PyCFunction)AlwaysFalse, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200788 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200789 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200790};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200791
792static OutputObject Output =
793{
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200794 PyObject_HEAD_INIT_TYPE(OutputType)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200795 0,
796 0
797};
798
799static OutputObject Error =
800{
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200801 PyObject_HEAD_INIT_TYPE(OutputType)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200802 0,
803 1
804};
805
806 static int
807PythonIO_Init_io(void)
808{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +0200809 if (PySys_SetObject("stdout", (PyObject *)(void *)&Output))
810 return -1;
811 if (PySys_SetObject("stderr", (PyObject *)(void *)&Error))
812 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200813
814 if (PyErr_Occurred())
815 {
Bram Moolenaar9a846fb2022-01-01 21:59:18 +0000816 emsg(_(e_python_error_initialising_io_object));
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200817 return -1;
818 }
819
820 return 0;
821}
822
Bram Moolenaar79a494d2018-07-22 04:30:21 +0200823#if PY_VERSION_HEX < 0x030700f0
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200824static PyObject *call_load_module(char *name, int len, PyObject *find_module_result);
825
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200826typedef struct
827{
828 PyObject_HEAD
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200829 char *fullname;
830 PyObject *result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200831} LoaderObject;
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +0200832DEFINE_PY_TYPE_OBJECT(LoaderType);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200833
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200834 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +0200835LoaderDestructor(PyObject *self_obj)
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200836{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +0200837 LoaderObject *self = (LoaderObject*)self_obj;
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200838 vim_free(self->fullname);
839 Py_XDECREF(self->result);
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200840 DESTRUCTOR_FINISH(self);
841}
842
843 static PyObject *
844LoaderLoadModule(LoaderObject *self, PyObject *args UNUSED)
845{
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200846 char *fullname = self->fullname;
847 PyObject *result = self->result;
848 PyObject *module;
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200849
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200850 if (!fullname)
851 {
852 module = result ? result : Py_None;
853 Py_INCREF(module);
854 return module;
855 }
856
857 module = call_load_module(fullname, (int)STRLEN(fullname), result);
858
859 self->fullname = NULL;
860 self->result = module;
861
862 vim_free(fullname);
863 Py_DECREF(result);
864
865 if (!module)
866 {
867 if (PyErr_Occurred())
868 return NULL;
869
870 Py_INCREF(Py_None);
871 return Py_None;
872 }
873
874 Py_INCREF(module);
875 return module;
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200876}
877
878static struct PyMethodDef LoaderMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100879 // name, function, calling, doc
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200880 {"load_module", (PyCFunction)LoaderLoadModule, METH_VARARGS, ""},
881 { NULL, NULL, 0, NULL}
882};
Bram Moolenaar79a494d2018-07-22 04:30:21 +0200883#endif
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200884
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100885/*
886 * Check to see whether a Vim error has been reported, or a keyboard
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200887 * interrupt has been detected.
888 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200889 static void
890VimTryStart(void)
891{
892 ++trylevel;
893}
894
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200895 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200896VimTryEnd(void)
897{
898 --trylevel;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100899 // Without this it stops processing all subsequent Vim script commands and
900 // generates strange error messages if I e.g. try calling Test() in a cycle
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200901 did_emsg = FALSE;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100902 // Keyboard interrupt should be preferred over anything else
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200903 if (got_int)
904 {
Bram Moolenaar4315f262014-01-31 14:54:04 +0100905 if (did_throw)
Bram Moolenaard6b8a522013-11-11 01:05:48 +0100906 discard_current_exception();
Bram Moolenaard6b8a522013-11-11 01:05:48 +0100907 got_int = FALSE;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200908 PyErr_SetNone(PyExc_KeyboardInterrupt);
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200909 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200910 }
Bram Moolenaar9fee7d42013-11-28 17:04:43 +0100911 else if (msg_list != NULL && *msg_list != NULL)
912 {
913 int should_free;
Bram Moolenaarb1443b42019-01-13 23:51:14 +0100914 char *msg;
Bram Moolenaar9fee7d42013-11-28 17:04:43 +0100915
916 msg = get_exception_string(*msg_list, ET_ERROR, NULL, &should_free);
917
918 if (msg == NULL)
919 {
920 PyErr_NoMemory();
921 return -1;
922 }
923
Bram Moolenaarb1443b42019-01-13 23:51:14 +0100924 PyErr_SetVim(msg);
Bram Moolenaar9fee7d42013-11-28 17:04:43 +0100925
926 free_global_msglist();
927
928 if (should_free)
929 vim_free(msg);
930
931 return -1;
932 }
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200933 else if (!did_throw)
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200934 return (PyErr_Occurred() ? -1 : 0);
Bram Moolenaar86181df2020-05-11 23:14:04 +0200935 // Python exception is preferred over Vim one; unlikely to occur though
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200936 else if (PyErr_Occurred())
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200937 {
Bram Moolenaar4315f262014-01-31 14:54:04 +0100938 discard_current_exception();
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200939 return -1;
940 }
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100941 // Finally transform Vim script exception to python one
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200942 else
943 {
Bram Moolenaar41009372013-07-01 22:03:04 +0200944 PyErr_SetVim((char *)current_exception->value);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200945 discard_current_exception();
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200946 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200947 }
948}
949
950 static int
951VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200952{
953 if (got_int)
954 {
955 PyErr_SetNone(PyExc_KeyboardInterrupt);
956 return 1;
957 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200958 return 0;
959}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200960
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100961// Vim module - Implementation
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200962
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200963 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200964VimCommand(PyObject *self UNUSED, PyObject *string)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200965{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200966 char_u *cmd;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200967 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200968 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200969
Bram Moolenaar389a1792013-06-23 13:00:44 +0200970 if (!(cmd = StringToChars(string, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200971 return NULL;
972
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200973 Py_BEGIN_ALLOW_THREADS
974 Python_Lock_Vim();
975
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200976 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200977 do_cmdline_cmd(cmd);
Bram Moolenaara4d158b2022-08-14 14:17:45 +0100978 update_screen(UPD_VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200979
980 Python_Release_Vim();
981 Py_END_ALLOW_THREADS
982
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200983 if (VimTryEnd())
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200984 ret = NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200985 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200986 ret = Py_None;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200987
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200988 Py_XINCREF(ret);
Bram Moolenaar389a1792013-06-23 13:00:44 +0200989 Py_XDECREF(todecref);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200990 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200991}
992
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200993/*
994 * Function to translate a typval_T into a PyObject; this will recursively
995 * translate lists/dictionaries into their Python equivalents.
996 *
997 * The depth parameter is to avoid infinite recursion, set it to 1 when
998 * you call VimToPython.
999 */
1000 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001001VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001002{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001003 PyObject *ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001004 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02001005 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001006
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001007 // Avoid infinite recursion
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001008 if (depth > 100)
1009 {
1010 Py_INCREF(Py_None);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001011 ret = Py_None;
1012 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001013 }
1014
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001015 // Check if we run into a recursive loop. The item must be in lookup_dict
1016 // then and we can use it again.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001017 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001018 || (our_tv->v_type == VAR_TUPLE && our_tv->vval.v_tuple != NULL)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001019 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
1020 {
Bram Moolenaardb913952012-06-29 12:54:53 +02001021 sprintf(ptrBuf, "%p",
1022 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001023 : our_tv->v_type == VAR_TUPLE ?
1024 (void *)our_tv->vval.v_tuple
1025 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001026
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001027 if ((ret = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001028 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001029 Py_INCREF(ret);
1030 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001031 }
1032 }
1033
1034 if (our_tv->v_type == VAR_STRING)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001035 ret = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02001036 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001037 else if (our_tv->v_type == VAR_NUMBER)
1038 {
1039 char buf[NUMBUFLEN];
1040
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001041 // For backwards compatibility numbers are stored as strings.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001042 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaar41009372013-07-01 22:03:04 +02001043 ret = PyString_FromString((char *)buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001044 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001045 else if (our_tv->v_type == VAR_FLOAT)
1046 {
1047 char buf[NUMBUFLEN];
1048
1049 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaar41009372013-07-01 22:03:04 +02001050 ret = PyString_FromString((char *)buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001051 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001052 else if (our_tv->v_type == VAR_LIST)
1053 {
1054 list_T *list = our_tv->vval.v_list;
1055 listitem_T *curr;
1056
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001057 if (list == NULL)
1058 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001059
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001060 if (!(ret = PyList_New(0)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001061 return NULL;
1062
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001063 if (PyDict_SetItemString(lookup_dict, ptrBuf, ret))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001064 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001065 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001066 return NULL;
1067 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001068
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02001069 CHECK_LIST_MATERIALIZE(list);
Bram Moolenaaraeea7212020-04-02 18:50:46 +02001070 FOR_ALL_LIST_ITEMS(list, curr)
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001071 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001072 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001073 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001074 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001075 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001076 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001077 if (PyList_Append(ret, newObj))
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001078 {
1079 Py_DECREF(newObj);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001080 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001081 return NULL;
1082 }
1083 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001084 }
1085 }
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001086 else if (our_tv->v_type == VAR_TUPLE)
1087 {
1088 tuple_T *tuple = our_tv->vval.v_tuple;
1089 int len;
1090
1091 if (tuple == NULL)
1092 return NULL;
1093
1094 len = TUPLE_LEN(tuple);
1095
1096 ret = PyTuple_New(len);
1097 if (ret == NULL)
1098 return NULL;
1099
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001100 for (int idx = 0; idx < len; idx++)
1101 {
1102 typval_T *item_tv = TUPLE_ITEM(tuple, idx);
1103
1104 newObj = VimToPython(item_tv, depth + 1, lookup_dict);
1105 if (!newObj)
1106 {
1107 Py_DECREF(ret);
1108 return NULL;
1109 }
Yee Cheng Chine06b2ae2025-03-27 20:13:33 +01001110 PyTuple_SetItem(ret, idx, newObj);
1111 }
1112
1113 if (PyDict_SetItemString(lookup_dict, ptrBuf, ret))
1114 {
1115 Py_DECREF(ret);
1116 return NULL;
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001117 }
1118 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001119 else if (our_tv->v_type == VAR_DICT)
1120 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001121
Bram Moolenaar24a6ff82015-02-10 18:41:58 +01001122 hashtab_T *ht;
1123 long_u todo;
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001124 hashitem_T *hi;
1125 dictitem_T *di;
Bram Moolenaar24a6ff82015-02-10 18:41:58 +01001126
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001127 if (our_tv->vval.v_dict == NULL)
1128 return NULL;
Bram Moolenaar24a6ff82015-02-10 18:41:58 +01001129 ht = &our_tv->vval.v_dict->dv_hashtab;
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001130
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001131 if (!(ret = PyDict_New()))
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001132 return NULL;
1133
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001134 if (PyDict_SetItemString(lookup_dict, ptrBuf, ret))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001135 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001136 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001137 return NULL;
1138 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001139
Bram Moolenaar24a6ff82015-02-10 18:41:58 +01001140 todo = ht->ht_used;
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001141 for (hi = ht->ht_array; todo > 0; ++hi)
1142 {
1143 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001144 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001145 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001146
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001147 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001148 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001149 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001150 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001151 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001152 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001153 if (PyDict_SetItemString(ret, (char *)hi->hi_key, newObj))
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001154 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001155 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +02001156 Py_DECREF(newObj);
1157 return NULL;
1158 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001159 }
1160 }
1161 }
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01001162 else if (our_tv->v_type == VAR_BOOL)
Bram Moolenaar520e1e42016-01-23 19:46:28 +01001163 {
1164 if (our_tv->vval.v_number == VVAL_FALSE)
1165 {
1166 ret = Py_False;
1167 Py_INCREF(ret);
1168 }
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01001169 else
Bram Moolenaar520e1e42016-01-23 19:46:28 +01001170 {
1171 ret = Py_True;
1172 Py_INCREF(ret);
1173 }
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01001174 return ret;
1175 }
1176 else if (our_tv->v_type == VAR_SPECIAL)
1177 {
1178 Py_INCREF(Py_None);
1179 ret = Py_None;
Bram Moolenaar520e1e42016-01-23 19:46:28 +01001180 return ret;
1181 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01001182 else if (our_tv->v_type == VAR_BLOB)
1183 ret = PyBytes_FromStringAndSize(
1184 (char*) our_tv->vval.v_blob->bv_ga.ga_data,
1185 (Py_ssize_t) our_tv->vval.v_blob->bv_ga.ga_len);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001186 else
1187 {
1188 Py_INCREF(Py_None);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001189 ret = Py_None;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001190 }
1191
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001192 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001193}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001194
1195 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +02001196VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001197{
Bram Moolenaar389a1792013-06-23 13:00:44 +02001198 char_u *expr;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001199 typval_T *our_tv;
Bram Moolenaar389a1792013-06-23 13:00:44 +02001200 PyObject *string;
1201 PyObject *todecref;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001202 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +02001203 PyObject *lookup_dict;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001204
Bram Moolenaar389a1792013-06-23 13:00:44 +02001205 if (!PyArg_ParseTuple(args, "O", &string))
1206 return NULL;
1207
1208 if (!(expr = StringToChars(string, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001209 return NULL;
1210
1211 Py_BEGIN_ALLOW_THREADS
1212 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001213 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +02001214 our_tv = eval_expr(expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001215 Python_Release_Vim();
1216 Py_END_ALLOW_THREADS
1217
Bram Moolenaar389a1792013-06-23 13:00:44 +02001218 Py_XDECREF(todecref);
1219
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001220 if (VimTryEnd())
1221 return NULL;
1222
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001223 if (our_tv == NULL)
1224 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001225 PyErr_SET_VIM(N_("invalid expression"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001226 return NULL;
1227 }
1228
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001229 // Convert the Vim type into a Python type. Create a dictionary that's
1230 // used to check for recursive loops.
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02001231 if (!(lookup_dict = PyDict_New()))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001232 ret = NULL;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02001233 else
1234 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001235 ret = VimToPython(our_tv, 1, lookup_dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02001236 Py_DECREF(lookup_dict);
1237 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001238
1239
1240 Py_BEGIN_ALLOW_THREADS
1241 Python_Lock_Vim();
1242 free_tv(our_tv);
1243 Python_Release_Vim();
1244 Py_END_ALLOW_THREADS
1245
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001246 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001247}
1248
Bram Moolenaardb913952012-06-29 12:54:53 +02001249static PyObject *ConvertToPyObject(typval_T *);
1250
1251 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02001252VimEvalPy(PyObject *self UNUSED, PyObject *string)
Bram Moolenaardb913952012-06-29 12:54:53 +02001253{
Bram Moolenaardb913952012-06-29 12:54:53 +02001254 typval_T *our_tv;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001255 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +02001256 char_u *expr;
1257 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001258
Bram Moolenaar389a1792013-06-23 13:00:44 +02001259 if (!(expr = StringToChars(string, &todecref)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001260 return NULL;
1261
1262 Py_BEGIN_ALLOW_THREADS
1263 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001264 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +02001265 our_tv = eval_expr(expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02001266 Python_Release_Vim();
1267 Py_END_ALLOW_THREADS
1268
Bram Moolenaar389a1792013-06-23 13:00:44 +02001269 Py_XDECREF(todecref);
1270
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001271 if (VimTryEnd())
1272 return NULL;
1273
Bram Moolenaardb913952012-06-29 12:54:53 +02001274 if (our_tv == NULL)
1275 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001276 PyErr_SET_VIM(N_("invalid expression"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001277 return NULL;
1278 }
1279
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001280 ret = ConvertToPyObject(our_tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001281 Py_BEGIN_ALLOW_THREADS
1282 Python_Lock_Vim();
1283 free_tv(our_tv);
1284 Python_Release_Vim();
1285 Py_END_ALLOW_THREADS
1286
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001287 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02001288}
1289
1290 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02001291VimStrwidth(PyObject *self UNUSED, PyObject *string)
Bram Moolenaardb913952012-06-29 12:54:53 +02001292{
Bram Moolenaar389a1792013-06-23 13:00:44 +02001293 char_u *str;
1294 PyObject *todecref;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001295 int len;
Bram Moolenaardb913952012-06-29 12:54:53 +02001296
Bram Moolenaar389a1792013-06-23 13:00:44 +02001297 if (!(str = StringToChars(string, &todecref)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001298 return NULL;
1299
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001300 len = mb_string2cells(str, (int)STRLEN(str));
Bram Moolenaar389a1792013-06-23 13:00:44 +02001301
1302 Py_XDECREF(todecref);
1303
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001304 return PyLong_FromLong(len);
Bram Moolenaardb913952012-06-29 12:54:53 +02001305}
1306
Bram Moolenaarf4258302013-06-02 18:20:17 +02001307 static PyObject *
1308_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
1309{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001310 PyObject *ret;
Bram Moolenaarf4258302013-06-02 18:20:17 +02001311 PyObject *newwd;
1312 PyObject *todecref;
1313 char_u *new_dir;
1314
Bram Moolenaard4209d22013-06-05 20:34:15 +02001315 if (_chdir == NULL)
1316 return NULL;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001317 if (!(ret = PyObject_Call(_chdir, args, kwargs)))
Bram Moolenaarf4258302013-06-02 18:20:17 +02001318 return NULL;
1319
1320 if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
1321 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001322 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001323 return NULL;
1324 }
1325
1326 if (!(new_dir = StringToChars(newwd, &todecref)))
1327 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001328 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001329 Py_DECREF(newwd);
1330 return NULL;
1331 }
1332
1333 VimTryStart();
1334
1335 if (vim_chdir(new_dir))
1336 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001337 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001338 Py_DECREF(newwd);
1339 Py_XDECREF(todecref);
1340
1341 if (VimTryEnd())
1342 return NULL;
1343
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001344 PyErr_SET_VIM(N_("failed to change directory"));
Bram Moolenaarf4258302013-06-02 18:20:17 +02001345 return NULL;
1346 }
1347
1348 Py_DECREF(newwd);
1349 Py_XDECREF(todecref);
1350
Bram Moolenaar1063f3d2019-05-07 22:06:52 +02001351 post_chdir(CDSCOPE_GLOBAL);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001352
1353 if (VimTryEnd())
1354 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001355 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001356 return NULL;
1357 }
1358
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001359 return ret;
Bram Moolenaarf4258302013-06-02 18:20:17 +02001360}
1361
1362 static PyObject *
1363VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
1364{
1365 return _VimChdir(py_chdir, args, kwargs);
1366}
1367
1368 static PyObject *
1369VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
1370{
1371 return _VimChdir(py_fchdir, args, kwargs);
1372}
1373
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001374typedef struct {
1375 PyObject *callable;
1376 PyObject *result;
1377} map_rtp_data;
1378
1379 static void
1380map_rtp_callback(char_u *path, void *_data)
1381{
1382 void **data = (void **) _data;
1383 PyObject *pathObject;
1384 map_rtp_data *mr_data = *((map_rtp_data **) data);
1385
Bram Moolenaar41009372013-07-01 22:03:04 +02001386 if (!(pathObject = PyString_FromString((char *)path)))
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001387 {
1388 *data = NULL;
1389 return;
1390 }
1391
1392 mr_data->result = PyObject_CallFunctionObjArgs(mr_data->callable,
1393 pathObject, NULL);
1394
1395 Py_DECREF(pathObject);
1396
1397 if (!mr_data->result || mr_data->result != Py_None)
1398 *data = NULL;
1399 else
1400 {
1401 Py_DECREF(mr_data->result);
1402 mr_data->result = NULL;
1403 }
1404}
1405
1406 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02001407VimForeachRTP(PyObject *self UNUSED, PyObject *callable)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001408{
1409 map_rtp_data data;
1410
Bram Moolenaar389a1792013-06-23 13:00:44 +02001411 data.callable = callable;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001412 data.result = NULL;
1413
Bram Moolenaar7f8989d2016-03-12 22:11:39 +01001414 do_in_runtimepath(NULL, 0, &map_rtp_callback, &data);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001415
1416 if (data.result == NULL)
1417 {
1418 if (PyErr_Occurred())
1419 return NULL;
1420 else
1421 {
1422 Py_INCREF(Py_None);
1423 return Py_None;
1424 }
1425 }
1426 return data.result;
1427}
1428
1429/*
1430 * _vim_runtimepath_ special path implementation.
1431 */
1432
1433 static void
1434map_finder_callback(char_u *path, void *_data)
1435{
1436 void **data = (void **) _data;
1437 PyObject *list = *((PyObject **) data);
1438 PyObject *pathObject1, *pathObject2;
1439 char *pathbuf;
1440 size_t pathlen;
1441
1442 pathlen = STRLEN(path);
1443
1444#if PY_MAJOR_VERSION < 3
1445# define PY_MAIN_DIR_STRING "python2"
1446#else
1447# define PY_MAIN_DIR_STRING "python3"
1448#endif
1449#define PY_ALTERNATE_DIR_STRING "pythonx"
1450
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001451#define PYTHONX_STRING_LENGTH 7 // STRLEN("pythonx")
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001452 if (!(pathbuf = PyMem_New(char,
1453 pathlen + STRLEN(PATHSEPSTR) + PYTHONX_STRING_LENGTH + 1)))
1454 {
1455 PyErr_NoMemory();
1456 *data = NULL;
1457 return;
1458 }
1459
1460 mch_memmove(pathbuf, path, pathlen + 1);
1461 add_pathsep((char_u *) pathbuf);
1462
1463 pathlen = STRLEN(pathbuf);
1464 mch_memmove(pathbuf + pathlen, PY_MAIN_DIR_STRING,
1465 PYTHONX_STRING_LENGTH + 1);
1466
1467 if (!(pathObject1 = PyString_FromString(pathbuf)))
1468 {
1469 *data = NULL;
1470 PyMem_Free(pathbuf);
1471 return;
1472 }
1473
1474 mch_memmove(pathbuf + pathlen, PY_ALTERNATE_DIR_STRING,
1475 PYTHONX_STRING_LENGTH + 1);
1476
1477 if (!(pathObject2 = PyString_FromString(pathbuf)))
1478 {
1479 Py_DECREF(pathObject1);
1480 PyMem_Free(pathbuf);
1481 *data = NULL;
1482 return;
1483 }
1484
1485 PyMem_Free(pathbuf);
1486
1487 if (PyList_Append(list, pathObject1)
1488 || PyList_Append(list, pathObject2))
1489 *data = NULL;
1490
1491 Py_DECREF(pathObject1);
1492 Py_DECREF(pathObject2);
1493}
1494
1495 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02001496Vim_GetPaths(PyObject *self UNUSED, PyObject *args UNUSED)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001497{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001498 PyObject *ret;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001499
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001500 if (!(ret = PyList_New(0)))
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001501 return NULL;
1502
Bram Moolenaar7f8989d2016-03-12 22:11:39 +01001503 do_in_runtimepath(NULL, 0, &map_finder_callback, ret);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001504
1505 if (PyErr_Occurred())
1506 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001507 Py_DECREF(ret);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001508 return NULL;
1509 }
1510
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001511 return ret;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001512}
1513
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001514#if PY_VERSION_HEX >= 0x030700f0
1515 static PyObject *
1516FinderFindSpec(PyObject *self, PyObject *args)
1517{
1518 char *fullname;
1519 PyObject *paths;
1520 PyObject *target = Py_None;
1521 PyObject *spec;
1522
1523 if (!PyArg_ParseTuple(args, "s|O", &fullname, &target))
1524 return NULL;
1525
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02001526 if (!(paths = Vim_GetPaths(self, NULL)))
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001527 return NULL;
1528
Bram Moolenaarde5b3802019-03-30 12:51:22 +01001529 spec = PyObject_CallFunction(py_find_spec, "sOO", fullname, paths, target);
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001530
1531 Py_DECREF(paths);
1532
1533 if (!spec)
1534 {
1535 if (PyErr_Occurred())
1536 return NULL;
1537
1538 Py_INCREF(Py_None);
1539 return Py_None;
1540 }
1541
1542 return spec;
1543}
Bram Moolenaar0b0ad352019-05-20 21:52:45 +02001544
1545 static PyObject *
1546FinderFindModule(PyObject* self UNUSED, PyObject* args UNUSED)
1547{
1548 // Apparently returning None works.
1549 Py_INCREF(Py_None);
1550 return Py_None;
1551}
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001552#else
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001553 static PyObject *
1554call_load_module(char *name, int len, PyObject *find_module_result)
1555{
1556 PyObject *fd, *pathname, *description;
1557
Bram Moolenaarc476e522013-06-23 13:46:40 +02001558 if (!PyTuple_Check(find_module_result))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001559 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02001560 PyErr_FORMAT_TYPE(
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001561 N_("expected 3-tuple as imp.find_module() result, but got %s"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02001562 find_module_result);
Bram Moolenaarc476e522013-06-23 13:46:40 +02001563 return NULL;
1564 }
1565 if (PyTuple_GET_SIZE(find_module_result) != 3)
1566 {
1567 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001568 N_("expected 3-tuple as imp.find_module() result, but got "
1569 "tuple of size %d"),
Bram Moolenaarc476e522013-06-23 13:46:40 +02001570 (int) PyTuple_GET_SIZE(find_module_result));
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001571 return NULL;
1572 }
1573
1574 if (!(fd = PyTuple_GET_ITEM(find_module_result, 0))
1575 || !(pathname = PyTuple_GET_ITEM(find_module_result, 1))
1576 || !(description = PyTuple_GET_ITEM(find_module_result, 2)))
1577 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001578 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001579 N_("internal error: imp.find_module returned tuple with NULL"));
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001580 return NULL;
1581 }
1582
1583 return PyObject_CallFunction(py_load_module,
1584 "s#OOO", name, len, fd, pathname, description);
1585}
1586
1587 static PyObject *
1588find_module(char *fullname, char *tail, PyObject *new_path)
1589{
1590 PyObject *find_module_result;
1591 PyObject *module;
1592 char *dot;
1593
Bram Moolenaar41009372013-07-01 22:03:04 +02001594 if ((dot = (char *)vim_strchr((char_u *) tail, '.')))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001595 {
1596 /*
Bram Moolenaaredb07a22013-06-12 18:13:38 +02001597 * There is a dot in the name: call find_module recursively without the
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001598 * first component
1599 */
1600 PyObject *newest_path;
1601 int partlen = (int) (dot - 1 - tail);
1602
1603 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1604 "s#O", tail, partlen, new_path)))
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001605 {
1606 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_ImportError))
1607 PyErr_Clear();
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001608 return NULL;
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001609 }
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001610
1611 if (!(module = call_load_module(
1612 fullname,
1613 ((int) (tail - fullname)) + partlen,
1614 find_module_result)))
1615 {
1616 Py_DECREF(find_module_result);
1617 return NULL;
1618 }
1619
1620 Py_DECREF(find_module_result);
1621
1622 if (!(newest_path = PyObject_GetAttrString(module, "__path__")))
1623 {
1624 Py_DECREF(module);
1625 return NULL;
1626 }
1627
1628 Py_DECREF(module);
1629
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001630 find_module_result = find_module(fullname, dot + 1, newest_path);
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001631
1632 Py_DECREF(newest_path);
1633
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001634 return find_module_result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001635 }
1636 else
1637 {
1638 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1639 "sO", tail, new_path)))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001640 {
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001641 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_ImportError))
1642 PyErr_Clear();
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001643 return NULL;
1644 }
1645
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001646 return find_module_result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001647 }
1648}
1649
1650 static PyObject *
1651FinderFindModule(PyObject *self, PyObject *args)
1652{
1653 char *fullname;
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001654 PyObject *result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001655 PyObject *new_path;
1656 LoaderObject *loader;
1657
1658 if (!PyArg_ParseTuple(args, "s", &fullname))
1659 return NULL;
1660
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02001661 if (!(new_path = Vim_GetPaths(self, NULL)))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001662 return NULL;
1663
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001664 result = find_module(fullname, fullname, new_path);
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001665
1666 Py_DECREF(new_path);
1667
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001668 if (!result)
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001669 {
Bram Moolenaar7e85d3d2013-06-23 16:40:39 +02001670 if (PyErr_Occurred())
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001671 return NULL;
Bram Moolenaar7e85d3d2013-06-23 16:40:39 +02001672
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001673 Py_INCREF(Py_None);
1674 return Py_None;
1675 }
1676
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001677 if (!(fullname = (char *)vim_strsave((char_u *)fullname)))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001678 {
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001679 Py_DECREF(result);
1680 PyErr_NoMemory();
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001681 return NULL;
1682 }
1683
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02001684 if (!(loader = PyObject_NEW(LoaderObject, LoaderTypePtr)))
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001685 {
1686 vim_free(fullname);
1687 Py_DECREF(result);
1688 return NULL;
1689 }
1690
1691 loader->fullname = fullname;
1692 loader->result = result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001693
1694 return (PyObject *) loader;
1695}
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001696#endif
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001697
1698 static PyObject *
1699VimPathHook(PyObject *self UNUSED, PyObject *args)
1700{
1701 char *path;
1702
1703 if (PyArg_ParseTuple(args, "s", &path)
1704 && STRCMP(path, vim_special_path) == 0)
1705 {
1706 Py_INCREF(vim_module);
1707 return vim_module;
1708 }
1709
1710 PyErr_Clear();
1711 PyErr_SetNone(PyExc_ImportError);
1712 return NULL;
1713}
1714
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001715/*
1716 * Vim module - Definitions
1717 */
1718
1719static struct PyMethodDef VimMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001720 // name, function, calling, documentation
Bram Moolenaar389a1792013-06-23 13:00:44 +02001721 {"command", VimCommand, METH_O, "Execute a Vim ex-mode command" },
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001722 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
Bram Moolenaar86181df2020-05-11 23:14:04 +02001723 {"bindeval", VimEvalPy, METH_O, "Like eval(), but returns objects attached to Vim ones"},
Bram Moolenaar389a1792013-06-23 13:00:44 +02001724 {"strwidth", VimStrwidth, METH_O, "Screen string width, counts <Tab> as having width 1"},
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02001725 {"chdir", (PyCFunction)(void *)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
1726 {"fchdir", (PyCFunction)(void *)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
Bram Moolenaar389a1792013-06-23 13:00:44 +02001727 {"foreach_rtp", VimForeachRTP, METH_O, "Call given callable for each path in &rtp"},
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001728#if PY_VERSION_HEX >= 0x030700f0
1729 {"find_spec", FinderFindSpec, METH_VARARGS, "Internal use only, returns spec object for any input it receives"},
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001730#endif
Bram Moolenaar0b0ad352019-05-20 21:52:45 +02001731 {"find_module", FinderFindModule, METH_VARARGS, "Internal use only, returns loader object for any input it receives"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001732 {"path_hook", VimPathHook, METH_VARARGS, "Hook function to install in sys.path_hooks"},
1733 {"_get_paths", (PyCFunction)Vim_GetPaths, METH_NOARGS, "Get &rtp-based additions to sys.path"},
1734 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001735};
1736
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001737/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001738 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001739 */
1740
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02001741DEFINE_PY_TYPE_OBJECT(IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001742
1743typedef PyObject *(*nextfun)(void **);
1744typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001745typedef int (*traversefun)(void *, visitproc, void *);
1746typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001747
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001748// Main purpose of this object is removing the need for do python
1749// initialization (i.e. PyType_Ready and setting type attributes) for a big
1750// bunch of objects.
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001751typedef struct
1752{
1753 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001754 void *cur;
1755 nextfun next;
1756 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001757 traversefun traverse;
1758 clearfun clear;
Bram Moolenaar423a85a2020-08-29 12:57:16 +02001759 PyObject *iter_object;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001760} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001761
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001762 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001763IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
Bram Moolenaar423a85a2020-08-29 12:57:16 +02001764 clearfun clear, PyObject *iter_object)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001765{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001766 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001767
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02001768 self = PyObject_GC_New(IterObject, IterTypePtr);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001769 self->cur = start;
1770 self->next = next;
1771 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001772 self->traverse = traverse;
1773 self->clear = clear;
Bram Moolenaar423a85a2020-08-29 12:57:16 +02001774 self->iter_object = iter_object;
1775
1776 if (iter_object)
1777 Py_INCREF(iter_object);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001778
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001779 return (PyObject *)(self);
1780}
1781
1782 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001783IterDestructor(PyObject *self_obj)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001784{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001785 IterObject *self = (IterObject*)self_obj;
Bram Moolenaar423a85a2020-08-29 12:57:16 +02001786 if (self->iter_object)
1787 Py_DECREF(self->iter_object);
Bram Moolenaar774267b2013-05-21 20:51:59 +02001788 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02001789 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +02001790 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001791}
1792
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001793 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001794IterTraverse(PyObject *self_obj, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001795{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001796 IterObject *self = (IterObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001797 if (self->traverse != NULL)
1798 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001799 else
1800 return 0;
1801}
1802
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001803// Mac OSX defines clear() somewhere.
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001804#ifdef clear
1805# undef clear
1806#endif
1807
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001808 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001809IterClear(PyObject *self_obj)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001810{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001811 IterObject *self = (IterObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001812 if (self->clear != NULL)
1813 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001814 else
1815 return 0;
1816}
1817
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001818 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001819IterNext(PyObject *self_obj)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001820{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001821 IterObject *self = (IterObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001822 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001823}
1824
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001825 static PyObject *
1826IterIter(PyObject *self)
1827{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +02001828 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001829 return self;
1830}
Bram Moolenaardfa38d42013-05-15 13:38:47 +02001831
Bram Moolenaardb913952012-06-29 12:54:53 +02001832typedef struct pylinkedlist_S {
1833 struct pylinkedlist_S *pll_next;
1834 struct pylinkedlist_S *pll_prev;
1835 PyObject *pll_obj;
1836} pylinkedlist_T;
1837
1838static pylinkedlist_T *lastdict = NULL;
1839static pylinkedlist_T *lastlist = NULL;
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01001840static pylinkedlist_T *lasttuple = NULL;
Bram Moolenaar8110a092016-04-14 15:56:09 +02001841static pylinkedlist_T *lastfunc = NULL;
Bram Moolenaardb913952012-06-29 12:54:53 +02001842
1843 static void
1844pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
1845{
1846 if (ref->pll_prev == NULL)
1847 {
1848 if (ref->pll_next == NULL)
1849 {
1850 *last = NULL;
1851 return;
1852 }
1853 }
1854 else
1855 ref->pll_prev->pll_next = ref->pll_next;
1856
1857 if (ref->pll_next == NULL)
1858 *last = ref->pll_prev;
1859 else
1860 ref->pll_next->pll_prev = ref->pll_prev;
1861}
1862
1863 static void
1864pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
1865{
1866 if (*last == NULL)
1867 ref->pll_prev = NULL;
1868 else
1869 {
1870 (*last)->pll_next = ref;
1871 ref->pll_prev = *last;
1872 }
1873 ref->pll_next = NULL;
1874 ref->pll_obj = self;
1875 *last = ref;
1876}
1877
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02001878DEFINE_PY_TYPE_OBJECT(DictionaryType);
Bram Moolenaardb913952012-06-29 12:54:53 +02001879
1880typedef struct
1881{
1882 PyObject_HEAD
1883 dict_T *dict;
1884 pylinkedlist_T ref;
1885} DictionaryObject;
1886
Bram Moolenaara9922d62013-05-30 13:01:18 +02001887static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
1888
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02001889#define NEW_DICTIONARY(dict) DictionaryNew(DictionaryTypePtr, dict)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001890
Bram Moolenaardb913952012-06-29 12:54:53 +02001891 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001892DictionaryNew(PyTypeObject *subtype, dict_T *dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02001893{
1894 DictionaryObject *self;
1895
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02001896 self = (DictionaryObject *) Py_TYPE_GET_TP_ALLOC(subtype)(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001897 if (self == NULL)
1898 return NULL;
1899 self->dict = dict;
1900 ++dict->dv_refcount;
1901
1902 pyll_add((PyObject *)(self), &self->ref, &lastdict);
1903
1904 return (PyObject *)(self);
1905}
1906
Bram Moolenaara9922d62013-05-30 13:01:18 +02001907 static dict_T *
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001908py_dict_alloc(void)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001909{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001910 dict_T *ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001911
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001912 if (!(ret = dict_alloc()))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001913 {
1914 PyErr_NoMemory();
1915 return NULL;
1916 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001917 ++ret->dv_refcount;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001918
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001919 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001920}
1921
1922 static PyObject *
1923DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
1924{
1925 DictionaryObject *self;
1926 dict_T *dict;
1927
1928 if (!(dict = py_dict_alloc()))
1929 return NULL;
1930
1931 self = (DictionaryObject *) DictionaryNew(subtype, dict);
1932
1933 --dict->dv_refcount;
1934
1935 if (kwargs || PyTuple_Size(args))
1936 {
1937 PyObject *tmp;
1938 if (!(tmp = DictionaryUpdate(self, args, kwargs)))
1939 {
1940 Py_DECREF(self);
1941 return NULL;
1942 }
1943
1944 Py_DECREF(tmp);
1945 }
1946
1947 return (PyObject *)(self);
1948}
1949
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001950 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001951DictionaryDestructor(PyObject *self_obj)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001952{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001953 DictionaryObject *self = (DictionaryObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001954 pyll_remove(&self->ref, &lastdict);
1955 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001956
1957 DESTRUCTOR_FINISH(self);
1958}
1959
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001960static char *DictionaryAttrs[] = {
1961 "locked", "scope",
1962 NULL
1963};
1964
1965 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02001966DictionaryDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001967{
1968 return ObjectDir(self, DictionaryAttrs);
1969}
1970
Bram Moolenaardb913952012-06-29 12:54:53 +02001971 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001972DictionarySetattr(PyObject *self_obj, char *name, PyObject *valObject)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001973{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02001974 DictionaryObject *self = (DictionaryObject*)self_obj;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001975 if (valObject == NULL)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001976 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001977 PyErr_SET_STRING(PyExc_AttributeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001978 N_("cannot delete vim.Dictionary attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001979 return -1;
1980 }
1981
1982 if (strcmp(name, "locked") == 0)
1983 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001984 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001985 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001986 PyErr_SET_STRING(PyExc_TypeError,
1987 N_("cannot modify fixed dictionary"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001988 return -1;
1989 }
1990 else
1991 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001992 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarb983f752013-05-15 16:11:50 +02001993 if (istrue == -1)
1994 return -1;
1995 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001996 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001997 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001998 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001999 }
2000 return 0;
2001 }
2002 else
2003 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002004 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name);
Bram Moolenaar66b79852012-09-21 14:00:35 +02002005 return -1;
2006 }
2007}
2008
2009 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002010DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02002011{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002012 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +02002013}
2014
Bram Moolenaara9922d62013-05-30 13:01:18 +02002015#define DICT_FLAG_HAS_DEFAULT 0x01
2016#define DICT_FLAG_POP 0x02
2017#define DICT_FLAG_NONE_DEFAULT 0x04
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002018#define DICT_FLAG_RETURN_BOOL 0x08 // Incompatible with DICT_FLAG_POP
Bram Moolenaara9922d62013-05-30 13:01:18 +02002019#define DICT_FLAG_RETURN_PAIR 0x10
2020
Bram Moolenaardb913952012-06-29 12:54:53 +02002021 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02002022_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
Bram Moolenaardb913952012-06-29 12:54:53 +02002023{
Bram Moolenaara9922d62013-05-30 13:01:18 +02002024 PyObject *keyObject;
2025 PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002026 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02002027 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +02002028 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002029 dict_T *dict = self->dict;
2030 hashitem_T *hi;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002031 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02002032
Bram Moolenaara9922d62013-05-30 13:01:18 +02002033 if (flags & DICT_FLAG_HAS_DEFAULT)
2034 {
2035 if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
2036 return NULL;
2037 }
2038 else
2039 keyObject = args;
2040
2041 if (flags & DICT_FLAG_RETURN_BOOL)
2042 defObject = Py_False;
2043
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002044 if (!(key = StringToChars(keyObject, &todecref)))
2045 return NULL;
2046
2047 if (*key == NUL)
2048 {
2049 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002050 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002051 return NULL;
2052 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002053
Bram Moolenaara9922d62013-05-30 13:01:18 +02002054 hi = hash_find(&dict->dv_hashtab, key);
Bram Moolenaar231e1a12012-09-05 18:45:28 +02002055
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002056 Py_XDECREF(todecref);
Bram Moolenaar696c2112012-09-21 13:43:14 +02002057
Bram Moolenaara9922d62013-05-30 13:01:18 +02002058 if (HASHITEM_EMPTY(hi))
Bram Moolenaar231e1a12012-09-05 18:45:28 +02002059 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002060 if (defObject)
2061 {
2062 Py_INCREF(defObject);
2063 return defObject;
2064 }
2065 else
2066 {
2067 PyErr_SetObject(PyExc_KeyError, keyObject);
2068 return NULL;
2069 }
2070 }
2071 else if (flags & DICT_FLAG_RETURN_BOOL)
2072 {
Bram Moolenaar0e4eebd2014-02-12 22:08:49 +01002073 ret = Py_True;
2074 Py_INCREF(ret);
2075 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002076 }
2077
2078 di = dict_lookup(hi);
2079
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002080 if (!(ret = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002081 return NULL;
2082
2083 if (flags & DICT_FLAG_POP)
2084 {
2085 if (dict->dv_lock)
2086 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002087 RAISE_LOCKED_DICTIONARY;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002088 Py_DECREF(ret);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002089 return NULL;
2090 }
2091
Bram Moolenaaref2c3252022-11-25 16:31:51 +00002092 hash_remove(&dict->dv_hashtab, hi, "Python remove variable");
Bram Moolenaara9922d62013-05-30 13:01:18 +02002093 dictitem_free(di);
2094 }
2095
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002096 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002097}
2098
2099 static PyObject *
2100DictionaryItem(DictionaryObject *self, PyObject *keyObject)
2101{
2102 return _DictionaryItem(self, keyObject, 0);
2103}
2104
2105 static int
2106DictionaryContains(DictionaryObject *self, PyObject *keyObject)
2107{
2108 PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002109 int ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002110
Bram Moolenaarba2d7ff2013-11-04 00:34:53 +01002111 if (rObj == NULL)
2112 return -1;
2113
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002114 ret = (rObj == Py_True);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002115
Bram Moolenaardee2e312013-06-23 16:35:47 +02002116 Py_DECREF(rObj);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002117
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002118 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002119}
2120
2121typedef struct
2122{
Bram Moolenaar1f22cc52020-07-14 21:08:49 +02002123 int dii_changed;
2124 hashtab_T *dii_ht;
2125 hashitem_T *dii_hi;
2126 long_u dii_todo;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002127} dictiterinfo_T;
2128
2129 static PyObject *
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02002130DictionaryIterNext(void **arg)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002131{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002132 PyObject *ret;
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02002133 dictiterinfo_T **dii = (dictiterinfo_T**)arg;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002134
Bram Moolenaar1f22cc52020-07-14 21:08:49 +02002135 if (!(*dii)->dii_todo)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002136 return NULL;
2137
Bram Moolenaar1f22cc52020-07-14 21:08:49 +02002138 if ((*dii)->dii_ht->ht_changed != (*dii)->dii_changed)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002139 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002140 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002141 N_("hashtab changed during iteration"));
Bram Moolenaar231e1a12012-09-05 18:45:28 +02002142 return NULL;
2143 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002144
Bram Moolenaar1f22cc52020-07-14 21:08:49 +02002145 while (((*dii)->dii_todo) && HASHITEM_EMPTY((*dii)->dii_hi))
2146 ++((*dii)->dii_hi);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002147
Bram Moolenaar1f22cc52020-07-14 21:08:49 +02002148 --((*dii)->dii_todo);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002149
Bram Moolenaar1f22cc52020-07-14 21:08:49 +02002150 if (!(ret = PyBytes_FromString((char *)(*dii)->dii_hi->hi_key)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002151 return NULL;
2152
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002153 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002154}
2155
2156 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02002157DictionaryIter(PyObject *self_obj)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002158{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02002159 DictionaryObject *self = (DictionaryObject*)self_obj;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002160 dictiterinfo_T *dii;
2161 hashtab_T *ht;
2162
2163 if (!(dii = PyMem_New(dictiterinfo_T, 1)))
2164 {
2165 PyErr_NoMemory();
2166 return NULL;
2167 }
2168
2169 ht = &self->dict->dv_hashtab;
Bram Moolenaar1f22cc52020-07-14 21:08:49 +02002170 dii->dii_changed = ht->ht_changed;
2171 dii->dii_ht = ht;
2172 dii->dii_hi = ht->ht_array;
2173 dii->dii_todo = ht->ht_used;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002174
2175 return IterNew(dii,
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02002176 PyMem_Free, DictionaryIterNext,
Bram Moolenaar423a85a2020-08-29 12:57:16 +02002177 NULL, NULL, (PyObject *)self);
Bram Moolenaardb913952012-06-29 12:54:53 +02002178}
2179
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02002180 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002181DictionaryAssItem(
2182 DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +02002183{
2184 char_u *key;
2185 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02002186 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02002187 dictitem_T *di;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002188 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02002189
Bram Moolenaarb38caae2013-05-29 22:39:52 +02002190 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +02002191 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002192 RAISE_LOCKED_DICTIONARY;
Bram Moolenaardb913952012-06-29 12:54:53 +02002193 return -1;
2194 }
2195
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002196 if (!(key = StringToChars(keyObject, &todecref)))
2197 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002198
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002199 if (*key == NUL)
2200 {
2201 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar78b59572013-06-02 18:54:21 +02002202 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002203 return -1;
2204 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002205
Bram Moolenaarb38caae2013-05-29 22:39:52 +02002206 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +02002207
2208 if (valObject == NULL)
2209 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02002210 hashitem_T *hi;
2211
Bram Moolenaardb913952012-06-29 12:54:53 +02002212 if (di == NULL)
2213 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002214 Py_XDECREF(todecref);
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002215 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02002216 return -1;
2217 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02002218 hi = hash_find(&dict->dv_hashtab, di->di_key);
Bram Moolenaaref2c3252022-11-25 16:31:51 +00002219 hash_remove(&dict->dv_hashtab, hi, "Python remove item");
Bram Moolenaardb913952012-06-29 12:54:53 +02002220 dictitem_free(di);
Bram Moolenaar78b59572013-06-02 18:54:21 +02002221 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02002222 return 0;
2223 }
2224
2225 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaar78b59572013-06-02 18:54:21 +02002226 {
2227 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02002228 return -1;
Bram Moolenaar78b59572013-06-02 18:54:21 +02002229 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002230
2231 if (di == NULL)
2232 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002233 if (!(di = dictitem_alloc(key)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002234 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002235 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02002236 PyErr_NoMemory();
2237 return -1;
2238 }
Bram Moolenaara9922d62013-05-30 13:01:18 +02002239 di->di_tv.v_type = VAR_UNKNOWN;
Bram Moolenaardb913952012-06-29 12:54:53 +02002240
Bram Moolenaarb38caae2013-05-29 22:39:52 +02002241 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02002242 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002243 dictitem_free(di);
Bram Moolenaarc476e522013-06-23 13:46:40 +02002244 RAISE_KEY_ADD_FAIL(key);
2245 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02002246 return -1;
2247 }
2248 }
2249 else
2250 clear_tv(&di->di_tv);
2251
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002252 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02002253
2254 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002255 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002256 return 0;
2257}
2258
Bram Moolenaara9922d62013-05-30 13:01:18 +02002259typedef PyObject *(*hi_to_py)(hashitem_T *);
2260
Bram Moolenaardb913952012-06-29 12:54:53 +02002261 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02002262DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
Bram Moolenaardb913952012-06-29 12:54:53 +02002263{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002264 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02002265 long_u todo = dict->dv_hashtab.ht_used;
2266 Py_ssize_t i = 0;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002267 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02002268 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002269 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02002270
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002271 ret = PyList_New(todo);
Bram Moolenaardb913952012-06-29 12:54:53 +02002272 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
2273 {
2274 if (!HASHITEM_EMPTY(hi))
2275 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002276 if (!(newObj = hiconvert(hi)))
2277 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002278 Py_DECREF(ret);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002279 return NULL;
2280 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002281 PyList_SET_ITEM(ret, i, newObj);
Bram Moolenaardb913952012-06-29 12:54:53 +02002282 --todo;
2283 ++i;
2284 }
2285 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002286 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02002287}
2288
Bram Moolenaara9922d62013-05-30 13:01:18 +02002289 static PyObject *
2290dict_key(hashitem_T *hi)
2291{
2292 return PyBytes_FromString((char *)(hi->hi_key));
2293}
2294
2295 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02002296DictionaryListKeys(DictionaryObject *self, PyObject *args UNUSED)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002297{
2298 return DictionaryListObjects(self, dict_key);
2299}
2300
2301 static PyObject *
2302dict_val(hashitem_T *hi)
2303{
2304 dictitem_T *di;
2305
2306 di = dict_lookup(hi);
2307 return ConvertToPyObject(&di->di_tv);
2308}
2309
2310 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02002311DictionaryListValues(DictionaryObject *self, PyObject *args UNUSED)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002312{
2313 return DictionaryListObjects(self, dict_val);
2314}
2315
2316 static PyObject *
2317dict_item(hashitem_T *hi)
2318{
2319 PyObject *keyObject;
2320 PyObject *valObject;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002321 PyObject *ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002322
2323 if (!(keyObject = dict_key(hi)))
2324 return NULL;
2325
2326 if (!(valObject = dict_val(hi)))
2327 {
2328 Py_DECREF(keyObject);
2329 return NULL;
2330 }
2331
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002332 ret = Py_BuildValue("(OO)", keyObject, valObject);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002333
2334 Py_DECREF(keyObject);
2335 Py_DECREF(valObject);
2336
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002337 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002338}
2339
2340 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02002341DictionaryListItems(DictionaryObject *self, PyObject *args UNUSED)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002342{
2343 return DictionaryListObjects(self, dict_item);
2344}
2345
2346 static PyObject *
2347DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
2348{
2349 dict_T *dict = self->dict;
2350
2351 if (dict->dv_lock)
2352 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002353 RAISE_LOCKED_DICTIONARY;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002354 return NULL;
2355 }
2356
2357 if (kwargs)
2358 {
2359 typval_T tv;
2360
2361 if (ConvertFromPyMapping(kwargs, &tv) == -1)
2362 return NULL;
2363
2364 VimTryStart();
Bram Moolenaar7a3fe3e2021-07-22 14:58:47 +02002365 dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force", NULL);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002366 clear_tv(&tv);
2367 if (VimTryEnd())
2368 return NULL;
2369 }
2370 else
2371 {
Bram Moolenaar2d5f38f2014-02-11 18:47:27 +01002372 PyObject *obj = NULL;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002373
Bram Moolenaar2d5f38f2014-02-11 18:47:27 +01002374 if (!PyArg_ParseTuple(args, "|O", &obj))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002375 return NULL;
2376
Bram Moolenaar2d5f38f2014-02-11 18:47:27 +01002377 if (obj == NULL)
2378 {
2379 Py_INCREF(Py_None);
2380 return Py_None;
2381 }
2382
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002383 if (PyObject_HasAttrString(obj, "keys"))
2384 return DictionaryUpdate(self, NULL, obj);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002385 else
2386 {
2387 PyObject *iterator;
2388 PyObject *item;
2389
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002390 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002391 return NULL;
2392
2393 while ((item = PyIter_Next(iterator)))
2394 {
2395 PyObject *fast;
2396 PyObject *keyObject;
2397 PyObject *valObject;
2398 PyObject *todecref;
2399 char_u *key;
2400 dictitem_T *di;
Bram Moolenaar9ed7d342017-11-09 22:10:33 +01002401 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002402
2403 if (!(fast = PySequence_Fast(item, "")))
2404 {
2405 Py_DECREF(iterator);
2406 Py_DECREF(item);
2407 return NULL;
2408 }
2409
2410 Py_DECREF(item);
2411
2412 if (PySequence_Fast_GET_SIZE(fast) != 2)
2413 {
2414 Py_DECREF(iterator);
2415 Py_DECREF(fast);
Bram Moolenaarc476e522013-06-23 13:46:40 +02002416 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002417 N_("expected sequence element of size 2, "
2418 "but got sequence of size %d"),
Bram Moolenaardee2e312013-06-23 16:35:47 +02002419 (int) PySequence_Fast_GET_SIZE(fast));
Bram Moolenaara9922d62013-05-30 13:01:18 +02002420 return NULL;
2421 }
2422
2423 keyObject = PySequence_Fast_GET_ITEM(fast, 0);
2424
2425 if (!(key = StringToChars(keyObject, &todecref)))
2426 {
2427 Py_DECREF(iterator);
2428 Py_DECREF(fast);
2429 return NULL;
2430 }
2431
2432 di = dictitem_alloc(key);
2433
2434 Py_XDECREF(todecref);
2435
2436 if (di == NULL)
2437 {
2438 Py_DECREF(fast);
2439 Py_DECREF(iterator);
2440 PyErr_NoMemory();
2441 return NULL;
2442 }
Bram Moolenaara9922d62013-05-30 13:01:18 +02002443 di->di_tv.v_type = VAR_UNKNOWN;
2444
2445 valObject = PySequence_Fast_GET_ITEM(fast, 1);
2446
2447 if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
2448 {
2449 Py_DECREF(iterator);
2450 Py_DECREF(fast);
2451 dictitem_free(di);
2452 return NULL;
2453 }
2454
2455 Py_DECREF(fast);
2456
Bram Moolenaar9ed7d342017-11-09 22:10:33 +01002457 hi = hash_find(&dict->dv_hashtab, di->di_key);
2458 if (!HASHITEM_EMPTY(hi) || dict_add(dict, di) == FAIL)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002459 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002460 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002461 Py_DECREF(iterator);
2462 dictitem_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002463 return NULL;
2464 }
2465 }
2466
2467 Py_DECREF(iterator);
2468
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002469 // Iterator may have finished due to an exception
Bram Moolenaara9922d62013-05-30 13:01:18 +02002470 if (PyErr_Occurred())
2471 return NULL;
2472 }
2473 }
2474 Py_INCREF(Py_None);
2475 return Py_None;
2476}
2477
2478 static PyObject *
2479DictionaryGet(DictionaryObject *self, PyObject *args)
2480{
2481 return _DictionaryItem(self, args,
2482 DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
2483}
2484
2485 static PyObject *
2486DictionaryPop(DictionaryObject *self, PyObject *args)
2487{
2488 return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
2489}
2490
2491 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02002492DictionaryPopItem(DictionaryObject *self, PyObject *args UNUSED)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002493{
Bram Moolenaarde71b562013-06-02 17:41:54 +02002494 hashitem_T *hi;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002495 PyObject *ret;
Bram Moolenaarde71b562013-06-02 17:41:54 +02002496 PyObject *valObject;
2497 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002498
Bram Moolenaarde71b562013-06-02 17:41:54 +02002499 if (self->dict->dv_hashtab.ht_used == 0)
2500 {
2501 PyErr_SetNone(PyExc_KeyError);
2502 return NULL;
2503 }
2504
2505 hi = self->dict->dv_hashtab.ht_array;
2506 while (HASHITEM_EMPTY(hi))
2507 ++hi;
2508
2509 di = dict_lookup(hi);
2510
2511 if (!(valObject = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002512 return NULL;
2513
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002514 if (!(ret = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, valObject)))
Bram Moolenaarde71b562013-06-02 17:41:54 +02002515 {
2516 Py_DECREF(valObject);
2517 return NULL;
2518 }
2519
Bram Moolenaaref2c3252022-11-25 16:31:51 +00002520 hash_remove(&self->dict->dv_hashtab, hi, "Python pop item");
Bram Moolenaarde71b562013-06-02 17:41:54 +02002521 dictitem_free(di);
2522
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002523 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002524}
2525
2526 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02002527DictionaryHasKey(DictionaryObject *self, PyObject *keyObject)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002528{
Bram Moolenaara9922d62013-05-30 13:01:18 +02002529 return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
2530}
2531
2532static PySequenceMethods DictionaryAsSeq = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002533 0, // sq_length
2534 0, // sq_concat
2535 0, // sq_repeat
2536 0, // sq_item
2537 0, // sq_slice
2538 0, // sq_ass_item
2539 0, // sq_ass_slice
2540 (objobjproc) DictionaryContains, // sq_contains
2541 0, // sq_inplace_concat
2542 0, // sq_inplace_repeat
Bram Moolenaara9922d62013-05-30 13:01:18 +02002543};
2544
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002545static PyMappingMethods DictionaryAsMapping = {
2546 (lenfunc) DictionaryLength,
2547 (binaryfunc) DictionaryItem,
2548 (objobjargproc) DictionaryAssItem,
2549};
2550
Bram Moolenaardb913952012-06-29 12:54:53 +02002551static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02002552 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02002553 {"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
2554 {"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02002555 {"update", (PyCFunction)(void *)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02002556 {"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
2557 {"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
Bram Moolenaarde71b562013-06-02 17:41:54 +02002558 {"popitem", (PyCFunction)DictionaryPopItem, METH_NOARGS, ""},
Bram Moolenaar389a1792013-06-23 13:00:44 +02002559 {"has_key", (PyCFunction)DictionaryHasKey, METH_O, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002560 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
2561 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002562};
2563
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02002564DEFINE_PY_TYPE_OBJECT(ListType);
Bram Moolenaardb913952012-06-29 12:54:53 +02002565
2566typedef struct
2567{
2568 PyObject_HEAD
2569 list_T *list;
2570 pylinkedlist_T ref;
2571} ListObject;
2572
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02002573#define NEW_LIST(list) ListNew(ListTypePtr, list)
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002574
Bram Moolenaardb913952012-06-29 12:54:53 +02002575 static PyObject *
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002576ListNew(PyTypeObject *subtype, list_T *list)
Bram Moolenaardb913952012-06-29 12:54:53 +02002577{
2578 ListObject *self;
2579
Bram Moolenaarab589462020-07-06 21:03:06 +02002580 if (list == NULL)
2581 return NULL;
2582
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02002583 self = (ListObject *) Py_TYPE_GET_TP_ALLOC(subtype)(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02002584 if (self == NULL)
2585 return NULL;
2586 self->list = list;
2587 ++list->lv_refcount;
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02002588 CHECK_LIST_MATERIALIZE(list);
Bram Moolenaardb913952012-06-29 12:54:53 +02002589
2590 pyll_add((PyObject *)(self), &self->ref, &lastlist);
2591
2592 return (PyObject *)(self);
2593}
2594
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002595 static list_T *
Bram Moolenaarfb97f282013-07-09 17:42:46 +02002596py_list_alloc(void)
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002597{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002598 list_T *ret;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002599
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002600 if (!(ret = list_alloc()))
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002601 {
2602 PyErr_NoMemory();
2603 return NULL;
2604 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002605 ++ret->lv_refcount;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002606
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002607 return ret;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002608}
2609
2610 static int
2611list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
2612{
2613 PyObject *iterator;
2614 PyObject *item;
2615 listitem_T *li;
2616
2617 if (!(iterator = PyObject_GetIter(obj)))
2618 return -1;
2619
2620 while ((item = PyIter_Next(iterator)))
2621 {
2622 if (!(li = listitem_alloc()))
2623 {
2624 PyErr_NoMemory();
2625 Py_DECREF(item);
2626 Py_DECREF(iterator);
2627 return -1;
2628 }
2629 li->li_tv.v_lock = 0;
2630 li->li_tv.v_type = VAR_UNKNOWN;
2631
2632 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
2633 {
2634 Py_DECREF(item);
2635 Py_DECREF(iterator);
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002636 listitem_free(l, li);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002637 return -1;
2638 }
2639
2640 Py_DECREF(item);
2641
2642 list_append(l, li);
2643 }
2644
2645 Py_DECREF(iterator);
2646
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002647 // Iterator may have finished due to an exception
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002648 if (PyErr_Occurred())
2649 return -1;
2650
2651 return 0;
2652}
2653
2654 static PyObject *
2655ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2656{
2657 list_T *list;
2658 PyObject *obj = NULL;
2659
2660 if (kwargs)
2661 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002662 PyErr_SET_STRING(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002663 N_("list constructor does not accept keyword arguments"));
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002664 return NULL;
2665 }
2666
2667 if (!PyArg_ParseTuple(args, "|O", &obj))
2668 return NULL;
2669
2670 if (!(list = py_list_alloc()))
2671 return NULL;
2672
2673 if (obj)
2674 {
2675 PyObject *lookup_dict;
2676
2677 if (!(lookup_dict = PyDict_New()))
2678 {
2679 list_unref(list);
2680 return NULL;
2681 }
2682
2683 if (list_py_concat(list, obj, lookup_dict) == -1)
2684 {
2685 Py_DECREF(lookup_dict);
2686 list_unref(list);
2687 return NULL;
2688 }
2689
2690 Py_DECREF(lookup_dict);
2691 }
2692
2693 return ListNew(subtype, list);
2694}
2695
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002696 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02002697ListDestructor(PyObject *self_obj)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002698{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02002699 ListObject *self = (ListObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002700 pyll_remove(&self->ref, &lastlist);
2701 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002702
2703 DESTRUCTOR_FINISH(self);
2704}
2705
Bram Moolenaardb913952012-06-29 12:54:53 +02002706 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002707ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02002708{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002709 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02002710}
2711
2712 static PyObject *
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002713ListIndex(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02002714{
2715 listitem_T *li;
2716
Bram Moolenaard6e39182013-05-21 18:30:34 +02002717 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02002718 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002719 PyErr_SET_STRING(PyExc_IndexError, N_("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002720 return NULL;
2721 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02002722 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002723 if (li == NULL)
2724 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002725 // No more suitable format specifications in python-2.3
Bram Moolenaar86181df2020-05-11 23:14:04 +02002726 PyErr_VIM_FORMAT(N_("internal error: failed to get Vim list item %d"),
Bram Moolenaarc476e522013-06-23 13:46:40 +02002727 (int) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002728 return NULL;
2729 }
2730 return ConvertToPyObject(&li->li_tv);
2731}
2732
Bram Moolenaardb913952012-06-29 12:54:53 +02002733 static PyObject *
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002734ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t step,
2735 Py_ssize_t slicelen)
Bram Moolenaardb913952012-06-29 12:54:53 +02002736{
2737 PyInt i;
Bram Moolenaardb913952012-06-29 12:54:53 +02002738 PyObject *list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002739
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002740 if (step == 0)
2741 {
2742 PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero"));
2743 return NULL;
2744 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002745
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002746 list = PyList_New(slicelen);
Bram Moolenaardb913952012-06-29 12:54:53 +02002747 if (list == NULL)
2748 return NULL;
2749
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002750 for (i = 0; i < slicelen; ++i)
Bram Moolenaardb913952012-06-29 12:54:53 +02002751 {
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002752 PyObject *item;
2753
2754 item = ListIndex(self, first + i*step);
Bram Moolenaardb913952012-06-29 12:54:53 +02002755 if (item == NULL)
2756 {
2757 Py_DECREF(list);
2758 return NULL;
2759 }
2760
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002761 PyList_SET_ITEM(list, i, item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002762 }
2763
2764 return list;
2765}
2766
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002767 static PyObject *
2768ListItem(ListObject *self, PyObject* idx)
2769{
2770#if PY_MAJOR_VERSION < 3
2771 if (PyInt_Check(idx))
2772 {
2773 long _idx = PyInt_AsLong(idx);
2774 return ListIndex(self, _idx);
2775 }
2776 else
2777#endif
2778 if (PyLong_Check(idx))
2779 {
2780 long _idx = PyLong_AsLong(idx);
2781 return ListIndex(self, _idx);
2782 }
2783 else if (PySlice_Check(idx))
2784 {
2785 Py_ssize_t start, stop, step, slicelen;
2786
Bram Moolenaar922a4662014-03-30 16:11:43 +02002787 if (PySlice_GetIndicesEx((PySliceObject_T *)idx, ListLength(self),
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002788 &start, &stop, &step, &slicelen) < 0)
2789 return NULL;
2790 return ListSlice(self, start, step, slicelen);
2791 }
2792 else
2793 {
2794 RAISE_INVALID_INDEX_TYPE(idx);
2795 return NULL;
2796 }
2797}
2798
2799 static void
2800list_restore(Py_ssize_t numadded, Py_ssize_t numreplaced, Py_ssize_t slicelen,
2801 list_T *l, listitem_T **lis, listitem_T *lastaddedli)
2802{
2803 while (numreplaced--)
2804 {
2805 list_insert(l, lis[numreplaced], lis[slicelen + numreplaced]);
2806 listitem_remove(l, lis[slicelen + numreplaced]);
2807 }
2808 while (numadded--)
2809 {
2810 listitem_T *next;
2811
2812 next = lastaddedli->li_prev;
2813 listitem_remove(l, lastaddedli);
2814 lastaddedli = next;
2815 }
2816}
2817
2818 static int
2819ListAssSlice(ListObject *self, Py_ssize_t first,
2820 Py_ssize_t step, Py_ssize_t slicelen, PyObject *obj)
2821{
2822 PyObject *iterator;
2823 PyObject *item;
2824 listitem_T *li;
2825 listitem_T *lastaddedli = NULL;
2826 listitem_T *next;
2827 typval_T v;
2828 list_T *l = self->list;
2829 PyInt i;
2830 PyInt j;
2831 PyInt numreplaced = 0;
2832 PyInt numadded = 0;
2833 PyInt size;
Bram Moolenaar3b522612014-02-11 16:00:35 +01002834 listitem_T **lis = NULL;
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002835
2836 size = ListLength(self);
2837
2838 if (l->lv_lock)
2839 {
2840 RAISE_LOCKED_LIST;
2841 return -1;
2842 }
2843
2844 if (step == 0)
2845 {
2846 PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero"));
2847 return -1;
2848 }
2849
2850 if (step != 1 && slicelen == 0)
2851 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002852 // Nothing to do. Only error out if obj has some items.
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002853 int ret = 0;
2854
2855 if (obj == NULL)
2856 return 0;
2857
2858 if (!(iterator = PyObject_GetIter(obj)))
2859 return -1;
2860
2861 if ((item = PyIter_Next(iterator)))
2862 {
2863 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar4de6a212014-03-08 16:13:44 +01002864 N_("attempt to assign sequence of size greater than %d "
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002865 "to extended slice"), 0);
2866 Py_DECREF(item);
2867 ret = -1;
2868 }
2869 Py_DECREF(iterator);
2870 return ret;
2871 }
2872
2873 if (obj != NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002874 // XXX May allocate zero bytes.
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002875 if (!(lis = PyMem_New(listitem_T *, slicelen * 2)))
2876 {
2877 PyErr_NoMemory();
2878 return -1;
2879 }
2880
2881 if (first == size)
2882 li = NULL;
2883 else
2884 {
2885 li = list_find(l, (long) first);
2886 if (li == NULL)
2887 {
Bram Moolenaar86181df2020-05-11 23:14:04 +02002888 PyErr_VIM_FORMAT(N_("internal error: no Vim list item %d"),
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002889 (int)first);
2890 if (obj != NULL)
2891 PyMem_Free(lis);
2892 return -1;
2893 }
2894 i = slicelen;
2895 while (i-- && li != NULL)
2896 {
2897 j = step;
2898 next = li;
2899 if (step > 0)
2900 while (next != NULL && ((next = next->li_next) != NULL) && --j);
2901 else
2902 while (next != NULL && ((next = next->li_prev) != NULL) && ++j);
2903
2904 if (obj == NULL)
2905 listitem_remove(l, li);
2906 else
2907 lis[slicelen - i - 1] = li;
2908
2909 li = next;
2910 }
2911 if (li == NULL && i != -1)
2912 {
2913 PyErr_SET_VIM(N_("internal error: not enough list items"));
2914 if (obj != NULL)
2915 PyMem_Free(lis);
2916 return -1;
2917 }
2918 }
2919
2920 if (obj == NULL)
2921 return 0;
2922
2923 if (!(iterator = PyObject_GetIter(obj)))
2924 {
2925 PyMem_Free(lis);
2926 return -1;
2927 }
2928
2929 i = 0;
2930 while ((item = PyIter_Next(iterator)))
2931 {
2932 if (ConvertFromPyObject(item, &v) == -1)
2933 {
2934 Py_DECREF(iterator);
2935 Py_DECREF(item);
2936 PyMem_Free(lis);
2937 return -1;
2938 }
2939 Py_DECREF(item);
2940 if (list_insert_tv(l, &v, numreplaced < slicelen
2941 ? lis[numreplaced]
2942 : li) == FAIL)
2943 {
2944 clear_tv(&v);
2945 PyErr_SET_VIM(N_("internal error: failed to add item to list"));
2946 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2947 PyMem_Free(lis);
2948 return -1;
2949 }
2950 if (numreplaced < slicelen)
2951 {
2952 lis[slicelen + numreplaced] = lis[numreplaced]->li_prev;
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02002953 vimlist_remove(l, lis[numreplaced], lis[numreplaced]);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002954 numreplaced++;
2955 }
2956 else
2957 {
2958 if (li)
2959 lastaddedli = li->li_prev;
2960 else
Bram Moolenaar0ff6aad2020-01-29 21:27:21 +01002961 lastaddedli = l->lv_u.mat.lv_last;
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002962 numadded++;
2963 }
2964 clear_tv(&v);
2965 if (step != 1 && i >= slicelen)
2966 {
2967 Py_DECREF(iterator);
2968 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar4de6a212014-03-08 16:13:44 +01002969 N_("attempt to assign sequence of size greater than %d "
Bram Moolenaar403b3cf2014-02-15 15:59:03 +01002970 "to extended slice"), (int) slicelen);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002971 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2972 PyMem_Free(lis);
2973 return -1;
2974 }
2975 ++i;
2976 }
2977 Py_DECREF(iterator);
2978
2979 if (step != 1 && i != slicelen)
2980 {
2981 PyErr_FORMAT2(PyExc_ValueError,
Bram Moolenaar403b3cf2014-02-15 15:59:03 +01002982 N_("attempt to assign sequence of size %d to extended slice "
2983 "of size %d"), (int) i, (int) slicelen);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002984 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2985 PyMem_Free(lis);
2986 return -1;
2987 }
2988
2989 if (PyErr_Occurred())
2990 {
2991 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2992 PyMem_Free(lis);
2993 return -1;
2994 }
2995
2996 for (i = 0; i < numreplaced; i++)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01002997 listitem_free(l, lis[i]);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002998 if (step == 1)
2999 for (i = numreplaced; i < slicelen; i++)
3000 listitem_remove(l, lis[i]);
3001
3002 PyMem_Free(lis);
3003
3004 return 0;
3005}
3006
3007 static int
3008ListAssIndex(ListObject *self, Py_ssize_t index, PyObject *obj)
3009{
3010 typval_T tv;
3011 list_T *l = self->list;
3012 listitem_T *li;
3013 Py_ssize_t length = ListLength(self);
3014
3015 if (l->lv_lock)
3016 {
3017 RAISE_LOCKED_LIST;
3018 return -1;
3019 }
3020 if (index > length || (index == length && obj == NULL))
3021 {
3022 PyErr_SET_STRING(PyExc_IndexError, N_("list index out of range"));
3023 return -1;
3024 }
3025
3026 if (obj == NULL)
3027 {
3028 li = list_find(l, (long) index);
Bram Moolenaarab589462020-07-06 21:03:06 +02003029 if (li == NULL)
3030 {
3031 PyErr_VIM_FORMAT(N_("internal error: failed to get Vim "
3032 "list item %d"), (int) index);
3033 return -1;
3034 }
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02003035 vimlist_remove(l, li, li);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003036 clear_tv(&li->li_tv);
3037 vim_free(li);
3038 return 0;
3039 }
3040
3041 if (ConvertFromPyObject(obj, &tv) == -1)
3042 return -1;
3043
3044 if (index == length)
3045 {
3046 if (list_append_tv(l, &tv) == FAIL)
3047 {
3048 clear_tv(&tv);
3049 PyErr_SET_VIM(N_("failed to add item to list"));
3050 return -1;
3051 }
3052 }
3053 else
3054 {
3055 li = list_find(l, (long) index);
Bram Moolenaarab589462020-07-06 21:03:06 +02003056 if (li == NULL)
3057 {
3058 PyErr_VIM_FORMAT(N_("internal error: failed to get Vim "
3059 "list item %d"), (int) index);
3060 return -1;
3061 }
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003062 clear_tv(&li->li_tv);
3063 copy_tv(&tv, &li->li_tv);
3064 clear_tv(&tv);
3065 }
3066 return 0;
3067}
3068
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003069 static int
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003070ListAssItem(ListObject *self, PyObject *idx, PyObject *obj)
3071{
3072#if PY_MAJOR_VERSION < 3
3073 if (PyInt_Check(idx))
3074 {
3075 long _idx = PyInt_AsLong(idx);
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003076 return (int)ListAssIndex(self, _idx, obj);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003077 }
3078 else
3079#endif
3080 if (PyLong_Check(idx))
3081 {
3082 long _idx = PyLong_AsLong(idx);
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003083 return (int)ListAssIndex(self, _idx, obj);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003084 }
3085 else if (PySlice_Check(idx))
3086 {
3087 Py_ssize_t start, stop, step, slicelen;
3088
Bram Moolenaar922a4662014-03-30 16:11:43 +02003089 if (PySlice_GetIndicesEx((PySliceObject_T *)idx, ListLength(self),
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003090 &start, &stop, &step, &slicelen) < 0)
3091 return -1;
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003092 return (int)ListAssSlice(self, start, step, slicelen,
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003093 obj);
3094 }
3095 else
3096 {
3097 RAISE_INVALID_INDEX_TYPE(idx);
3098 return -1;
3099 }
3100}
3101
3102 static PyObject *
3103ListConcatInPlace(ListObject *self, PyObject *obj)
3104{
3105 list_T *l = self->list;
3106 PyObject *lookup_dict;
3107
3108 if (l->lv_lock)
3109 {
3110 RAISE_LOCKED_LIST;
3111 return NULL;
3112 }
3113
3114 if (!(lookup_dict = PyDict_New()))
3115 return NULL;
3116
3117 if (list_py_concat(l, obj, lookup_dict) == -1)
3118 {
3119 Py_DECREF(lookup_dict);
3120 return NULL;
3121 }
3122 Py_DECREF(lookup_dict);
3123
Ken Takata9abd7152024-08-10 09:44:20 +02003124 Py_INCREF((PyObject *)self);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003125 return (PyObject *)(self);
3126}
3127
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003128typedef struct
3129{
3130 listwatch_T lw;
3131 list_T *list;
3132} listiterinfo_T;
3133
3134 static void
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02003135ListIterDestruct(void *arg)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003136{
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02003137 listiterinfo_T *lii = (listiterinfo_T*)arg;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003138 list_rem_watch(lii->list, &lii->lw);
Bram Moolenaar21578272021-02-21 19:12:47 +01003139 list_unref(lii->list);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003140 PyMem_Free(lii);
3141}
3142
3143 static PyObject *
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02003144ListIterNext(void **arg)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003145{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003146 PyObject *ret;
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02003147 listiterinfo_T **lii = (listiterinfo_T**)arg;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003148
3149 if (!((*lii)->lw.lw_item))
3150 return NULL;
3151
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003152 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003153 return NULL;
3154
3155 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
3156
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003157 return ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003158}
3159
3160 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003161ListIter(PyObject *self_obj)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003162{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003163 ListObject *self = (ListObject*)self_obj;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003164 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003165 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003166
3167 if (!(lii = PyMem_New(listiterinfo_T, 1)))
3168 {
3169 PyErr_NoMemory();
3170 return NULL;
3171 }
3172
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02003173 CHECK_LIST_MATERIALIZE(l);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003174 list_add_watch(l, &lii->lw);
3175 lii->lw.lw_item = l->lv_first;
3176 lii->list = l;
Bram Moolenaar21578272021-02-21 19:12:47 +01003177 ++l->lv_refcount;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003178
3179 return IterNew(lii,
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02003180 ListIterDestruct, ListIterNext,
Bram Moolenaar423a85a2020-08-29 12:57:16 +02003181 NULL, NULL, (PyObject *)self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003182}
3183
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003184static char *ListAttrs[] = {
3185 "locked",
3186 NULL
3187};
3188
3189 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003190ListDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003191{
3192 return ObjectDir(self, ListAttrs);
3193}
3194
Bram Moolenaar66b79852012-09-21 14:00:35 +02003195 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003196ListSetattr(PyObject *self_obj, char *name, PyObject *valObject)
Bram Moolenaar66b79852012-09-21 14:00:35 +02003197{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003198 ListObject *self = (ListObject*)self_obj;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003199 if (valObject == NULL)
Bram Moolenaar66b79852012-09-21 14:00:35 +02003200 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003201 PyErr_SET_STRING(PyExc_AttributeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003202 N_("cannot delete vim.List attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02003203 return -1;
3204 }
3205
3206 if (strcmp(name, "locked") == 0)
3207 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003208 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02003209 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003210 PyErr_SET_STRING(PyExc_TypeError, N_("cannot modify fixed list"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02003211 return -1;
3212 }
3213 else
3214 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003215 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarb983f752013-05-15 16:11:50 +02003216 if (istrue == -1)
3217 return -1;
3218 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003219 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02003220 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02003221 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02003222 }
3223 return 0;
3224 }
3225 else
3226 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003227 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name);
Bram Moolenaar66b79852012-09-21 14:00:35 +02003228 return -1;
3229 }
3230}
3231
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003232static PySequenceMethods ListAsSeq = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003233 (lenfunc) ListLength, // sq_length, len(x)
3234 (binaryfunc) 0, // RangeConcat, sq_concat, x+y
3235 0, // RangeRepeat, sq_repeat, x*n
3236 (PyIntArgFunc) ListIndex, // sq_item, x[i]
3237 0, // was_sq_slice, x[i:j]
3238 (PyIntObjArgProc) ListAssIndex, // sq_as_item, x[i]=v
3239 0, // was_sq_ass_slice, x[i:j]=v
3240 0, // sq_contains
3241 (binaryfunc) ListConcatInPlace,// sq_inplace_concat
3242 0, // sq_inplace_repeat
Bram Moolenaar063a46b2014-01-14 16:36:51 +01003243};
3244
3245static PyMappingMethods ListAsMapping = {
3246 /* mp_length */ (lenfunc) ListLength,
3247 /* mp_subscript */ (binaryfunc) ListItem,
3248 /* mp_ass_subscript */ (objobjargproc) ListAssItem,
3249};
3250
Bram Moolenaardb913952012-06-29 12:54:53 +02003251static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003252 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
3253 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
3254 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02003255};
3256
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01003257DEFINE_PY_TYPE_OBJECT(TupleType);
3258
3259typedef struct
3260{
3261 PyObject_HEAD
3262 tuple_T *tuple;
3263 pylinkedlist_T ref;
3264} TupleObject;
3265
3266#define NEW_TUPLE(tuple) TupleNew(TupleTypePtr, tuple)
3267
3268 static PyObject *
3269TupleNew(PyTypeObject *subtype, tuple_T *tuple)
3270{
3271 TupleObject *self;
3272
3273 if (tuple == NULL)
3274 return NULL;
3275
3276 self = (TupleObject *) Py_TYPE_GET_TP_ALLOC(subtype)(subtype, 0);
3277 if (self == NULL)
3278 return NULL;
3279 self->tuple = tuple;
3280 ++tuple->tv_refcount;
3281
3282 pyll_add((PyObject *)(self), &self->ref, &lasttuple);
3283
3284 return (PyObject *)(self);
3285}
3286
3287 static tuple_T *
3288py_tuple_alloc(void)
3289{
3290 tuple_T *ret;
3291
3292 if (!(ret = tuple_alloc()))
3293 {
3294 PyErr_NoMemory();
3295 return NULL;
3296 }
3297 ++ret->tv_refcount;
3298
3299 return ret;
3300}
3301
3302 static int
3303tuple_py_concat(tuple_T *t, PyObject *obj, PyObject *lookup_dict)
3304{
3305 PyObject *iterator;
3306 PyObject *item;
3307
3308 if (!(iterator = PyObject_GetIter(obj)))
3309 return -1;
3310
3311 while ((item = PyIter_Next(iterator)))
3312 {
3313 typval_T new_tv;
3314
3315 if (_ConvertFromPyObject(item, &new_tv, lookup_dict) == -1)
3316 {
3317 Py_DECREF(item);
3318 Py_DECREF(iterator);
3319 return -1;
3320 }
3321
3322 Py_DECREF(item);
3323
3324 if (tuple_append_tv(t, &new_tv) == FAIL)
3325 {
3326 Py_DECREF(iterator);
3327 return -1;
3328 }
3329 }
3330
3331 Py_DECREF(iterator);
3332
3333 // Iterator may have finished due to an exception
3334 if (PyErr_Occurred())
3335 return -1;
3336
3337 return 0;
3338}
3339
3340 static PyObject *
3341TupleConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
3342{
3343 tuple_T *tuple;
3344 PyObject *obj = NULL;
3345
3346 if (kwargs)
3347 {
3348 PyErr_SET_STRING(PyExc_TypeError,
3349 N_("tuple constructor does not accept keyword arguments"));
3350 return NULL;
3351 }
3352
3353 if (!PyArg_ParseTuple(args, "|O", &obj))
3354 return NULL;
3355
3356 if (!(tuple = py_tuple_alloc()))
3357 return NULL;
3358
3359 if (obj)
3360 {
3361 PyObject *lookup_dict;
3362
3363 if (!(lookup_dict = PyDict_New()))
3364 {
3365 tuple_unref(tuple);
3366 return NULL;
3367 }
3368
3369 if (tuple_py_concat(tuple, obj, lookup_dict) == -1)
3370 {
3371 Py_DECREF(lookup_dict);
3372 tuple_unref(tuple);
3373 return NULL;
3374 }
3375
3376 Py_DECREF(lookup_dict);
3377 }
3378
3379 return TupleNew(subtype, tuple);
3380}
3381
3382 static void
3383TupleDestructor(PyObject *self_obj)
3384{
3385 TupleObject *self = (TupleObject *)self_obj;
3386 pyll_remove(&self->ref, &lasttuple);
3387 tuple_unref(self->tuple);
3388
3389 DESTRUCTOR_FINISH(self);
3390}
3391
3392 static PyInt
3393TupleLength(TupleObject *self)
3394{
3395 return ((PyInt)(tuple_len(self->tuple)));
3396}
3397
3398 static PyObject *
3399TupleIndex(TupleObject *self, Py_ssize_t index)
3400{
3401 PyInt len = TupleLength(self);
3402
3403 if (index < 0)
3404 index = len + index;
3405
3406 if (index < 0 || index >= len)
3407 {
3408 PyErr_SET_STRING(PyExc_IndexError, N_("tuple index out of range"));
3409 return NULL;
3410 }
3411 return ConvertToPyObject(TUPLE_ITEM(self->tuple, index));
3412}
3413
3414/*
3415 * Return a new tuple object for the tuple slice starting from the index
3416 * "first" and of length "slicelen" skipping "step" items.
3417 */
3418 static PyObject *
3419TupleSlice(
3420 TupleObject *self,
3421 Py_ssize_t first,
3422 Py_ssize_t step,
3423 Py_ssize_t slicelen)
3424{
3425 PyInt i;
3426 PyObject *tuple;
3427
3428 tuple = PyTuple_New(slicelen);
3429 if (tuple == NULL)
3430 return NULL;
3431
3432 for (i = 0; i < slicelen; ++i)
3433 {
3434 PyObject *item;
3435
3436 item = TupleIndex(self, first + i * step);
3437 if (item == NULL)
3438 {
3439 Py_DECREF(tuple);
3440 return NULL;
3441 }
3442
Yee Cheng Chine06b2ae2025-03-27 20:13:33 +01003443 PyTuple_SetItem(tuple, i, item);
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01003444 }
3445
3446 return tuple;
3447}
3448
3449 static PyObject *
3450TupleItem(TupleObject *self, PyObject* idx)
3451{
3452#if PY_MAJOR_VERSION < 3
3453 if (PyInt_Check(idx))
3454 {
3455 long _idx = PyInt_AsLong(idx);
3456 return TupleIndex(self, _idx);
3457 }
3458 else
3459#endif
3460 if (PyLong_Check(idx))
3461 {
3462 long _idx = PyLong_AsLong(idx);
3463 return TupleIndex(self, _idx);
3464 }
3465 else if (PySlice_Check(idx))
3466 {
3467 Py_ssize_t start, stop, step, slicelen;
3468
3469 if (PySlice_GetIndicesEx((PySliceObject_T *)idx, TupleLength(self),
3470 &start, &stop, &step, &slicelen) < 0)
3471 return NULL;
3472 return TupleSlice(self, start, step, slicelen);
3473 }
3474 else
3475 {
3476 RAISE_INVALID_INDEX_TYPE(idx);
3477 return NULL;
3478 }
3479}
3480
3481typedef struct
3482{
3483 tuple_T *tuple;
3484 int index;
3485} tupleiterinfo_T;
3486
3487 static void
3488TupleIterDestruct(void *arg)
3489{
3490 tupleiterinfo_T *tii = (tupleiterinfo_T*)arg;
3491 tuple_unref(tii->tuple);
3492 PyMem_Free(tii);
3493}
3494
3495 static PyObject *
3496TupleIterNext(void **arg)
3497{
3498 PyObject *ret;
3499 tupleiterinfo_T **tii = (tupleiterinfo_T**)arg;
3500
3501 if ((*tii)->index >= TUPLE_LEN((*tii)->tuple))
3502 return NULL;
3503
3504 if (!(ret = ConvertToPyObject(TUPLE_ITEM((*tii)->tuple, (*tii)->index))))
3505 return NULL;
3506
3507 (*tii)->index++;
3508
3509 return ret;
3510}
3511
3512 static PyObject *
3513TupleIter(PyObject *self_obj)
3514{
3515 TupleObject *self = (TupleObject*)self_obj;
3516 tupleiterinfo_T *tii;
3517 tuple_T *t = self->tuple;
3518
3519 if (!(tii = PyMem_New(tupleiterinfo_T, 1)))
3520 {
3521 PyErr_NoMemory();
3522 return NULL;
3523 }
3524
3525 tii->tuple = t;
3526 tii->index = 0;
3527 ++t->tv_refcount;
3528
3529 return IterNew(tii,
3530 TupleIterDestruct, TupleIterNext,
3531 NULL, NULL, (PyObject *)self);
3532}
3533
3534static char *TupleAttrs[] = {
3535 "locked",
3536 NULL
3537};
3538
3539 static PyObject *
3540TupleDir(PyObject *self, PyObject *args UNUSED)
3541{
3542 return ObjectDir(self, TupleAttrs);
3543}
3544
3545 static int
3546TupleSetattr(PyObject *self_obj, char *name, PyObject *valObject)
3547{
3548 TupleObject *self = (TupleObject*)self_obj;
3549 if (valObject == NULL)
3550 {
3551 PyErr_SET_STRING(PyExc_AttributeError,
3552 N_("cannot delete vim.Tuple attributes"));
3553 return -1;
3554 }
3555
3556 if (strcmp(name, "locked") == 0)
3557 {
3558 if (self->tuple->tv_lock == VAR_FIXED)
3559 {
3560 PyErr_SET_STRING(PyExc_TypeError, N_("cannot modify fixed tuple"));
3561 return -1;
3562 }
3563 else
3564 {
3565 int istrue = PyObject_IsTrue(valObject);
3566 if (istrue == -1)
3567 return -1;
3568 else if (istrue)
3569 self->tuple->tv_lock = VAR_LOCKED;
3570 else
3571 self->tuple->tv_lock = 0;
3572 }
3573 return 0;
3574 }
3575 else
3576 {
3577 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name);
3578 return -1;
3579 }
3580}
3581
3582static PySequenceMethods TupleAsSeq = {
3583 (lenfunc) TupleLength, // sq_length, len(x)
3584 (binaryfunc) 0, // RangeConcat, sq_concat, x+y
3585 0, // RangeRepeat, sq_repeat, x*n
3586 (PyIntArgFunc) TupleIndex, // sq_item, x[i]
3587 0, // was_sq_slice, x[i:j]
3588 (PyIntObjArgProc) 0, // sq_as_item, x[i]=v
3589 0, // was_sq_ass_slice, x[i:j]=v
3590 0, // sq_contains
3591 (binaryfunc) 0, // sq_inplace_concat
3592 0, // sq_inplace_repeat
3593};
3594
3595static PyMappingMethods TupleAsMapping = {
3596 /* mp_length */ (lenfunc) TupleLength,
3597 /* mp_subscript */ (binaryfunc) TupleItem,
3598 /* mp_ass_subscript */ (objobjargproc) 0,
3599};
3600
3601static struct PyMethodDef TupleMethods[] = {
3602 {"__dir__", (PyCFunction)TupleDir, METH_NOARGS, ""},
3603 { NULL, NULL, 0, NULL}
3604};
3605
Bram Moolenaardb913952012-06-29 12:54:53 +02003606typedef struct
3607{
3608 PyObject_HEAD
3609 char_u *name;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003610 int argc;
3611 typval_T *argv;
3612 dict_T *self;
3613 pylinkedlist_T ref;
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003614 int auto_rebind;
Bram Moolenaardb913952012-06-29 12:54:53 +02003615} FunctionObject;
3616
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02003617DEFINE_PY_TYPE_OBJECT(FunctionType);
Bram Moolenaardb913952012-06-29 12:54:53 +02003618
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003619#define NEW_FUNCTION(name, argc, argv, self, pt_auto) \
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02003620 FunctionNew(FunctionTypePtr, (name), (argc), (argv), (self), (pt_auto))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003621
Bram Moolenaardb913952012-06-29 12:54:53 +02003622 static PyObject *
Bram Moolenaar8110a092016-04-14 15:56:09 +02003623FunctionNew(PyTypeObject *subtype, char_u *name, int argc, typval_T *argv,
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003624 dict_T *selfdict, int auto_rebind)
Bram Moolenaardb913952012-06-29 12:54:53 +02003625{
3626 FunctionObject *self;
3627
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02003628 self = (FunctionObject *) Py_TYPE_GET_TP_ALLOC(subtype)(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02003629 if (self == NULL)
3630 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003631
Keith Thompson184f71c2024-01-04 21:19:04 +01003632 if (isdigit((unsigned char)*name))
Bram Moolenaardb913952012-06-29 12:54:53 +02003633 {
Bram Moolenaara14bb7e2020-04-28 00:02:41 +02003634 if (!translated_function_exists(name, FALSE))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003635 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003636 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003637 N_("unnamed function %s does not exist"), name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003638 return NULL;
3639 }
3640 self->name = vim_strsave(name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003641 }
3642 else
Bram Moolenaar9123c0b2018-12-22 18:59:06 +01003643 {
3644 char_u *p;
3645
3646 if ((p = get_expanded_name(name,
3647 vim_strchr(name, AUTOLOAD_CHAR) == NULL)) == NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003648 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003649 PyErr_FORMAT(PyExc_ValueError,
3650 N_("function %s does not exist"), name);
Bram Moolenaar018acca2013-05-30 13:37:28 +02003651 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003652 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003653
Bram Moolenaar9123c0b2018-12-22 18:59:06 +01003654 if (p[0] == K_SPECIAL && p[1] == KS_EXTRA && p[2] == (int)KE_SNR)
3655 {
3656 char_u *np;
3657 size_t len = STRLEN(p) + 1;
3658
Bram Moolenaar51e14382019-05-25 20:21:28 +02003659 if ((np = alloc(len + 2)) == NULL)
Bram Moolenaar9123c0b2018-12-22 18:59:06 +01003660 {
3661 vim_free(p);
3662 return NULL;
3663 }
3664 mch_memmove(np, "<SNR>", 5);
3665 mch_memmove(np + 5, p + 3, len - 3);
3666 vim_free(p);
3667 self->name = np;
3668 }
3669 else
3670 self->name = p;
3671 }
3672
Bram Moolenaar2d3d60a2016-08-01 16:27:23 +02003673 func_ref(self->name);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003674 self->argc = argc;
3675 self->argv = argv;
3676 self->self = selfdict;
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003677 self->auto_rebind = selfdict == NULL ? TRUE : auto_rebind;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003678
3679 if (self->argv || self->self)
3680 pyll_add((PyObject *)(self), &self->ref, &lastfunc);
3681
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003682 return (PyObject *)(self);
3683}
3684
3685 static PyObject *
3686FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
3687{
3688 PyObject *self;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003689 PyObject *selfdictObject;
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003690 PyObject *autoRebindObject;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003691 PyObject *argsObject = NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003692 char_u *name;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003693 typval_T selfdicttv;
3694 typval_T argstv;
3695 list_T *argslist = NULL;
3696 dict_T *selfdict = NULL;
3697 int argc = 0;
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003698 int auto_rebind = TRUE;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003699 typval_T *argv = NULL;
3700 typval_T *curtv;
3701 listitem_T *li;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003702
Bram Moolenaar8110a092016-04-14 15:56:09 +02003703 if (kwargs != NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003704 {
Bram Moolenaar8110a092016-04-14 15:56:09 +02003705 selfdictObject = PyDict_GetItemString(kwargs, "self");
3706 if (selfdictObject != NULL)
3707 {
3708 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
3709 return NULL;
3710 selfdict = selfdicttv.vval.v_dict;
3711 }
3712 argsObject = PyDict_GetItemString(kwargs, "args");
3713 if (argsObject != NULL)
3714 {
3715 if (ConvertFromPySequence(argsObject, &argstv) == -1)
3716 {
3717 dict_unref(selfdict);
3718 return NULL;
3719 }
3720 argslist = argstv.vval.v_list;
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02003721 CHECK_LIST_MATERIALIZE(argslist);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003722
3723 argc = argslist->lv_len;
3724 if (argc != 0)
3725 {
3726 argv = PyMem_New(typval_T, (size_t) argc);
Bram Moolenaarfe4b1862016-04-15 21:47:54 +02003727 if (argv == NULL)
3728 {
3729 PyErr_NoMemory();
3730 dict_unref(selfdict);
3731 list_unref(argslist);
3732 return NULL;
3733 }
Bram Moolenaar8110a092016-04-14 15:56:09 +02003734 curtv = argv;
Bram Moolenaaraeea7212020-04-02 18:50:46 +02003735 FOR_ALL_LIST_ITEMS(argslist, li)
Bram Moolenaar8110a092016-04-14 15:56:09 +02003736 copy_tv(&li->li_tv, curtv++);
3737 }
3738 list_unref(argslist);
3739 }
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003740 if (selfdict != NULL)
3741 {
3742 auto_rebind = FALSE;
3743 autoRebindObject = PyDict_GetItemString(kwargs, "auto_rebind");
3744 if (autoRebindObject != NULL)
3745 {
3746 auto_rebind = PyObject_IsTrue(autoRebindObject);
3747 if (auto_rebind == -1)
3748 {
3749 dict_unref(selfdict);
3750 list_unref(argslist);
3751 return NULL;
3752 }
3753 }
3754 }
Bram Moolenaardb913952012-06-29 12:54:53 +02003755 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003756
Bram Moolenaar389a1792013-06-23 13:00:44 +02003757 if (!PyArg_ParseTuple(args, "et", "ascii", &name))
Bram Moolenaar8110a092016-04-14 15:56:09 +02003758 {
3759 dict_unref(selfdict);
3760 while (argc--)
3761 clear_tv(&argv[argc]);
3762 PyMem_Free(argv);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003763 return NULL;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003764 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003765
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003766 self = FunctionNew(subtype, name, argc, argv, selfdict, auto_rebind);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003767
Bram Moolenaar389a1792013-06-23 13:00:44 +02003768 PyMem_Free(name);
3769
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003770 return self;
Bram Moolenaardb913952012-06-29 12:54:53 +02003771}
3772
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003773 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003774FunctionDestructor(PyObject *self_obj)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003775{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003776 FunctionObject *self = (FunctionObject*)self_obj;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003777 int i;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003778 func_unref(self->name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003779 vim_free(self->name);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003780 for (i = 0; i < self->argc; ++i)
3781 clear_tv(&self->argv[i]);
3782 PyMem_Free(self->argv);
3783 dict_unref(self->self);
3784 if (self->argv || self->self)
3785 pyll_remove(&self->ref, &lastfunc);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003786
3787 DESTRUCTOR_FINISH(self);
3788}
3789
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003790static char *FunctionAttrs[] = {
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003791 "softspace", "args", "self", "auto_rebind",
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003792 NULL
3793};
3794
3795 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003796FunctionDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003797{
3798 return ObjectDir(self, FunctionAttrs);
3799}
3800
Bram Moolenaardb913952012-06-29 12:54:53 +02003801 static PyObject *
Bram Moolenaar8110a092016-04-14 15:56:09 +02003802FunctionAttr(FunctionObject *self, char *name)
3803{
3804 list_T *list;
3805 int i;
3806 if (strcmp(name, "name") == 0)
3807 return PyString_FromString((char *)(self->name));
3808 else if (strcmp(name, "args") == 0)
3809 {
Bram Moolenaar9f289532016-08-26 16:39:03 +02003810 if (self->argv == NULL || (list = list_alloc()) == NULL)
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003811 return ALWAYS_NONE;
Bram Moolenaar9f289532016-08-26 16:39:03 +02003812
Bram Moolenaar8110a092016-04-14 15:56:09 +02003813 for (i = 0; i < self->argc; ++i)
3814 list_append_tv(list, &self->argv[i]);
3815 return NEW_LIST(list);
3816 }
3817 else if (strcmp(name, "self") == 0)
3818 return self->self == NULL
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003819 ? ALWAYS_NONE
Bram Moolenaar8110a092016-04-14 15:56:09 +02003820 : NEW_DICTIONARY(self->self);
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003821 else if (strcmp(name, "auto_rebind") == 0)
3822 return self->auto_rebind
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02003823 ? ALWAYS_TRUE
3824 : ALWAYS_FALSE;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003825 else if (strcmp(name, "__members__") == 0)
3826 return ObjectDir(NULL, FunctionAttrs);
3827 return NULL;
3828}
3829
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003830/*
3831 * Populate partial_T given function object.
Bram Moolenaar8110a092016-04-14 15:56:09 +02003832 *
3833 * "exported" should be set to true when it is needed to construct a partial
3834 * that may be stored in a variable (i.e. may be freed by Vim).
3835 */
3836 static void
3837set_partial(FunctionObject *self, partial_T *pt, int exported)
3838{
Bram Moolenaar8110a092016-04-14 15:56:09 +02003839 int i;
3840
3841 pt->pt_name = self->name;
3842 if (self->argv)
3843 {
3844 pt->pt_argc = self->argc;
3845 if (exported)
3846 {
Bram Moolenaarc799fe22019-05-28 23:08:19 +02003847 pt->pt_argv = ALLOC_CLEAR_MULT(typval_T, self->argc);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003848 for (i = 0; i < pt->pt_argc; ++i)
3849 copy_tv(&self->argv[i], &pt->pt_argv[i]);
3850 }
3851 else
3852 pt->pt_argv = self->argv;
3853 }
3854 else
3855 {
3856 pt->pt_argc = 0;
3857 pt->pt_argv = NULL;
3858 }
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003859 pt->pt_auto = self->auto_rebind || !exported;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003860 pt->pt_dict = self->self;
3861 if (exported && self->self)
3862 ++pt->pt_dict->dv_refcount;
3863 if (exported)
3864 pt->pt_name = vim_strsave(pt->pt_name);
3865 pt->pt_refcount = 1;
3866}
3867
3868 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003869FunctionCall(PyObject *self_obj, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02003870{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003871 FunctionObject *self = (FunctionObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003872 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02003873 typval_T args;
3874 typval_T selfdicttv;
3875 typval_T rettv;
3876 dict_T *selfdict = NULL;
3877 PyObject *selfdictObject;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003878 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02003879 int error;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003880 partial_T pt;
3881 partial_T *pt_ptr = NULL;
Bram Moolenaardb913952012-06-29 12:54:53 +02003882
Bram Moolenaar8110a092016-04-14 15:56:09 +02003883 if (ConvertFromPySequence(argsObject, &args) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02003884 return NULL;
3885
3886 if (kwargs != NULL)
3887 {
3888 selfdictObject = PyDict_GetItemString(kwargs, "self");
3889 if (selfdictObject != NULL)
3890 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02003891 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003892 {
3893 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02003894 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003895 }
Bram Moolenaardb913952012-06-29 12:54:53 +02003896 selfdict = selfdicttv.vval.v_dict;
3897 }
3898 }
3899
Bram Moolenaar8110a092016-04-14 15:56:09 +02003900 if (self->argv || self->self)
3901 {
Bram Moolenaara80faa82020-04-12 19:37:17 +02003902 CLEAR_FIELD(pt);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003903 set_partial(self, &pt, FALSE);
3904 pt_ptr = &pt;
3905 }
3906
Bram Moolenaar71700b82013-05-15 17:49:05 +02003907 Py_BEGIN_ALLOW_THREADS
3908 Python_Lock_Vim();
3909
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003910 VimTryStart();
Bram Moolenaar8110a092016-04-14 15:56:09 +02003911 error = func_call(name, &args, pt_ptr, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02003912
3913 Python_Release_Vim();
3914 Py_END_ALLOW_THREADS
3915
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003916 if (VimTryEnd())
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003917 ret = NULL;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003918 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02003919 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003920 ret = NULL;
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003921 PyErr_VIM_FORMAT(N_("failed to run function %s"), (char *)name);
Bram Moolenaardb913952012-06-29 12:54:53 +02003922 }
3923 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003924 ret = ConvertToPyObject(&rettv);
Bram Moolenaardb913952012-06-29 12:54:53 +02003925
Bram Moolenaardb913952012-06-29 12:54:53 +02003926 clear_tv(&args);
3927 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003928 if (selfdict != NULL)
3929 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02003930
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003931 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02003932}
3933
Bram Moolenaara5b725c2013-05-30 12:43:54 +02003934 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003935FunctionRepr(PyObject *self_obj)
Bram Moolenaara5b725c2013-05-30 12:43:54 +02003936{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02003937 FunctionObject *self = (FunctionObject*)self_obj;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003938 PyObject *ret;
3939 garray_T repr_ga;
3940 int i;
3941 char_u *tofree = NULL;
3942 typval_T tv;
3943 char_u numbuf[NUMBUFLEN];
3944
Bram Moolenaar04935fb2022-01-08 16:19:22 +00003945 ga_init2(&repr_ga, sizeof(char), 70);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003946 ga_concat(&repr_ga, (char_u *)"<vim.Function '");
3947 if (self->name)
3948 ga_concat(&repr_ga, self->name);
3949 else
3950 ga_concat(&repr_ga, (char_u *)"<NULL>");
3951 ga_append(&repr_ga, '\'');
3952 if (self->argv)
3953 {
3954 ga_concat(&repr_ga, (char_u *)", args=[");
3955 ++emsg_silent;
3956 for (i = 0; i < self->argc; i++)
3957 {
3958 if (i != 0)
3959 ga_concat(&repr_ga, (char_u *)", ");
3960 ga_concat(&repr_ga, tv2string(&self->argv[i], &tofree, numbuf,
3961 get_copyID()));
3962 vim_free(tofree);
3963 }
3964 --emsg_silent;
3965 ga_append(&repr_ga, ']');
3966 }
3967 if (self->self)
3968 {
3969 ga_concat(&repr_ga, (char_u *)", self=");
3970 tv.v_type = VAR_DICT;
3971 tv.vval.v_dict = self->self;
3972 ++emsg_silent;
3973 ga_concat(&repr_ga, tv2string(&tv, &tofree, numbuf, get_copyID()));
3974 --emsg_silent;
3975 vim_free(tofree);
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003976 if (self->auto_rebind)
3977 ga_concat(&repr_ga, (char_u *)", auto_rebind=True");
Bram Moolenaar8110a092016-04-14 15:56:09 +02003978 }
3979 ga_append(&repr_ga, '>');
3980 ret = PyString_FromString((char *)repr_ga.ga_data);
3981 ga_clear(&repr_ga);
3982 return ret;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02003983}
3984
Bram Moolenaardb913952012-06-29 12:54:53 +02003985static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003986 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
3987 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02003988};
3989
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003990/*
3991 * Options object
3992 */
3993
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02003994DEFINE_PY_TYPE_OBJECT(OptionsType);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003995
3996typedef int (*checkfun)(void *);
3997
3998typedef struct
3999{
4000 PyObject_HEAD
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004001 int opt_type;
4002 void *from;
4003 checkfun Check;
4004 PyObject *fromObj;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004005} OptionsObject;
4006
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004007 static int
4008dummy_check(void *arg UNUSED)
4009{
4010 return 0;
4011}
4012
4013 static PyObject *
4014OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
4015{
4016 OptionsObject *self;
4017
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004018 self = PyObject_GC_New(OptionsObject, OptionsTypePtr);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004019 if (self == NULL)
4020 return NULL;
4021
4022 self->opt_type = opt_type;
4023 self->from = from;
4024 self->Check = Check;
4025 self->fromObj = fromObj;
4026 if (fromObj)
4027 Py_INCREF(fromObj);
4028
4029 return (PyObject *)(self);
4030}
4031
4032 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004033OptionsDestructor(PyObject *self_obj)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004034{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004035 OptionsObject *self = (OptionsObject*)self_obj;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004036 PyObject_GC_UnTrack((void *)(self));
4037 Py_XDECREF(self->fromObj);
4038 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004039}
4040
4041 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004042OptionsTraverse(PyObject *self_obj, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004043{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004044 OptionsObject *self = (OptionsObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004045 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004046 return 0;
4047}
4048
4049 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004050OptionsClear(PyObject *self_obj)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004051{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004052 OptionsObject *self = (OptionsObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004053 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004054 return 0;
4055}
4056
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004057 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004058OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004059{
4060 char_u *key;
4061 int flags;
4062 long numval;
4063 char_u *stringval;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004064 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004065
Bram Moolenaarbb790dc2020-07-07 20:12:54 +02004066 if (self->Check(self->fromObj))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004067 return NULL;
4068
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004069 if (!(key = StringToChars(keyObject, &todecref)))
4070 return NULL;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004071
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004072 if (*key == NUL)
4073 {
4074 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004075 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004076 return NULL;
4077 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004078
4079 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02004080 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004081
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004082 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004083
4084 if (flags == 0)
4085 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02004086 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004087 return NULL;
4088 }
4089
4090 if (flags & SOPT_UNSET)
4091 {
4092 Py_INCREF(Py_None);
4093 return Py_None;
4094 }
4095 else if (flags & SOPT_BOOL)
4096 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004097 PyObject *ret;
4098 ret = numval ? Py_True : Py_False;
4099 Py_INCREF(ret);
4100 return ret;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004101 }
4102 else if (flags & SOPT_NUM)
4103 return PyInt_FromLong(numval);
4104 else if (flags & SOPT_STRING)
4105 {
4106 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02004107 {
Bram Moolenaar41009372013-07-01 22:03:04 +02004108 PyObject *ret = PyBytes_FromString((char *)stringval);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02004109 vim_free(stringval);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004110 return ret;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02004111 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004112 else
4113 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004114 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004115 N_("unable to get option value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004116 return NULL;
4117 }
4118 }
4119 else
4120 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004121 PyErr_SET_VIM(N_("internal error: unknown option type"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004122 return NULL;
4123 }
4124}
4125
4126 static int
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004127OptionsContains(OptionsObject *self, PyObject *keyObject)
4128{
4129 char_u *key;
4130 PyObject *todecref;
4131
4132 if (!(key = StringToChars(keyObject, &todecref)))
4133 return -1;
4134
4135 if (*key == NUL)
4136 {
4137 Py_XDECREF(todecref);
4138 return 0;
4139 }
4140
4141 if (get_option_value_strict(key, NULL, NULL, self->opt_type, NULL))
4142 {
4143 Py_XDECREF(todecref);
4144 return 1;
4145 }
4146 else
4147 {
4148 Py_XDECREF(todecref);
4149 return 0;
4150 }
4151}
4152
4153typedef struct
4154{
4155 void *lastoption;
4156 int opt_type;
4157} optiterinfo_T;
4158
4159 static PyObject *
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02004160OptionsIterNext(void **arg)
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004161{
4162 char_u *name;
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02004163 optiterinfo_T **oii = (optiterinfo_T**)arg;
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004164
4165 if ((name = option_iter_next(&((*oii)->lastoption), (*oii)->opt_type)))
4166 return PyString_FromString((char *)name);
4167
4168 return NULL;
4169}
4170
4171 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004172OptionsIter(PyObject *self_obj)
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004173{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004174 OptionsObject *self = (OptionsObject*)self_obj;
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004175 optiterinfo_T *oii;
4176
4177 if (!(oii = PyMem_New(optiterinfo_T, 1)))
4178 {
4179 PyErr_NoMemory();
4180 return NULL;
4181 }
4182
4183 oii->opt_type = self->opt_type;
4184 oii->lastoption = NULL;
4185
4186 return IterNew(oii,
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02004187 PyMem_Free, OptionsIterNext,
Bram Moolenaar423a85a2020-08-29 12:57:16 +02004188 NULL, NULL, (PyObject *)self);
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004189}
4190
4191 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02004192set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004193{
Bram Moolenaarb1443b42019-01-13 23:51:14 +01004194 char *errmsg;
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004195
4196 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
4197 {
4198 if (VimTryEnd())
4199 return FAIL;
Bram Moolenaarb1443b42019-01-13 23:51:14 +01004200 PyErr_SetVim(errmsg);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004201 return FAIL;
4202 }
4203 return OK;
4204}
4205
4206 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02004207set_option_value_for(
4208 char_u *key,
4209 int numval,
4210 char_u *stringval,
4211 int opt_flags,
4212 int opt_type,
4213 void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004214{
Bram Moolenaar18f47402022-01-06 13:24:51 +00004215 switchwin_T switchwin;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004216 bufref_T save_curbuf;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004217 int set_ret = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004218
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004219 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004220 switch (opt_type)
4221 {
4222 case SREQ_WIN:
Bram Moolenaar18f47402022-01-06 13:24:51 +00004223 if (switch_win(&switchwin, (win_T *)from,
Bram Moolenaard6949742013-06-16 14:18:28 +02004224 win_find_tabpage((win_T *)from), FALSE) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004225 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00004226 restore_win(&switchwin, TRUE);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004227 if (VimTryEnd())
4228 return -1;
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004229 PyErr_SET_VIM(N_("problem while switching windows"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004230 return -1;
4231 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004232 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar18f47402022-01-06 13:24:51 +00004233 restore_win(&switchwin, TRUE);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004234 break;
4235 case SREQ_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02004236 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004237 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004238 restore_buffer(&save_curbuf);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004239 break;
4240 case SREQ_GLOBAL:
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004241 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004242 break;
4243 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004244 if (set_ret == FAIL)
4245 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004246 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004247}
4248
4249 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02004250OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004251{
4252 char_u *key;
4253 int flags;
4254 int opt_flags;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004255 int ret = 0;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004256 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004257
Bram Moolenaarbb790dc2020-07-07 20:12:54 +02004258 if (self->Check(self->fromObj))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004259 return -1;
4260
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004261 if (!(key = StringToChars(keyObject, &todecref)))
4262 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004263
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004264 if (*key == NUL)
4265 {
4266 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004267 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004268 return -1;
4269 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004270
4271 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02004272 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004273
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004274 if (flags == 0)
4275 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02004276 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004277 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004278 return -1;
4279 }
4280
4281 if (valObject == NULL)
4282 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004283 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004284 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02004285 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004286 N_("unable to unset global option %s"), key);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004287 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004288 return -1;
4289 }
4290 else if (!(flags & SOPT_GLOBAL))
4291 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02004292 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004293 N_("unable to unset option %s "
4294 "which does not have global value"), key);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004295 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004296 return -1;
4297 }
4298 else
4299 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004300 unset_global_local_option(key, self->from);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004301 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004302 return 0;
4303 }
4304 }
4305
Bram Moolenaard6e39182013-05-21 18:30:34 +02004306 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004307
4308 if (flags & SOPT_BOOL)
4309 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02004310 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02004311
Bram Moolenaarb983f752013-05-15 16:11:50 +02004312 if (istrue == -1)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004313 ret = -1;
Bram Moolenaar1bc24282013-05-29 21:37:35 +02004314 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004315 ret = set_option_value_for(key, istrue, NULL,
Bram Moolenaar1bc24282013-05-29 21:37:35 +02004316 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004317 }
4318 else if (flags & SOPT_NUM)
4319 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004320 long val;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004321
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004322 if (NumberToLong(valObject, &val, NUMBER_INT))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004323 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004324 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004325 return -1;
4326 }
4327
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004328 ret = set_option_value_for(key, (int) val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02004329 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004330 }
4331 else
4332 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004333 char_u *val;
Bram Moolenaarc2401d62013-12-07 14:28:43 +01004334 PyObject *todecref2;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004335
Bram Moolenaarc2401d62013-12-07 14:28:43 +01004336 if ((val = StringToChars(valObject, &todecref2)))
4337 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004338 ret = set_option_value_for(key, 0, val, opt_flags,
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004339 self->opt_type, self->from);
Bram Moolenaarc2401d62013-12-07 14:28:43 +01004340 Py_XDECREF(todecref2);
4341 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004342 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004343 ret = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004344 }
4345
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004346 Py_XDECREF(todecref);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02004347
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004348 return ret;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004349}
4350
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004351static PySequenceMethods OptionsAsSeq = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004352 0, // sq_length
4353 0, // sq_concat
4354 0, // sq_repeat
4355 0, // sq_item
4356 0, // sq_slice
4357 0, // sq_ass_item
4358 0, // sq_ass_slice
4359 (objobjproc) OptionsContains, // sq_contains
4360 0, // sq_inplace_concat
4361 0, // sq_inplace_repeat
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01004362};
4363
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004364static PyMappingMethods OptionsAsMapping = {
4365 (lenfunc) NULL,
4366 (binaryfunc) OptionsItem,
4367 (objobjargproc) OptionsAssItem,
4368};
4369
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004370// Tabpage object
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004371
4372typedef struct
4373{
4374 PyObject_HEAD
4375 tabpage_T *tab;
4376} TabPageObject;
4377
4378static PyObject *WinListNew(TabPageObject *tabObject);
4379
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004380DEFINE_PY_TYPE_OBJECT(TabPageType);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004381
4382 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02004383CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004384{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004385 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004386 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004387 PyErr_SET_VIM(N_("attempt to refer to deleted tab page"));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004388 return -1;
4389 }
4390
4391 return 0;
4392}
4393
4394 static PyObject *
4395TabPageNew(tabpage_T *tab)
4396{
4397 TabPageObject *self;
4398
4399 if (TAB_PYTHON_REF(tab))
4400 {
4401 self = TAB_PYTHON_REF(tab);
Ken Takata9abd7152024-08-10 09:44:20 +02004402 Py_INCREF((PyObject *)self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004403 }
4404 else
4405 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004406 self = PyObject_NEW(TabPageObject, TabPageTypePtr);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004407 if (self == NULL)
4408 return NULL;
4409 self->tab = tab;
4410 TAB_PYTHON_REF(tab) = self;
4411 }
4412
4413 return (PyObject *)(self);
4414}
4415
4416 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004417TabPageDestructor(PyObject *self_obj)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004418{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004419 TabPageObject *self = (TabPageObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004420 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
4421 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004422
4423 DESTRUCTOR_FINISH(self);
4424}
4425
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004426static char *TabPageAttrs[] = {
4427 "windows", "number", "vars", "window", "valid",
4428 NULL
4429};
4430
4431 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02004432TabPageDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004433{
4434 return ObjectDir(self, TabPageAttrs);
4435}
4436
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004437 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004438TabPageAttrValid(TabPageObject *self, char *name)
4439{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004440 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004441
4442 if (strcmp(name, "valid") != 0)
4443 return NULL;
4444
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004445 ret = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
4446 Py_INCREF(ret);
4447 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004448}
4449
4450 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004451TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004452{
4453 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004454 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004455 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004456 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004457 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02004458 return NEW_DICTIONARY(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004459 else if (strcmp(name, "window") == 0)
4460 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004461 // For current tab window.c does not bother to set or update tp_curwin
Bram Moolenaard6e39182013-05-21 18:30:34 +02004462 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004463 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004464 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004465 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004466 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004467 else if (strcmp(name, "__members__") == 0)
4468 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004469 return NULL;
4470}
4471
4472 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004473TabPageRepr(PyObject *self_obj)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004474{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004475 TabPageObject *self = (TabPageObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004476 if (self->tab == INVALID_TABPAGE_VALUE)
Dominique Pellec14f6672022-01-09 12:57:48 +00004477 return PyString_FromFormat("<tabpage object (deleted) at %p>", (void *)self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004478 else
4479 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004480 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004481
4482 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004483 return PyString_FromFormat("<tabpage object (unknown) at %p>",
Dominique Pellec14f6672022-01-09 12:57:48 +00004484 (void *)self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004485 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004486 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004487 }
4488}
4489
4490static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004491 // name, function, calling, documentation
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004492 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
4493 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004494};
4495
4496/*
4497 * Window list object
4498 */
4499
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004500DEFINE_PY_TYPE_OBJECT(TabListType);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004501static PySequenceMethods TabListAsSeq;
4502
4503typedef struct
4504{
4505 PyObject_HEAD
4506} TabListObject;
4507
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004508static TabListObject TheTabPageList =
4509{
4510 PyObject_HEAD_INIT_TYPE(TabListType)
4511};
4512
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004513 static PyInt
4514TabListLength(PyObject *self UNUSED)
4515{
4516 tabpage_T *tp = first_tabpage;
4517 PyInt n = 0;
4518
4519 while (tp != NULL)
4520 {
4521 ++n;
4522 tp = tp->tp_next;
4523 }
4524
4525 return n;
4526}
4527
4528 static PyObject *
4529TabListItem(PyObject *self UNUSED, PyInt n)
4530{
4531 tabpage_T *tp;
4532
4533 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
4534 if (n == 0)
4535 return TabPageNew(tp);
4536
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004537 PyErr_SET_STRING(PyExc_IndexError, N_("no such tab page"));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004538 return NULL;
4539}
4540
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +02004541/*
4542 * Window object
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004543 */
4544
4545typedef struct
4546{
4547 PyObject_HEAD
4548 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004549 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004550} WindowObject;
4551
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004552DEFINE_PY_TYPE_OBJECT(WindowType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004553
4554 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02004555CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004556{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004557 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004558 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004559 PyErr_SET_VIM(N_("attempt to refer to deleted window"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004560 return -1;
4561 }
4562
4563 return 0;
4564}
4565
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02004566 static int
4567CheckWindowCb(void *self)
4568{
4569 return CheckWindow((WindowObject*)self);
4570}
4571
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004572 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004573WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02004574{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004575 /*
4576 * We need to handle deletion of windows underneath us.
Bram Moolenaar971db462013-05-12 18:44:48 +02004577 * If we add a "w_python*_ref" field to the win_T structure,
4578 * then we can get at it in win_free() in vim. We then
4579 * need to create only ONE Python object per window - if
4580 * we try to create a second, just INCREF the existing one
4581 * and return it. The (single) Python object referring to
4582 * the window is stored in "w_python*_ref".
4583 * On a win_free() we set the Python object's win_T* field
4584 * to an invalid value. We trap all uses of a window
4585 * object, and reject them if the win_T* field is invalid.
4586 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004587 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02004588 * w_python_ref and w_python3_ref fields respectively.
4589 */
4590
4591 WindowObject *self;
4592
4593 if (WIN_PYTHON_REF(win))
4594 {
4595 self = WIN_PYTHON_REF(win);
Ken Takata9abd7152024-08-10 09:44:20 +02004596 Py_INCREF((PyObject *)self);
Bram Moolenaar971db462013-05-12 18:44:48 +02004597 }
4598 else
4599 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004600 self = PyObject_GC_New(WindowObject, WindowTypePtr);
Bram Moolenaar971db462013-05-12 18:44:48 +02004601 if (self == NULL)
4602 return NULL;
4603 self->win = win;
4604 WIN_PYTHON_REF(win) = self;
4605 }
4606
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004607 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
4608
Bram Moolenaar971db462013-05-12 18:44:48 +02004609 return (PyObject *)(self);
4610}
4611
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004612 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004613WindowDestructor(PyObject *self_obj)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004614{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004615 WindowObject *self = (WindowObject*)self_obj;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004616 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02004617 if (self->win && self->win != INVALID_WINDOW_VALUE)
4618 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaarab589462020-07-06 21:03:06 +02004619 Py_XDECREF(((PyObject *)(self->tabObject)));
Bram Moolenaar774267b2013-05-21 20:51:59 +02004620 PyObject_GC_Del((void *)(self));
4621}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004622
Bram Moolenaar774267b2013-05-21 20:51:59 +02004623 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004624WindowTraverse(PyObject *self_obj, visitproc visit, void *arg)
Bram Moolenaar774267b2013-05-21 20:51:59 +02004625{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004626 WindowObject *self = (WindowObject*)self_obj;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004627 Py_VISIT(((PyObject *)(self->tabObject)));
4628 return 0;
4629}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004630
Bram Moolenaar774267b2013-05-21 20:51:59 +02004631 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004632WindowClear(PyObject *self_obj)
Bram Moolenaar774267b2013-05-21 20:51:59 +02004633{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004634 WindowObject *self = (WindowObject*)self_obj;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004635 Py_CLEAR(self->tabObject);
4636 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004637}
4638
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004639 static win_T *
4640get_firstwin(TabPageObject *tabObject)
4641{
4642 if (tabObject)
4643 {
4644 if (CheckTabPage(tabObject))
4645 return NULL;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004646 // For current tab window.c does not bother to set or update tp_firstwin
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004647 else if (tabObject->tab == curtab)
4648 return firstwin;
4649 else
4650 return tabObject->tab->tp_firstwin;
4651 }
4652 else
4653 return firstwin;
4654}
Bram Moolenaare950f992018-06-10 13:55:55 +02004655
4656// Use the same order as in the WindowAttr() function.
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004657static char *WindowAttrs[] = {
Bram Moolenaare950f992018-06-10 13:55:55 +02004658 "buffer",
4659 "cursor",
4660 "height",
4661 "row",
4662 "width",
4663 "col",
4664 "vars",
4665 "options",
4666 "number",
4667 "tabpage",
4668 "valid",
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004669 NULL
4670};
4671
4672 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02004673WindowDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004674{
4675 return ObjectDir(self, WindowAttrs);
4676}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004677
Bram Moolenaar971db462013-05-12 18:44:48 +02004678 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004679WindowAttrValid(WindowObject *self, char *name)
4680{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004681 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004682
4683 if (strcmp(name, "valid") != 0)
4684 return NULL;
4685
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004686 ret = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
4687 Py_INCREF(ret);
4688 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004689}
4690
4691 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004692WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004693{
4694 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004695 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004696 else if (strcmp(name, "cursor") == 0)
4697 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004698 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004699
4700 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
4701 }
4702 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004703 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02004704 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004705 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004706 else if (strcmp(name, "width") == 0)
Bram Moolenaar02631462017-09-22 15:20:32 +02004707 return PyLong_FromLong((long)(self->win->w_width));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02004708 else if (strcmp(name, "col") == 0)
Bram Moolenaar53f81742017-09-22 14:35:51 +02004709 return PyLong_FromLong((long)(self->win->w_wincol));
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02004710 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02004711 return NEW_DICTIONARY(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004712 else if (strcmp(name, "options") == 0)
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02004713 return OptionsNew(SREQ_WIN, self->win, CheckWindowCb,
Bram Moolenaard6e39182013-05-21 18:30:34 +02004714 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02004715 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004716 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004717 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004718 return NULL;
4719 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004720 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004721 }
4722 else if (strcmp(name, "tabpage") == 0)
4723 {
Ken Takata9abd7152024-08-10 09:44:20 +02004724 Py_INCREF((PyObject *)self->tabObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02004725 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004726 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004727 else if (strcmp(name, "__members__") == 0)
4728 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004729 else
4730 return NULL;
4731}
4732
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004733 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004734WindowSetattr(PyObject *self_obj, char *name, PyObject *valObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004735{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004736 WindowObject *self = (WindowObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004737 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004738 return -1;
4739
4740 if (strcmp(name, "buffer") == 0)
4741 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004742 PyErr_SET_STRING(PyExc_TypeError, N_("readonly attribute: buffer"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004743 return -1;
4744 }
4745 else if (strcmp(name, "cursor") == 0)
4746 {
4747 long lnum;
4748 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004749
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004750 if (!PyArg_Parse(valObject, "(ll)", &lnum, &col))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004751 return -1;
4752
Bram Moolenaard6e39182013-05-21 18:30:34 +02004753 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004754 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004755 PyErr_SET_VIM(N_("cursor position outside buffer"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004756 return -1;
4757 }
4758
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004759 // Check for keyboard interrupts
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004760 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004761 return -1;
4762
Bram Moolenaard6e39182013-05-21 18:30:34 +02004763 self->win->w_cursor.lnum = lnum;
4764 self->win->w_cursor.col = col;
Bram Moolenaar53901442018-07-25 22:02:36 +02004765 self->win->w_set_curswant = TRUE;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004766 self->win->w_cursor.coladd = 0;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004767 // When column is out of range silently correct it.
Bram Moolenaard6e39182013-05-21 18:30:34 +02004768 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004769
Bram Moolenaara4d158b2022-08-14 14:17:45 +01004770 update_screen(UPD_VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004771 return 0;
4772 }
4773 else if (strcmp(name, "height") == 0)
4774 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004775 long height;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004776 win_T *savewin;
4777
Bram Moolenaardee2e312013-06-23 16:35:47 +02004778 if (NumberToLong(valObject, &height, NUMBER_INT|NUMBER_UNSIGNED))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004779 return -1;
4780
4781#ifdef FEAT_GUI
4782 need_mouse_correct = TRUE;
4783#endif
4784 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004785 curwin = self->win;
Bram Moolenaar6c87bbb2022-12-10 11:17:11 +00004786 curbuf = curwin->w_buffer;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004787
4788 VimTryStart();
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004789 win_setheight((int) height);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004790 curwin = savewin;
Bram Moolenaar6c87bbb2022-12-10 11:17:11 +00004791 curbuf = curwin->w_buffer;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004792 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004793 return -1;
4794
4795 return 0;
4796 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004797 else if (strcmp(name, "width") == 0)
4798 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004799 long width;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004800 win_T *savewin;
4801
Bram Moolenaardee2e312013-06-23 16:35:47 +02004802 if (NumberToLong(valObject, &width, NUMBER_INT|NUMBER_UNSIGNED))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004803 return -1;
4804
4805#ifdef FEAT_GUI
4806 need_mouse_correct = TRUE;
4807#endif
4808 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004809 curwin = self->win;
Bram Moolenaar6c87bbb2022-12-10 11:17:11 +00004810 curbuf = curwin->w_buffer;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004811
4812 VimTryStart();
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004813 win_setwidth((int) width);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004814 curwin = savewin;
Bram Moolenaar6c87bbb2022-12-10 11:17:11 +00004815 curbuf = curwin->w_buffer;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004816 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004817 return -1;
4818
4819 return 0;
4820 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004821 else
4822 {
4823 PyErr_SetString(PyExc_AttributeError, name);
4824 return -1;
4825 }
4826}
4827
4828 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004829WindowRepr(PyObject *self_obj)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004830{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02004831 WindowObject *self = (WindowObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004832 if (self->win == INVALID_WINDOW_VALUE)
Dominique Pellec14f6672022-01-09 12:57:48 +00004833 return PyString_FromFormat("<window object (deleted) at %p>", (void *)self);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004834 else
4835 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004836 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004837
Bram Moolenaar6d216452013-05-12 19:00:41 +02004838 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004839 return PyString_FromFormat("<window object (unknown) at %p>",
Dominique Pellec14f6672022-01-09 12:57:48 +00004840 (void *)self);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004841 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004842 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004843 }
4844}
4845
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004846static struct PyMethodDef WindowMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004847 // name, function, calling, documentation
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004848 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
4849 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004850};
4851
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004852/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004853 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004854 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004855
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004856DEFINE_PY_TYPE_OBJECT(WinListType);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004857static PySequenceMethods WinListAsSeq;
4858
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004859typedef struct
4860{
4861 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004862 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004863} WinListObject;
4864
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004865static WinListObject TheWindowList =
4866{
4867 PyObject_HEAD_INIT_TYPE(WinListType)
4868 NULL
4869};
4870
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004871 static PyObject *
4872WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004873{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004874 WinListObject *self;
4875
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004876 self = PyObject_NEW(WinListObject, WinListTypePtr);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004877 self->tabObject = tabObject;
Ken Takata9abd7152024-08-10 09:44:20 +02004878 Py_INCREF((PyObject *)tabObject);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004879
4880 return (PyObject *)(self);
4881}
4882
4883 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004884WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004885{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004886 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004887
4888 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02004889 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004890 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02004891 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004892
4893 DESTRUCTOR_FINISH(self);
4894}
4895
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004896 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004897WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004898{
4899 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004900 PyInt n = 0;
4901
Bram Moolenaard6e39182013-05-21 18:30:34 +02004902 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004903 return -1;
4904
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004905 while (w != NULL)
4906 {
4907 ++n;
4908 w = W_NEXT(w);
4909 }
4910
4911 return n;
4912}
4913
4914 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004915WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004916{
4917 win_T *w;
4918
Bram Moolenaard6e39182013-05-21 18:30:34 +02004919 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004920 return NULL;
4921
4922 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004923 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004924 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004925
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004926 PyErr_SET_STRING(PyExc_IndexError, N_("no such window"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004927 return NULL;
4928}
4929
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004930/*
4931 * Convert a Python string into a Vim line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004932 *
4933 * The result is in allocated memory. All internal nulls are replaced by
4934 * newline characters. It is an error for the string to contain newline
4935 * characters.
4936 *
4937 * On errors, the Python exception data is set, and NULL is returned.
4938 */
4939 static char *
4940StringToLine(PyObject *obj)
4941{
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004942 char *str;
4943 char *save;
4944 PyObject *bytes = NULL;
Bram Moolenaardee2e312013-06-23 16:35:47 +02004945 Py_ssize_t len = 0;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004946 PyInt i;
4947 char *p;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004948
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004949 if (PyBytes_Check(obj))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004950 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004951 if (PyBytes_AsStringAndSize(obj, &str, &len) == -1
4952 || str == NULL)
4953 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004954 }
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004955 else if (PyUnicode_Check(obj))
4956 {
Bram Moolenaar2e2f52a2020-12-21 16:03:02 +01004957 if (!(bytes = PyUnicode_AsEncodedString(obj, ENC_OPT,
4958 ERRORS_ENCODE_ARG)))
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004959 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004960
Bram Moolenaardaa27022013-06-24 22:33:30 +02004961 if (PyBytes_AsStringAndSize(bytes, &str, &len) == -1
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004962 || str == NULL)
4963 {
4964 Py_DECREF(bytes);
4965 return NULL;
4966 }
4967 }
Bram Moolenaardaa27022013-06-24 22:33:30 +02004968 else
4969 {
4970#if PY_MAJOR_VERSION < 3
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004971 PyErr_FORMAT_TYPE(
Bram Moolenaardaa27022013-06-24 22:33:30 +02004972 N_("expected str() or unicode() instance, but got %s"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004973 obj);
Bram Moolenaardaa27022013-06-24 22:33:30 +02004974#else
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004975 PyErr_FORMAT_TYPE(
Bram Moolenaardaa27022013-06-24 22:33:30 +02004976 N_("expected bytes() or str() instance, but got %s"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02004977 obj);
Bram Moolenaardaa27022013-06-24 22:33:30 +02004978#endif
4979 return NULL;
4980 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004981
4982 /*
4983 * Error checking: String must not contain newlines, as we
4984 * are replacing a single line, and we must replace it with
4985 * a single line.
4986 * A trailing newline is removed, so that append(f.readlines()) works.
4987 */
4988 p = memchr(str, '\n', len);
4989 if (p != NULL)
4990 {
4991 if (p == str + len - 1)
4992 --len;
4993 else
4994 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004995 PyErr_SET_VIM(N_("string cannot contain newlines"));
Bram Moolenaar841fbd22013-06-23 14:37:07 +02004996 Py_XDECREF(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004997 return NULL;
4998 }
4999 }
5000
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005001 /*
5002 * Create a copy of the string, with internal nulls replaced by
Bram Moolenaar86181df2020-05-11 23:14:04 +02005003 * newline characters, as is the Vim convention.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005004 */
Bram Moolenaarc799fe22019-05-28 23:08:19 +02005005 save = alloc(len+1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005006 if (save == NULL)
5007 {
5008 PyErr_NoMemory();
Bram Moolenaar841fbd22013-06-23 14:37:07 +02005009 Py_XDECREF(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005010 return NULL;
5011 }
5012
5013 for (i = 0; i < len; ++i)
5014 {
5015 if (str[i] == '\0')
5016 save[i] = '\n';
5017 else
5018 save[i] = str[i];
5019 }
5020
5021 save[i] = '\0';
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005022 Py_XDECREF(bytes); // Python 2 does nothing here
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005023
5024 return save;
5025}
5026
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005027/*
5028 * Get a line from the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005029 * in Vim format (1-based). The line is returned as a Python
5030 * string object.
5031 */
5032 static PyObject *
5033GetBufferLine(buf_T *buf, PyInt n)
5034{
5035 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
5036}
5037
5038
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005039/*
5040 * Get a list of lines from the specified buffer. The line numbers
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005041 * are in Vim format (1-based). The range is from lo up to, but not
5042 * including, hi. The list is returned as a Python list of string objects.
5043 */
5044 static PyObject *
5045GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
5046{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005047 PyInt i;
5048 PyInt n = hi - lo;
5049 PyObject *list = PyList_New(n);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005050
5051 if (list == NULL)
5052 return NULL;
5053
5054 for (i = 0; i < n; ++i)
5055 {
Bram Moolenaarbb790dc2020-07-07 20:12:54 +02005056 linenr_T lnum = (linenr_T)(lo + i);
5057 char *text;
5058 PyObject *string;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005059
Bram Moolenaarbb790dc2020-07-07 20:12:54 +02005060 if (lnum > buf->b_ml.ml_line_count)
5061 text = "";
5062 else
5063 text = (char *)ml_get_buf(buf, lnum, FALSE);
5064 string = LineToString(text);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005065 if (string == NULL)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005066 {
5067 Py_DECREF(list);
5068 return NULL;
5069 }
5070
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005071 PyList_SET_ITEM(list, i, string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005072 }
5073
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005074 // The ownership of the Python list is passed to the caller (ie,
5075 // the caller should Py_DECREF() the object when it is finished
5076 // with it).
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005077
5078 return list;
5079}
5080
5081/*
5082 * Check if deleting lines made the cursor position invalid.
5083 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
5084 * deleted).
5085 */
5086 static void
5087py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
5088{
5089 if (curwin->w_cursor.lnum >= lo)
5090 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005091 // Adjust the cursor position if it's in/after the changed
5092 // lines.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005093 if (curwin->w_cursor.lnum >= hi)
5094 {
5095 curwin->w_cursor.lnum += extra;
5096 check_cursor_col();
5097 }
5098 else if (extra < 0)
5099 {
5100 curwin->w_cursor.lnum = lo;
5101 check_cursor();
5102 }
5103 else
5104 check_cursor_col();
5105 changed_cline_bef_curs();
5106 }
5107 invalidate_botline();
5108}
5109
Bram Moolenaar19e60942011-06-19 00:27:51 +02005110/*
5111 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005112 * in Vim format (1-based). The replacement line is given as
5113 * a Python string object. The object is checked for validity
5114 * and correct format. Errors are returned as a value of FAIL.
5115 * The return value is OK on success.
5116 * If OK is returned and len_change is not NULL, *len_change
5117 * is set to the change in the buffer length.
5118 */
5119 static int
5120SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
5121{
Bram Moolenaar45e5fd12017-06-04 14:58:02 +02005122 bufref_T save_curbuf = {NULL, 0, 0};
Bram Moolenaar18f47402022-01-06 13:24:51 +00005123 switchwin_T switchwin;
Bram Moolenaaraf003f62013-07-24 17:11:46 +02005124
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005125 // First of all, we check the type of the supplied Python object.
5126 // There are three cases:
5127 // 1. NULL, or None - this is a deletion.
5128 // 2. A string - this is a replacement.
5129 // 3. Anything else - this is an error.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005130 if (line == Py_None || line == NULL)
5131 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005132 PyErr_Clear();
Bram Moolenaar18f47402022-01-06 13:24:51 +00005133 switchwin.sw_curwin = NULL;
5134 switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005135
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005136 VimTryStart();
5137
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005138 if (u_savedel((linenr_T)n, 1L) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02005139 RAISE_UNDO_FAIL;
Bram Moolenaarca70c072020-05-30 20:30:46 +02005140 else if (ml_delete((linenr_T)n) == FAIL)
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005141 RAISE_DELETE_LINE_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005142 else
5143 {
Bram Moolenaar18f47402022-01-06 13:24:51 +00005144 if (buf == curbuf && (switchwin.sw_curwin != NULL
Bram Moolenaar63dbfd32019-03-23 17:41:59 +01005145 || save_curbuf.br_buf == NULL))
5146 // Using an existing window for the buffer, adjust the cursor
5147 // position.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005148 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02005149 if (save_curbuf.br_buf == NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005150 // Only adjust marks if we managed to switch to a window that
5151 // holds the buffer, otherwise line numbers will be invalid.
Bram Moolenaaraf003f62013-07-24 17:11:46 +02005152 deleted_lines_mark((linenr_T)n, 1L);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005153 }
5154
Bram Moolenaar18f47402022-01-06 13:24:51 +00005155 restore_win_for_buf(&switchwin, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005156
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005157 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005158 return FAIL;
5159
5160 if (len_change)
5161 *len_change = -1;
5162
5163 return OK;
5164 }
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02005165 else if (PyBytes_Check(line) || PyUnicode_Check(line))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005166 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02005167 char *save = StringToLine(line);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005168
5169 if (save == NULL)
5170 return FAIL;
5171
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005172 VimTryStart();
5173
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005174 // We do not need to free "save" if ml_replace() consumes it.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005175 PyErr_Clear();
Bram Moolenaar18f47402022-01-06 13:24:51 +00005176 switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005177
5178 if (u_savesub((linenr_T)n) == FAIL)
5179 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005180 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005181 vim_free(save);
5182 }
5183 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
5184 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005185 RAISE_REPLACE_LINE_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005186 vim_free(save);
5187 }
5188 else
5189 changed_bytes((linenr_T)n, 0);
5190
Bram Moolenaar18f47402022-01-06 13:24:51 +00005191 restore_win_for_buf(&switchwin, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005192
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005193 // Check that the cursor is not beyond the end of the line now.
Bram Moolenaaraf003f62013-07-24 17:11:46 +02005194 if (buf == curbuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005195 check_cursor_col();
5196
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005197 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005198 return FAIL;
5199
5200 if (len_change)
5201 *len_change = 0;
5202
5203 return OK;
5204 }
5205 else
5206 {
5207 PyErr_BadArgument();
5208 return FAIL;
5209 }
5210}
5211
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005212/*
5213 * Replace a range of lines in the specified buffer. The line numbers are in
Bram Moolenaar19e60942011-06-19 00:27:51 +02005214 * Vim format (1-based). The range is from lo up to, but not including, hi.
5215 * The replacement lines are given as a Python list of string objects. The
5216 * list is checked for validity and correct format. Errors are returned as a
5217 * value of FAIL. The return value is OK on success.
5218 * If OK is returned and len_change is not NULL, *len_change
5219 * is set to the change in the buffer length.
5220 */
5221 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005222SetBufferLineList(
5223 buf_T *buf,
5224 PyInt lo,
5225 PyInt hi,
5226 PyObject *list,
5227 PyInt *len_change)
Bram Moolenaar19e60942011-06-19 00:27:51 +02005228{
Bram Moolenaar45e5fd12017-06-04 14:58:02 +02005229 bufref_T save_curbuf = {NULL, 0, 0};
Bram Moolenaar18f47402022-01-06 13:24:51 +00005230 switchwin_T switchwin;
Bram Moolenaaraf003f62013-07-24 17:11:46 +02005231
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005232 // First of all, we check the type of the supplied Python object.
5233 // There are three cases:
5234 // 1. NULL, or None - this is a deletion.
5235 // 2. A list - this is a replacement.
5236 // 3. Anything else - this is an error.
Bram Moolenaar19e60942011-06-19 00:27:51 +02005237 if (list == Py_None || list == NULL)
5238 {
5239 PyInt i;
5240 PyInt n = (int)(hi - lo);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005241
5242 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005243 VimTryStart();
Bram Moolenaar18f47402022-01-06 13:24:51 +00005244 switchwin.sw_curwin = NULL;
5245 switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005246
5247 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02005248 RAISE_UNDO_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02005249 else
5250 {
5251 for (i = 0; i < n; ++i)
5252 {
Bram Moolenaarca70c072020-05-30 20:30:46 +02005253 if (ml_delete((linenr_T)lo) == FAIL)
Bram Moolenaar19e60942011-06-19 00:27:51 +02005254 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005255 RAISE_DELETE_LINE_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02005256 break;
5257 }
5258 }
Bram Moolenaar18f47402022-01-06 13:24:51 +00005259 if (buf == curbuf && (switchwin.sw_curwin != NULL
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02005260 || save_curbuf.br_buf == NULL))
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005261 // Using an existing window for the buffer, adjust the cursor
5262 // position.
Bram Moolenaar19e60942011-06-19 00:27:51 +02005263 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02005264 if (save_curbuf.br_buf == NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005265 // Only adjust marks if we managed to switch to a window that
5266 // holds the buffer, otherwise line numbers will be invalid.
Bram Moolenaaraf003f62013-07-24 17:11:46 +02005267 deleted_lines_mark((linenr_T)lo, (long)i);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005268 }
5269
Bram Moolenaar18f47402022-01-06 13:24:51 +00005270 restore_win_for_buf(&switchwin, &save_curbuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005271
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005272 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02005273 return FAIL;
5274
5275 if (len_change)
5276 *len_change = -n;
5277
5278 return OK;
5279 }
5280 else if (PyList_Check(list))
5281 {
5282 PyInt i;
5283 PyInt new_len = PyList_Size(list);
5284 PyInt old_len = hi - lo;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005285 PyInt extra = 0; // lines added to text, can be negative
Bram Moolenaar19e60942011-06-19 00:27:51 +02005286 char **array;
Bram Moolenaar19e60942011-06-19 00:27:51 +02005287
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005288 if (new_len == 0) // avoid allocating zero bytes
Bram Moolenaar19e60942011-06-19 00:27:51 +02005289 array = NULL;
5290 else
5291 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005292 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005293 if (array == NULL)
5294 {
5295 PyErr_NoMemory();
5296 return FAIL;
5297 }
5298 }
5299
5300 for (i = 0; i < new_len; ++i)
5301 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02005302 PyObject *line;
Bram Moolenaar19e60942011-06-19 00:27:51 +02005303
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02005304 if (!(line = PyList_GetItem(list, i)) ||
5305 !(array[i] = StringToLine(line)))
Bram Moolenaar19e60942011-06-19 00:27:51 +02005306 {
5307 while (i)
5308 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005309 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005310 return FAIL;
5311 }
5312 }
5313
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005314 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02005315 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02005316
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005317 // START of region without "return". Must call restore_buffer()!
Bram Moolenaar18f47402022-01-06 13:24:51 +00005318 switchwin.sw_curwin = NULL;
5319 switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005320
5321 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02005322 RAISE_UNDO_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02005323
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005324 // If the size of the range is reducing (ie, new_len < old_len) we
5325 // need to delete some old_len. We do this at the start, by
5326 // repeatedly deleting line "lo".
Bram Moolenaar19e60942011-06-19 00:27:51 +02005327 if (!PyErr_Occurred())
5328 {
5329 for (i = 0; i < old_len - new_len; ++i)
Bram Moolenaarca70c072020-05-30 20:30:46 +02005330 if (ml_delete((linenr_T)lo) == FAIL)
Bram Moolenaar19e60942011-06-19 00:27:51 +02005331 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005332 RAISE_DELETE_LINE_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02005333 break;
5334 }
5335 extra -= i;
5336 }
5337
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005338 // For as long as possible, replace the existing old_len with the
5339 // new old_len. This is a more efficient operation, as it requires
5340 // less memory allocation and freeing.
Bram Moolenaar19e60942011-06-19 00:27:51 +02005341 if (!PyErr_Occurred())
5342 {
5343 for (i = 0; i < old_len && i < new_len; ++i)
5344 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
5345 == FAIL)
5346 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005347 RAISE_REPLACE_LINE_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02005348 break;
5349 }
5350 }
5351 else
5352 i = 0;
5353
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005354 // Now we may need to insert the remaining new old_len. If we do, we
5355 // must free the strings as we finish with them (we can't pass the
Bram Moolenaar86181df2020-05-11 23:14:04 +02005356 // responsibility to Vim in this case).
Bram Moolenaar19e60942011-06-19 00:27:51 +02005357 if (!PyErr_Occurred())
5358 {
5359 while (i < new_len)
5360 {
5361 if (ml_append((linenr_T)(lo + i - 1),
5362 (char_u *)array[i], 0, FALSE) == FAIL)
5363 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005364 RAISE_INSERT_LINE_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02005365 break;
5366 }
5367 vim_free(array[i]);
5368 ++i;
5369 ++extra;
5370 }
5371 }
5372
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005373 // Free any left-over old_len, as a result of an error
Bram Moolenaar19e60942011-06-19 00:27:51 +02005374 while (i < new_len)
5375 {
5376 vim_free(array[i]);
5377 ++i;
5378 }
5379
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005380 // Free the array of old_len. All of its contents have now
5381 // been dealt with (either freed, or the responsibility passed
5382 // to vim.
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005383 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005384
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005385 // Adjust marks. Invalidate any which lie in the
5386 // changed range, and move any in the remainder of the buffer.
5387 // Only adjust marks if we managed to switch to a window that holds
5388 // the buffer, otherwise line numbers will be invalid.
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02005389 if (save_curbuf.br_buf == NULL)
Bram Moolenaar37233f62022-05-22 12:23:48 +01005390 {
Bram Moolenaaraf003f62013-07-24 17:11:46 +02005391 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
Bram Moolenaar19e60942011-06-19 00:27:51 +02005392 (long)MAXLNUM, (long)extra);
Bram Moolenaar37233f62022-05-22 12:23:48 +01005393 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
5394 }
Bram Moolenaar19e60942011-06-19 00:27:51 +02005395
Bram Moolenaar18f47402022-01-06 13:24:51 +00005396 if (buf == curbuf && (switchwin.sw_curwin != NULL
Bram Moolenaar63dbfd32019-03-23 17:41:59 +01005397 || save_curbuf.br_buf == NULL))
5398 // Using an existing window for the buffer, adjust the cursor
5399 // position.
Bram Moolenaar19e60942011-06-19 00:27:51 +02005400 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
5401
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005402 // END of region without "return".
Bram Moolenaar18f47402022-01-06 13:24:51 +00005403 restore_win_for_buf(&switchwin, &save_curbuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02005404
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005405 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02005406 return FAIL;
5407
5408 if (len_change)
5409 *len_change = new_len - old_len;
5410
5411 return OK;
5412 }
5413 else
5414 {
5415 PyErr_BadArgument();
5416 return FAIL;
5417 }
5418}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005419
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005420/*
5421 * Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005422 * The line number is in Vim format (1-based). The lines to be inserted are
5423 * given as a Python list of string objects or as a single string. The lines
5424 * to be added are checked for validity and correct format. Errors are
5425 * returned as a value of FAIL. The return value is OK on success.
5426 * If OK is returned and len_change is not NULL, *len_change
5427 * is set to the change in the buffer length.
5428 */
5429 static int
5430InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
5431{
Bram Moolenaar45e5fd12017-06-04 14:58:02 +02005432 bufref_T save_curbuf = {NULL, 0, 0};
Bram Moolenaar18f47402022-01-06 13:24:51 +00005433 switchwin_T switchwin;
Bram Moolenaar95064ec2013-07-17 17:15:25 +02005434
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005435 // First of all, we check the type of the supplied Python object.
5436 // It must be a string or a list, or the call is in error.
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02005437 if (PyBytes_Check(lines) || PyUnicode_Check(lines))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005438 {
Bram Moolenaar95064ec2013-07-17 17:15:25 +02005439 char *str = StringToLine(lines);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005440
5441 if (str == NULL)
5442 return FAIL;
5443
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005444 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005445 VimTryStart();
Bram Moolenaar18f47402022-01-06 13:24:51 +00005446 switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005447
Bram Moolenaar95064ec2013-07-17 17:15:25 +02005448 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02005449 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005450 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005451 RAISE_INSERT_LINE_FAIL;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02005452 else if (save_curbuf.br_buf == NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005453 // Only adjust marks if we managed to switch to a window that
5454 // holds the buffer, otherwise line numbers will be invalid.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005455 appended_lines_mark((linenr_T)n, 1L);
5456
5457 vim_free(str);
Bram Moolenaar18f47402022-01-06 13:24:51 +00005458 restore_win_for_buf(&switchwin, &save_curbuf);
Bram Moolenaara4d158b2022-08-14 14:17:45 +01005459 update_screen(UPD_VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005460
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005461 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005462 return FAIL;
5463
5464 if (len_change)
5465 *len_change = 1;
5466
5467 return OK;
5468 }
5469 else if (PyList_Check(lines))
5470 {
5471 PyInt i;
5472 PyInt size = PyList_Size(lines);
5473 char **array;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005474
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005475 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005476 if (array == NULL)
5477 {
5478 PyErr_NoMemory();
5479 return FAIL;
5480 }
5481
5482 for (i = 0; i < size; ++i)
5483 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02005484 PyObject *line;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005485
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02005486 if (!(line = PyList_GetItem(lines, i)) ||
5487 !(array[i] = StringToLine(line)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005488 {
5489 while (i)
5490 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005491 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005492 return FAIL;
5493 }
5494 }
5495
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005496 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005497 VimTryStart();
Bram Moolenaar18f47402022-01-06 13:24:51 +00005498 switch_to_win_for_buf(buf, &switchwin, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005499
5500 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02005501 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005502 else
5503 {
5504 for (i = 0; i < size; ++i)
5505 {
5506 if (ml_append((linenr_T)(n + i),
5507 (char_u *)array[i], 0, FALSE) == FAIL)
5508 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005509 RAISE_INSERT_LINE_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005510
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005511 // Free the rest of the lines
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005512 while (i < size)
5513 vim_free(array[i++]);
5514
5515 break;
5516 }
5517 vim_free(array[i]);
5518 }
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02005519 if (i > 0 && save_curbuf.br_buf == NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005520 // Only adjust marks if we managed to switch to a window that
5521 // holds the buffer, otherwise line numbers will be invalid.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005522 appended_lines_mark((linenr_T)n, (long)i);
5523 }
5524
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005525 // Free the array of lines. All of its contents have now
5526 // been freed.
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005527 PyMem_Free(array);
Bram Moolenaar18f47402022-01-06 13:24:51 +00005528 restore_win_for_buf(&switchwin, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005529
Bram Moolenaara4d158b2022-08-14 14:17:45 +01005530 update_screen(UPD_VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005531
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005532 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005533 return FAIL;
5534
5535 if (len_change)
5536 *len_change = size;
5537
5538 return OK;
5539 }
5540 else
5541 {
5542 PyErr_BadArgument();
5543 return FAIL;
5544 }
5545}
5546
5547/*
5548 * Common routines for buffers and line ranges
5549 * -------------------------------------------
5550 */
5551
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005552typedef struct
5553{
5554 PyObject_HEAD
5555 buf_T *buf;
5556} BufferObject;
5557
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005558 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02005559CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005560{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005561 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005562 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005563 PyErr_SET_VIM(N_("attempt to refer to deleted buffer"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005564 return -1;
5565 }
5566
5567 return 0;
5568}
5569
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02005570 static int
5571CheckBufferCb(void *self)
5572{
5573 return CheckBuffer((BufferObject*)self);
5574}
5575
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005576 static PyObject *
5577RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
5578{
5579 if (CheckBuffer(self))
5580 return NULL;
5581
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02005582 if (end == -1)
5583 end = self->buf->b_ml.ml_line_count;
5584
Bram Moolenaarbd80f352013-05-12 21:16:23 +02005585 if (n < 0)
5586 n += end - start + 1;
5587
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005588 if (n < 0 || n > end - start)
5589 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005590 PyErr_SET_STRING(PyExc_IndexError, N_("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005591 return NULL;
5592 }
5593
5594 return GetBufferLine(self->buf, n+start);
5595}
5596
5597 static PyObject *
5598RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
5599{
5600 PyInt size;
5601
5602 if (CheckBuffer(self))
5603 return NULL;
5604
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02005605 if (end == -1)
5606 end = self->buf->b_ml.ml_line_count;
5607
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005608 size = end - start + 1;
5609
5610 if (lo < 0)
5611 lo = 0;
5612 else if (lo > size)
5613 lo = size;
5614 if (hi < 0)
5615 hi = 0;
5616 if (hi < lo)
5617 hi = lo;
5618 else if (hi > size)
5619 hi = size;
5620
5621 return GetBufferLineList(self->buf, lo+start, hi+start);
5622}
5623
5624 static PyInt
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005625RBAsItem(
5626 BufferObject *self,
5627 PyInt n,
5628 PyObject *valObject,
5629 PyInt start,
5630 PyInt end,
5631 PyInt *new_end)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005632{
5633 PyInt len_change;
5634
5635 if (CheckBuffer(self))
5636 return -1;
5637
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02005638 if (end == -1)
5639 end = self->buf->b_ml.ml_line_count;
5640
Bram Moolenaarbd80f352013-05-12 21:16:23 +02005641 if (n < 0)
5642 n += end - start + 1;
5643
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005644 if (n < 0 || n > end - start)
5645 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005646 PyErr_SET_STRING(PyExc_IndexError, N_("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005647 return -1;
5648 }
5649
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005650 if (SetBufferLine(self->buf, n+start, valObject, &len_change) == FAIL)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005651 return -1;
5652
5653 if (new_end)
5654 *new_end = end + len_change;
5655
5656 return 0;
5657}
5658
Bram Moolenaar19e60942011-06-19 00:27:51 +02005659 static PyInt
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005660RBAsSlice(
5661 BufferObject *self,
5662 PyInt lo,
5663 PyInt hi,
5664 PyObject *valObject,
5665 PyInt start,
5666 PyInt end,
5667 PyInt *new_end)
Bram Moolenaar19e60942011-06-19 00:27:51 +02005668{
5669 PyInt size;
5670 PyInt len_change;
5671
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005672 // Self must be a valid buffer
Bram Moolenaar19e60942011-06-19 00:27:51 +02005673 if (CheckBuffer(self))
5674 return -1;
5675
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02005676 if (end == -1)
5677 end = self->buf->b_ml.ml_line_count;
5678
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005679 // Sort out the slice range
Bram Moolenaar19e60942011-06-19 00:27:51 +02005680 size = end - start + 1;
5681
5682 if (lo < 0)
5683 lo = 0;
5684 else if (lo > size)
5685 lo = size;
5686 if (hi < 0)
5687 hi = 0;
5688 if (hi < lo)
5689 hi = lo;
5690 else if (hi > size)
5691 hi = size;
5692
5693 if (SetBufferLineList(self->buf, lo + start, hi + start,
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005694 valObject, &len_change) == FAIL)
Bram Moolenaar19e60942011-06-19 00:27:51 +02005695 return -1;
5696
5697 if (new_end)
5698 *new_end = end + len_change;
5699
5700 return 0;
5701}
5702
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005703
5704 static PyObject *
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005705RBAppend(
5706 BufferObject *self,
5707 PyObject *args,
5708 PyInt start,
5709 PyInt end,
5710 PyInt *new_end)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005711{
5712 PyObject *lines;
5713 PyInt len_change;
5714 PyInt max;
5715 PyInt n;
5716
5717 if (CheckBuffer(self))
5718 return NULL;
5719
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02005720 if (end == -1)
5721 end = self->buf->b_ml.ml_line_count;
5722
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005723 max = n = end - start + 1;
5724
5725 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
5726 return NULL;
5727
5728 if (n < 0 || n > max)
5729 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005730 PyErr_SET_STRING(PyExc_IndexError, N_("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005731 return NULL;
5732 }
5733
5734 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
5735 return NULL;
5736
5737 if (new_end)
5738 *new_end = end + len_change;
5739
5740 Py_INCREF(Py_None);
5741 return Py_None;
5742}
5743
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005744// Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005745
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02005746DEFINE_PY_TYPE_OBJECT(RangeType);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005747static PySequenceMethods RangeAsSeq;
5748static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005749
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005750typedef struct
5751{
5752 PyObject_HEAD
5753 BufferObject *buf;
5754 PyInt start;
5755 PyInt end;
5756} RangeObject;
5757
5758 static PyObject *
5759RangeNew(buf_T *buf, PyInt start, PyInt end)
5760{
5761 BufferObject *bufr;
5762 RangeObject *self;
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02005763 self = PyObject_GC_New(RangeObject, RangeTypePtr);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005764 if (self == NULL)
5765 return NULL;
5766
5767 bufr = (BufferObject *)BufferNew(buf);
5768 if (bufr == NULL)
5769 {
5770 Py_DECREF(self);
5771 return NULL;
5772 }
Ken Takata9abd7152024-08-10 09:44:20 +02005773 Py_INCREF((PyObject *)bufr);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005774
5775 self->buf = bufr;
5776 self->start = start;
5777 self->end = end;
5778
5779 return (PyObject *)(self);
5780}
5781
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005782 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005783RangeDestructor(PyObject *self_obj)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005784{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005785 RangeObject *self = (RangeObject*)self_obj;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005786 PyObject_GC_UnTrack((void *)(self));
oreo6390a825bd2025-03-09 08:54:21 +01005787 Py_XDECREF(((PyObject *)(self->buf)));
Bram Moolenaar774267b2013-05-21 20:51:59 +02005788 PyObject_GC_Del((void *)(self));
5789}
5790
5791 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005792RangeTraverse(PyObject *self_obj, visitproc visit, void *arg)
Bram Moolenaar774267b2013-05-21 20:51:59 +02005793{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005794 RangeObject *self = (RangeObject*)self_obj;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005795 Py_VISIT(((PyObject *)(self->buf)));
5796 return 0;
5797}
5798
5799 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005800RangeClear(PyObject *self_obj)
Bram Moolenaar774267b2013-05-21 20:51:59 +02005801{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005802 RangeObject *self = (RangeObject*)self_obj;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005803 Py_CLEAR(self->buf);
5804 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005805}
5806
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005807 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02005808RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005809{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005810 // HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION?
Bram Moolenaard6e39182013-05-21 18:30:34 +02005811 if (CheckBuffer(self->buf))
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005812 return -1; // ???
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005813
Bram Moolenaard6e39182013-05-21 18:30:34 +02005814 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005815}
5816
5817 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005818RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005819{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005820 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005821}
5822
5823 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005824RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005825{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005826 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005827}
5828
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005829static char *RangeAttrs[] = {
5830 "start", "end",
5831 NULL
5832};
5833
5834 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02005835RangeDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005836{
5837 return ObjectDir(self, RangeAttrs);
5838}
5839
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005840 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005841RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005842{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005843 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005844}
5845
5846 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005847RangeRepr(PyObject *self_obj)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005848{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005849 RangeObject *self = (RangeObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005850 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02005851 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
Dominique Pellec14f6672022-01-09 12:57:48 +00005852 (void *)self);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005853 else
5854 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02005855 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005856
5857 if (name == NULL)
5858 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005859
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02005860 return PyString_FromFormat("<range %s (%d:%d)>",
Bram Moolenaarf62d9422013-05-30 19:01:24 +02005861 name, (int)self->start, (int)self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005862 }
5863}
5864
5865static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005866 // name, function, calling, documentation
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02005867 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005868 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
5869 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005870};
5871
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02005872DEFINE_PY_TYPE_OBJECT(BufferType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005873static PySequenceMethods BufferAsSeq;
5874static PyMappingMethods BufferAsMapping;
5875
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005876 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02005877BufferNew(buf_T *buf)
5878{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005879 /*
5880 * We need to handle deletion of buffers underneath us.
Bram Moolenaar971db462013-05-12 18:44:48 +02005881 * If we add a "b_python*_ref" field to the buf_T structure,
5882 * then we can get at it in buf_freeall() in vim. We then
5883 * need to create only ONE Python object per buffer - if
5884 * we try to create a second, just INCREF the existing one
5885 * and return it. The (single) Python object referring to
5886 * the buffer is stored in "b_python*_ref".
5887 * Question: what to do on a buf_freeall(). We'll probably
5888 * have to either delete the Python object (DECREF it to
5889 * zero - a bad idea, as it leaves dangling refs!) or
5890 * set the buf_T * value to an invalid value (-1?), which
5891 * means we need checks in all access functions... Bah.
5892 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005893 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02005894 * b_python_ref and b_python3_ref fields respectively.
5895 */
5896
5897 BufferObject *self;
5898
5899 if (BUF_PYTHON_REF(buf) != NULL)
5900 {
5901 self = BUF_PYTHON_REF(buf);
Ken Takata9abd7152024-08-10 09:44:20 +02005902 Py_INCREF((PyObject *)self);
Bram Moolenaar971db462013-05-12 18:44:48 +02005903 }
5904 else
5905 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02005906 self = PyObject_NEW(BufferObject, BufferTypePtr);
Bram Moolenaar971db462013-05-12 18:44:48 +02005907 if (self == NULL)
5908 return NULL;
5909 self->buf = buf;
5910 BUF_PYTHON_REF(buf) = self;
5911 }
5912
5913 return (PyObject *)(self);
5914}
5915
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005916 static void
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005917BufferDestructor(PyObject *self_obj)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005918{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005919 BufferObject *self = (BufferObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005920 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
5921 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005922
5923 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005924}
5925
Bram Moolenaar971db462013-05-12 18:44:48 +02005926 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02005927BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02005928{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005929 // HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION?
Bram Moolenaard6e39182013-05-21 18:30:34 +02005930 if (CheckBuffer(self))
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005931 return -1; // ???
Bram Moolenaar971db462013-05-12 18:44:48 +02005932
Bram Moolenaard6e39182013-05-21 18:30:34 +02005933 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02005934}
5935
5936 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005937BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02005938{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005939 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02005940}
5941
5942 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005943BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02005944{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005945 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02005946}
5947
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005948static char *BufferAttrs[] = {
5949 "name", "number", "vars", "options", "valid",
5950 NULL
5951};
5952
5953 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02005954BufferDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005955{
5956 return ObjectDir(self, BufferAttrs);
5957}
5958
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005959 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02005960BufferAttrValid(BufferObject *self, char *name)
5961{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005962 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02005963
5964 if (strcmp(name, "valid") != 0)
5965 return NULL;
5966
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005967 ret = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
5968 Py_INCREF(ret);
5969 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02005970}
5971
5972 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005973BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005974{
5975 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02005976 return PyString_FromString((self->buf->b_ffname == NULL
Bram Moolenaar41009372013-07-01 22:03:04 +02005977 ? "" : (char *)self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005978 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02005979 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005980 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02005981 return NEW_DICTIONARY(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005982 else if (strcmp(name, "options") == 0)
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02005983 return OptionsNew(SREQ_BUF, self->buf, CheckBufferCb,
Bram Moolenaard6e39182013-05-21 18:30:34 +02005984 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005985 else if (strcmp(name, "__members__") == 0)
5986 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005987 else
5988 return NULL;
5989}
5990
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005991 static int
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005992BufferSetattr(PyObject *self_obj, char *name, PyObject *valObject)
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005993{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02005994 BufferObject *self = (BufferObject*)self_obj;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005995 if (CheckBuffer(self))
5996 return -1;
5997
5998 if (strcmp(name, "name") == 0)
5999 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006000 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02006001 aco_save_T aco;
Bram Moolenaar37199892022-11-29 13:46:48 +00006002 int ren_ret = OK;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02006003 PyObject *todecref;
6004
6005 if (!(val = StringToChars(valObject, &todecref)))
6006 return -1;
6007
6008 VimTryStart();
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006009 // Using aucmd_*: autocommands will be executed by rename_buffer
Bram Moolenaare9ba5162013-05-29 22:02:22 +02006010 aucmd_prepbuf(&aco, self->buf);
Bram Moolenaare76062c2022-11-28 18:51:43 +00006011 if (curbuf == self->buf)
6012 {
6013 ren_ret = rename_buffer(val);
6014 aucmd_restbuf(&aco);
6015 }
Bram Moolenaare9ba5162013-05-29 22:02:22 +02006016 Py_XDECREF(todecref);
6017 if (VimTryEnd())
6018 return -1;
6019
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006020 if (ren_ret == FAIL)
Bram Moolenaare9ba5162013-05-29 22:02:22 +02006021 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006022 PyErr_SET_VIM(N_("failed to rename buffer"));
Bram Moolenaare9ba5162013-05-29 22:02:22 +02006023 return -1;
6024 }
6025 return 0;
6026 }
6027 else
6028 {
6029 PyErr_SetString(PyExc_AttributeError, name);
6030 return -1;
6031 }
6032}
6033
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006034 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02006035BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006036{
Bram Moolenaard6e39182013-05-21 18:30:34 +02006037 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006038}
6039
6040 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02006041BufferMark(BufferObject *self, PyObject *pmarkObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006042{
6043 pos_T *posp;
Bram Moolenaar389a1792013-06-23 13:00:44 +02006044 char_u *pmark;
6045 char_u mark;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006046 bufref_T savebuf;
Bram Moolenaar389a1792013-06-23 13:00:44 +02006047 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006048
Bram Moolenaard6e39182013-05-21 18:30:34 +02006049 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006050 return NULL;
6051
Bram Moolenaar389a1792013-06-23 13:00:44 +02006052 if (!(pmark = StringToChars(pmarkObject, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006053 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006054
Bram Moolenaar389a1792013-06-23 13:00:44 +02006055 if (pmark[0] == '\0' || pmark[1] != '\0')
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02006056 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02006057 PyErr_SET_STRING(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006058 N_("mark name must be a single character"));
Bram Moolenaar841fbd22013-06-23 14:37:07 +02006059 Py_XDECREF(todecref);
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02006060 return NULL;
6061 }
6062
6063 mark = *pmark;
Bram Moolenaar389a1792013-06-23 13:00:44 +02006064
6065 Py_XDECREF(todecref);
6066
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006067 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02006068 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006069 posp = getmark(mark, FALSE);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02006070 restore_buffer(&savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006071 if (VimTryEnd())
6072 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006073
6074 if (posp == NULL)
6075 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006076 PyErr_SET_VIM(N_("invalid mark name"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006077 return NULL;
6078 }
6079
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006080 if (posp->lnum <= 0)
6081 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006082 // Or raise an error?
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006083 Py_INCREF(Py_None);
6084 return Py_None;
6085 }
6086
6087 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
6088}
6089
6090 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02006091BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006092{
6093 PyInt start;
6094 PyInt end;
6095
Bram Moolenaard6e39182013-05-21 18:30:34 +02006096 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006097 return NULL;
6098
6099 if (!PyArg_ParseTuple(args, "nn", &start, &end))
6100 return NULL;
6101
Bram Moolenaard6e39182013-05-21 18:30:34 +02006102 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006103}
6104
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006105 static PyObject *
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02006106BufferRepr(PyObject *self_obj)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006107{
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02006108 BufferObject *self = (BufferObject*)self_obj;
Bram Moolenaard6e39182013-05-21 18:30:34 +02006109 if (self->buf == INVALID_BUFFER_VALUE)
Dominique Pellec14f6672022-01-09 12:57:48 +00006110 return PyString_FromFormat("<buffer object (deleted) at %p>", (void *)self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006111 else
6112 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02006113 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006114
6115 if (name == NULL)
6116 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006117
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02006118 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006119 }
6120}
6121
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006122static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006123 // name, function, calling, documentation
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02006124 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
Bram Moolenaar389a1792013-06-23 13:00:44 +02006125 {"mark", (PyCFunction)BufferMark, METH_O, "Return (row,col) representing position of named mark" },
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02006126 {"range", (PyCFunction)BufferRange, METH_VARARGS, "Return a range object which represents the part of the given buffer between line numbers s and e" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006127 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
6128 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006129};
6130
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006131/*
6132 * Buffer list object - Implementation
6133 */
6134
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006135DEFINE_PY_TYPE_OBJECT(BufMapType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006136
6137typedef struct
6138{
6139 PyObject_HEAD
6140} BufMapObject;
6141
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006142static BufMapObject TheBufferMap =
6143{
6144 PyObject_HEAD_INIT_TYPE(BufMapType)
6145};
6146
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006147 static PyInt
6148BufMapLength(PyObject *self UNUSED)
6149{
6150 buf_T *b = firstbuf;
6151 PyInt n = 0;
6152
6153 while (b)
6154 {
6155 ++n;
6156 b = b->b_next;
6157 }
6158
6159 return n;
6160}
6161
6162 static PyObject *
6163BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
6164{
6165 buf_T *b;
Bram Moolenaar141be8a2013-06-23 14:16:57 +02006166 long bnr;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006167
Bram Moolenaar141be8a2013-06-23 14:16:57 +02006168 if (NumberToLong(keyObject, &bnr, NUMBER_INT|NUMBER_NATURAL))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006169 return NULL;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006170
Bram Moolenaar141be8a2013-06-23 14:16:57 +02006171 b = buflist_findnr((int) bnr);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006172
6173 if (b)
6174 return BufferNew(b);
6175 else
6176 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02006177 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006178 return NULL;
6179 }
6180}
6181
6182 static void
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006183BufMapIterDestruct(void* arg)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006184{
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006185 PyObject *buffer = (PyObject*)arg;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006186 // Iteration was stopped before all buffers were processed
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006187 if (buffer)
6188 {
6189 Py_DECREF(buffer);
6190 }
6191}
6192
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02006193 static int
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006194BufMapIterTraverse(void *iter, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02006195{
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006196 PyObject *buffer = (PyObject*)iter;
Bram Moolenaar774267b2013-05-21 20:51:59 +02006197 if (buffer)
6198 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02006199 return 0;
6200}
6201
6202 static int
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006203BufMapIterClear(void **iter)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02006204{
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006205 PyObject **buffer = (PyObject**)iter;
Bram Moolenaar774267b2013-05-21 20:51:59 +02006206 if (*buffer)
6207 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02006208 return 0;
6209}
6210
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006211 static PyObject *
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006212BufMapIterNext(void **arg)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006213{
6214 PyObject *next;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006215 PyObject *ret;
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006216 PyObject **buffer = (PyObject**)arg;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006217
6218 if (!*buffer)
6219 return NULL;
6220
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006221 ret = *buffer;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006222
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006223 if (CheckBuffer((BufferObject *)(ret)))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006224 {
6225 *buffer = NULL;
6226 return NULL;
6227 }
6228
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006229 if (!((BufferObject *)(ret))->buf->b_next)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006230 next = NULL;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006231 else if (!(next = BufferNew(((BufferObject *)(ret))->buf->b_next)))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006232 return NULL;
6233 *buffer = next;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006234 // Do not increment reference: we no longer hold it (decref), but whoever
6235 // on other side will hold (incref). Decref+incref = nothing.
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006236 return ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006237}
6238
6239 static PyObject *
Bram Moolenaar423a85a2020-08-29 12:57:16 +02006240BufMapIter(PyObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006241{
6242 PyObject *buffer;
6243
6244 buffer = BufferNew(firstbuf);
6245 return IterNew(buffer,
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006246 BufMapIterDestruct, BufMapIterNext,
6247 BufMapIterTraverse, BufMapIterClear,
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02006248 self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006249}
6250
6251static PyMappingMethods BufMapAsMapping = {
6252 (lenfunc) BufMapLength,
6253 (binaryfunc) BufMapItem,
6254 (objobjargproc) 0,
6255};
6256
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006257// Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02006258
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006259static char *CurrentAttrs[] = {
6260 "buffer", "window", "line", "range", "tabpage",
6261 NULL
6262};
6263
6264 static PyObject *
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02006265CurrentDir(PyObject *self, PyObject *args UNUSED)
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006266{
6267 return ObjectDir(self, CurrentAttrs);
6268}
6269
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006270 static PyObject *
6271CurrentGetattr(PyObject *self UNUSED, char *name)
6272{
6273 if (strcmp(name, "buffer") == 0)
6274 return (PyObject *)BufferNew(curbuf);
6275 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02006276 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02006277 else if (strcmp(name, "tabpage") == 0)
6278 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006279 else if (strcmp(name, "line") == 0)
6280 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
6281 else if (strcmp(name, "range") == 0)
6282 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006283 else if (strcmp(name, "__members__") == 0)
6284 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006285 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006286#if PY_MAJOR_VERSION < 3
6287 return Py_FindMethod(WindowMethods, self, name);
6288#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006289 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006290#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006291}
6292
6293 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006294CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *valObject)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006295{
6296 if (strcmp(name, "line") == 0)
6297 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006298 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, valObject,
6299 NULL) == FAIL)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006300 return -1;
6301
6302 return 0;
6303 }
Bram Moolenaare7614592013-05-15 15:51:08 +02006304 else if (strcmp(name, "buffer") == 0)
6305 {
6306 int count;
6307
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006308 if (valObject->ob_type != BufferTypePtr)
Bram Moolenaare7614592013-05-15 15:51:08 +02006309 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006310 PyErr_FORMAT_TYPE(
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006311 N_("expected vim.Buffer object, but got %s"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006312 valObject);
Bram Moolenaare7614592013-05-15 15:51:08 +02006313 return -1;
6314 }
6315
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006316 if (CheckBuffer((BufferObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02006317 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006318 count = ((BufferObject *)(valObject))->buf->b_fnum;
Bram Moolenaare7614592013-05-15 15:51:08 +02006319
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006320 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02006321 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
6322 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006323 if (VimTryEnd())
6324 return -1;
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006325 PyErr_VIM_FORMAT(N_("failed to switch to buffer %d"), count);
Bram Moolenaare7614592013-05-15 15:51:08 +02006326 return -1;
6327 }
6328
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006329 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02006330 }
6331 else if (strcmp(name, "window") == 0)
6332 {
6333 int count;
6334
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006335 if (valObject->ob_type != WindowTypePtr)
Bram Moolenaare7614592013-05-15 15:51:08 +02006336 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006337 PyErr_FORMAT_TYPE(
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006338 N_("expected vim.Window object, but got %s"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006339 valObject);
Bram Moolenaare7614592013-05-15 15:51:08 +02006340 return -1;
6341 }
6342
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006343 if (CheckWindow((WindowObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02006344 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006345 count = get_win_number(((WindowObject *)(valObject))->win, firstwin);
Bram Moolenaare7614592013-05-15 15:51:08 +02006346
6347 if (!count)
6348 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02006349 PyErr_SET_STRING(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006350 N_("failed to find window in the current tab page"));
Bram Moolenaare7614592013-05-15 15:51:08 +02006351 return -1;
6352 }
6353
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006354 VimTryStart();
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006355 win_goto(((WindowObject *)(valObject))->win);
6356 if (((WindowObject *)(valObject))->win != curwin)
Bram Moolenaare7614592013-05-15 15:51:08 +02006357 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006358 if (VimTryEnd())
6359 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02006360 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006361 N_("did not switch to the specified window"));
Bram Moolenaare7614592013-05-15 15:51:08 +02006362 return -1;
6363 }
6364
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006365 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02006366 }
6367 else if (strcmp(name, "tabpage") == 0)
6368 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006369 if (valObject->ob_type != TabPageTypePtr)
Bram Moolenaare7614592013-05-15 15:51:08 +02006370 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006371 PyErr_FORMAT_TYPE(
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006372 N_("expected vim.TabPage object, but got %s"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006373 valObject);
Bram Moolenaare7614592013-05-15 15:51:08 +02006374 return -1;
6375 }
6376
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006377 if (CheckTabPage((TabPageObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02006378 return -1;
6379
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006380 VimTryStart();
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006381 goto_tabpage_tp(((TabPageObject *)(valObject))->tab, TRUE, TRUE);
6382 if (((TabPageObject *)(valObject))->tab != curtab)
Bram Moolenaare7614592013-05-15 15:51:08 +02006383 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006384 if (VimTryEnd())
6385 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02006386 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006387 N_("did not switch to the specified tab page"));
Bram Moolenaare7614592013-05-15 15:51:08 +02006388 return -1;
6389 }
6390
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02006391 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02006392 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006393 else
6394 {
6395 PyErr_SetString(PyExc_AttributeError, name);
6396 return -1;
6397 }
6398}
6399
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006400static struct PyMethodDef CurrentMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006401 // name, function, calling, documentation
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006402 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
6403 { NULL, NULL, 0, NULL}
6404};
6405
Bram Moolenaardb913952012-06-29 12:54:53 +02006406 static void
Yee Cheng Chin2ce070c2023-09-19 20:30:22 +02006407init_range_cmd(void *arg)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006408{
Yee Cheng Chin2ce070c2023-09-19 20:30:22 +02006409 exarg_T *eap = (exarg_T*)arg;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006410 RangeStart = eap->line1;
6411 RangeEnd = eap->line2;
6412}
6413
6414 static void
Yee Cheng Chin2ce070c2023-09-19 20:30:22 +02006415init_range_eval(void *rettv UNUSED)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006416{
6417 RangeStart = (PyInt) curwin->w_cursor.lnum;
6418 RangeEnd = RangeStart;
6419}
6420
6421 static void
Ben Jacksonea19e782024-11-06 21:50:05 +01006422run_cmd(const char *cmd, dict_T* locals UNUSED, void *arg UNUSED
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006423#ifdef PY_CAN_RECURSE
6424 , PyGILState_STATE *pygilstate UNUSED
6425#endif
6426 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006427{
Bram Moolenaar41009372013-07-01 22:03:04 +02006428 PyObject *run_ret;
6429 run_ret = PyRun_String((char *)cmd, Py_file_input, globals, globals);
6430 if (run_ret != NULL)
6431 {
6432 Py_DECREF(run_ret);
6433 }
6434 else if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))
6435 {
Bram Moolenaard82a47d2022-01-05 20:24:39 +00006436 emsg(_(e_cant_handle_systemexit_of_python_exception_in_vim));
Bram Moolenaar41009372013-07-01 22:03:04 +02006437 PyErr_Clear();
6438 }
6439 else
6440 PyErr_PrintEx(1);
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006441}
6442
6443static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
6444static int code_hdr_len = 30;
6445
6446 static void
Ben Jacksonea19e782024-11-06 21:50:05 +01006447run_do(const char *cmd, dict_T* locals UNUSED, void *arg UNUSED
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006448#ifdef PY_CAN_RECURSE
6449 , PyGILState_STATE *pygilstate
6450#endif
6451 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006452{
6453 PyInt lnum;
6454 size_t len;
6455 char *code;
6456 int status;
6457 PyObject *pyfunc, *pymain;
Bram Moolenaar41009372013-07-01 22:03:04 +02006458 PyObject *run_ret;
Bram Moolenaara58883b2017-01-29 21:31:09 +01006459 buf_T *was_curbuf = curbuf;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006460
Bram Moolenaar4ac66762013-05-28 22:31:46 +02006461 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006462 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006463 emsg(_("cannot save undo information"));
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006464 return;
6465 }
6466
6467 len = code_hdr_len + STRLEN(cmd);
6468 code = PyMem_New(char, len + 1);
6469 memcpy(code, code_hdr, code_hdr_len);
6470 STRCPY(code + code_hdr_len, cmd);
Bram Moolenaar41009372013-07-01 22:03:04 +02006471 run_ret = PyRun_String(code, Py_file_input, globals, globals);
6472 status = -1;
6473 if (run_ret != NULL)
6474 {
6475 status = 0;
6476 Py_DECREF(run_ret);
6477 }
6478 else if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))
6479 {
6480 PyMem_Free(code);
Bram Moolenaard82a47d2022-01-05 20:24:39 +00006481 emsg(_(e_cant_handle_systemexit_of_python_exception_in_vim));
Bram Moolenaar41009372013-07-01 22:03:04 +02006482 PyErr_Clear();
6483 return;
6484 }
6485 else
6486 PyErr_PrintEx(1);
6487
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006488 PyMem_Free(code);
6489
6490 if (status)
6491 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006492 emsg(_("failed to run the code"));
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006493 return;
6494 }
6495
6496 status = 0;
6497 pymain = PyImport_AddModule("__main__");
6498 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006499#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006500 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006501#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006502
6503 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
6504 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006505 PyObject *line;
6506 PyObject *linenr;
6507 PyObject *ret;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006508
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006509#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006510 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006511#endif
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006512 // Check the line number, the command my have deleted lines.
Bram Moolenaara58883b2017-01-29 21:31:09 +01006513 if (lnum > curbuf->b_ml.ml_line_count
6514 || !(line = GetBufferLine(curbuf, lnum)))
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006515 goto err;
6516 if (!(linenr = PyInt_FromLong((long) lnum)))
6517 {
6518 Py_DECREF(line);
6519 goto err;
6520 }
6521 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
6522 Py_DECREF(line);
6523 Py_DECREF(linenr);
6524 if (!ret)
6525 goto err;
6526
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006527 // Check that the command didn't switch to another buffer.
zeertzjqe99f0682024-01-29 19:32:39 +01006528 // Check the line number, the command my have deleted lines.
6529 if (curbuf != was_curbuf || lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaara58883b2017-01-29 21:31:09 +01006530 {
6531 Py_XDECREF(ret);
6532 goto err;
6533 }
6534
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006535 if (ret != Py_None)
6536 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
Bram Moolenaara58883b2017-01-29 21:31:09 +01006537 {
6538 Py_XDECREF(ret);
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006539 goto err;
Bram Moolenaara58883b2017-01-29 21:31:09 +01006540 }
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006541
6542 Py_XDECREF(ret);
6543 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006544#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006545 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006546#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006547 }
6548 goto out;
6549err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006550#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006551 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006552#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006553 PyErr_PrintEx(0);
6554 PythonIO_Flush();
6555 status = 1;
6556out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006557#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006558 if (!status)
6559 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006560#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006561 Py_DECREF(pyfunc);
6562 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
6563 if (status)
6564 return;
6565 check_cursor();
Bram Moolenaara4d158b2022-08-14 14:17:45 +01006566 update_curbuf(UPD_NOT_VALID);
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006567}
6568
6569 static void
Ben Jacksonea19e782024-11-06 21:50:05 +01006570run_eval(const char *cmd, dict_T *locals, void *arg
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02006571#ifdef PY_CAN_RECURSE
6572 , PyGILState_STATE *pygilstate UNUSED
6573#endif
6574 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006575{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006576 PyObject *run_ret;
Yee Cheng Chind606fcc2023-09-20 19:59:47 +02006577 typval_T *rettv = (typval_T*)arg;
Ben Jacksonea19e782024-11-06 21:50:05 +01006578 PyObject *pylocals = locals ? NEW_DICTIONARY(locals) : globals;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006579
Ben Jacksonea19e782024-11-06 21:50:05 +01006580 run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, pylocals);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006581 if (run_ret == NULL)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006582 {
Bram Moolenaar91aeaf42013-07-06 13:02:30 +02006583 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))
Bram Moolenaar41009372013-07-01 22:03:04 +02006584 {
Bram Moolenaard82a47d2022-01-05 20:24:39 +00006585 emsg(_(e_cant_handle_systemexit_of_python_exception_in_vim));
Bram Moolenaar41009372013-07-01 22:03:04 +02006586 PyErr_Clear();
6587 }
Bram Moolenaar91aeaf42013-07-06 13:02:30 +02006588 else
6589 {
6590 if (PyErr_Occurred() && !msg_silent)
6591 PyErr_PrintEx(0);
Bram Moolenaar9d00e4a2022-01-05 17:49:15 +00006592 emsg(_(e_eval_did_not_return_valid_python_object));
Bram Moolenaar91aeaf42013-07-06 13:02:30 +02006593 }
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006594 }
6595 else
6596 {
Bram Moolenaarde323092017-11-09 19:56:08 +01006597 if (ConvertFromPyObject(run_ret, rettv) == -1)
Bram Moolenaar9d00e4a2022-01-05 17:49:15 +00006598 emsg(_(e_failed_to_convert_returned_python_object_to_vim_value));
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006599 Py_DECREF(run_ret);
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02006600 }
6601 PyErr_Clear();
6602}
6603
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006604 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02006605set_ref_in_py(const int copyID)
6606{
6607 pylinkedlist_T *cur;
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006608 list_T *ll;
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01006609 tuple_T *tt;
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006610 int i;
6611 int abort = FALSE;
Bram Moolenaar8110a092016-04-14 15:56:09 +02006612 FunctionObject *func;
Bram Moolenaardb913952012-06-29 12:54:53 +02006613
6614 if (lastdict != NULL)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006615 {
Bram Moolenaar8110a092016-04-14 15:56:09 +02006616 for (cur = lastdict ; !abort && cur != NULL ; cur = cur->pll_prev)
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006617 abort = set_ref_in_dict(((DictionaryObject *)(cur->pll_obj))->dict,
6618 copyID);
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006619 }
Bram Moolenaardb913952012-06-29 12:54:53 +02006620
6621 if (lastlist != NULL)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006622 {
Bram Moolenaar8110a092016-04-14 15:56:09 +02006623 for (cur = lastlist ; !abort && cur != NULL ; cur = cur->pll_prev)
Bram Moolenaardb913952012-06-29 12:54:53 +02006624 {
6625 ll = ((ListObject *) (cur->pll_obj))->list;
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006626 abort = set_ref_in_list(ll, copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02006627 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006628 }
6629
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01006630 if (lasttuple != NULL)
6631 {
6632 for (cur = lasttuple ; !abort && cur != NULL ; cur = cur->pll_prev)
6633 {
6634 tt = ((TupleObject *) (cur->pll_obj))->tuple;
6635 abort = set_ref_in_tuple(tt, copyID);
6636 }
6637 }
6638
Bram Moolenaar8110a092016-04-14 15:56:09 +02006639 if (lastfunc != NULL)
6640 {
6641 for (cur = lastfunc ; !abort && cur != NULL ; cur = cur->pll_prev)
6642 {
6643 func = (FunctionObject *) cur->pll_obj;
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02006644 abort = set_ref_in_dict(func->self, copyID);
Bram Moolenaar8110a092016-04-14 15:56:09 +02006645 if (func->argc)
6646 for (i = 0; !abort && i < func->argc; ++i)
6647 abort = abort
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01006648 || set_ref_in_item(&func->argv[i], copyID, NULL, NULL, NULL);
Bram Moolenaar8110a092016-04-14 15:56:09 +02006649 }
6650 }
6651
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01006652 return abort;
Bram Moolenaardb913952012-06-29 12:54:53 +02006653}
6654
6655 static int
6656set_string_copy(char_u *str, typval_T *tv)
6657{
6658 tv->vval.v_string = vim_strsave(str);
6659 if (tv->vval.v_string == NULL)
6660 {
6661 PyErr_NoMemory();
6662 return -1;
6663 }
6664 return 0;
6665}
6666
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006667 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006668pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006669{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006670 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006671 char_u *key;
6672 dictitem_T *di;
6673 PyObject *keyObject;
6674 PyObject *valObject;
6675 Py_ssize_t iter = 0;
6676
Bram Moolenaar35eacd72013-05-30 22:06:33 +02006677 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006678 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006679
6680 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006681 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006682
6683 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
6684 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006685 PyObject *todecref = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006686
Bram Moolenaara03e6312013-05-29 22:49:26 +02006687 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006688 {
6689 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006690 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006691 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006692
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006693 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006694 {
6695 dict_unref(dict);
6696 return -1;
6697 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02006698
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006699 if (*key == NUL)
6700 {
6701 dict_unref(dict);
6702 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02006703 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006704 return -1;
6705 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006706
6707 di = dictitem_alloc(key);
6708
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006709 Py_XDECREF(todecref);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006710
6711 if (di == NULL)
6712 {
6713 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006714 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006715 return -1;
6716 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006717
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006718 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006719 {
6720 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006721 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006722 return -1;
6723 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006724
6725 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006726 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02006727 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaara03e6312013-05-29 22:49:26 +02006728 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006729 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006730 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006731 return -1;
6732 }
6733 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006734
6735 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006736 return 0;
6737}
6738
6739 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006740pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006741{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006742 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006743 char_u *key;
6744 dictitem_T *di;
6745 PyObject *list;
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006746 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006747 PyObject *keyObject;
6748 PyObject *valObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006749
Bram Moolenaar35eacd72013-05-30 22:06:33 +02006750 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006751 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006752
6753 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006754 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006755
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006756 if (!(list = PyMapping_Keys(obj)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006757 {
6758 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006759 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006760 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006761
6762 if (!(iterator = PyObject_GetIter(list)))
6763 {
6764 dict_unref(dict);
6765 Py_DECREF(list);
6766 return -1;
6767 }
6768 Py_DECREF(list);
6769
6770 while ((keyObject = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006771 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006772 PyObject *todecref;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006773
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006774 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006775 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006776 Py_DECREF(keyObject);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006777 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006778 dict_unref(dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006779 return -1;
6780 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02006781
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006782 if (*key == NUL)
6783 {
6784 Py_DECREF(keyObject);
6785 Py_DECREF(iterator);
6786 Py_XDECREF(todecref);
6787 dict_unref(dict);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02006788 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006789 return -1;
6790 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006791
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006792 if (!(valObject = PyObject_GetItem(obj, keyObject)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006793 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006794 Py_DECREF(keyObject);
6795 Py_DECREF(iterator);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006796 Py_XDECREF(todecref);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006797 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006798 return -1;
6799 }
6800
6801 di = dictitem_alloc(key);
6802
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006803 Py_DECREF(keyObject);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006804 Py_XDECREF(todecref);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006805
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006806 if (di == NULL)
6807 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006808 Py_DECREF(iterator);
6809 Py_DECREF(valObject);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006810 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006811 PyErr_NoMemory();
6812 return -1;
6813 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006814
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006815 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006816 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006817 Py_DECREF(iterator);
6818 Py_DECREF(valObject);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006819 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006820 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006821 return -1;
6822 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02006823
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006824 Py_DECREF(valObject);
6825
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006826 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006827 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02006828 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006829 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006830 dictitem_free(di);
6831 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006832 return -1;
6833 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006834 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006835 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006836 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006837 return 0;
6838}
6839
6840 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006841pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006842{
6843 list_T *l;
6844
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006845 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006846 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006847
6848 tv->v_type = VAR_LIST;
6849 tv->vval.v_list = l;
6850
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006851 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006852 {
6853 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006854 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006855 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006856
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006857 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006858 return 0;
6859}
6860
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01006861 static int
6862pytuple_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
6863{
6864 tuple_T *t;
6865
6866 if (!(t = py_tuple_alloc()))
6867 return -1;
6868
6869 tv->v_type = VAR_TUPLE;
6870 tv->vval.v_tuple = t;
6871
6872 if (tuple_py_concat(t, obj, lookup_dict) == -1)
6873 {
6874 tuple_unref(t);
6875 return -1;
6876 }
6877
6878 --t->tv_refcount;
6879 return 0;
6880}
6881
Bram Moolenaardb913952012-06-29 12:54:53 +02006882typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
6883
6884 static int
6885convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006886 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02006887{
6888 PyObject *capsule;
6889 char hexBuf[sizeof(void *) * 2 + 3];
6890
Bram Moolenaar792f0e32018-02-27 17:27:13 +01006891 sprintf(hexBuf, "%p", (void *)obj);
Bram Moolenaardb913952012-06-29 12:54:53 +02006892
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006893#ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006894 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006895#else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006896 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006897#endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02006898 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02006899 {
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006900#ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02006901 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006902#else
Bram Moolenaar221d6872012-06-30 13:34:34 +02006903 capsule = PyCObject_FromVoidPtr(tv, NULL);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006904#endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02006905 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
6906 {
6907 Py_DECREF(capsule);
6908 tv->v_type = VAR_UNKNOWN;
6909 return -1;
6910 }
Bram Moolenaar841fbd22013-06-23 14:37:07 +02006911
6912 Py_DECREF(capsule);
6913
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006914 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02006915 {
6916 tv->v_type = VAR_UNKNOWN;
6917 return -1;
6918 }
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006919 // As we are not using copy_tv which increments reference count we must
6920 // do it ourself.
Bram Moolenaar81e7a9c2016-02-06 19:57:20 +01006921 if (tv->v_type == VAR_DICT)
6922 ++tv->vval.v_dict->dv_refcount;
6923 else if (tv->v_type == VAR_LIST)
6924 ++tv->vval.v_list->lv_refcount;
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01006925 else if (tv->v_type == VAR_TUPLE)
6926 ++tv->vval.v_tuple->tv_refcount;
Bram Moolenaardb913952012-06-29 12:54:53 +02006927 }
6928 else
6929 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02006930 typval_T *v;
6931
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006932#ifdef PY_USE_CAPSULE
Bram Moolenaar2afa3232012-06-29 16:28:28 +02006933 v = PyCapsule_GetPointer(capsule, NULL);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006934#else
Bram Moolenaar221d6872012-06-30 13:34:34 +02006935 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006936#endif
Bram Moolenaardb913952012-06-29 12:54:53 +02006937 copy_tv(v, tv);
6938 }
6939 return 0;
6940}
6941
6942 static int
Bram Moolenaara9922d62013-05-30 13:01:18 +02006943ConvertFromPyMapping(PyObject *obj, typval_T *tv)
6944{
6945 PyObject *lookup_dict;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006946 int ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006947
6948 if (!(lookup_dict = PyDict_New()))
6949 return -1;
6950
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006951 if (PyType_IsSubtype(obj->ob_type, DictionaryTypePtr))
Bram Moolenaara9922d62013-05-30 13:01:18 +02006952 {
6953 tv->v_type = VAR_DICT;
6954 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
6955 ++tv->vval.v_dict->dv_refcount;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006956 ret = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006957 }
6958 else if (PyDict_Check(obj))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006959 ret = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaara9922d62013-05-30 13:01:18 +02006960 else if (PyMapping_Check(obj))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006961 ret = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaara9922d62013-05-30 13:01:18 +02006962 else
6963 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006964 PyErr_FORMAT_TYPE(
Bram Moolenaar86181df2020-05-11 23:14:04 +02006965 N_("unable to convert %s to a Vim dictionary"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006966 obj);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006967 ret = -1;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006968 }
6969 Py_DECREF(lookup_dict);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006970 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006971}
6972
6973 static int
Bram Moolenaar8110a092016-04-14 15:56:09 +02006974ConvertFromPySequence(PyObject *obj, typval_T *tv)
6975{
6976 PyObject *lookup_dict;
Bram Moolenaar66210042016-04-15 20:40:41 +02006977 int ret;
Bram Moolenaar8110a092016-04-14 15:56:09 +02006978
6979 if (!(lookup_dict = PyDict_New()))
6980 return -1;
6981
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006982 if (PyType_IsSubtype(obj->ob_type, ListTypePtr))
Bram Moolenaar8110a092016-04-14 15:56:09 +02006983 {
6984 tv->v_type = VAR_LIST;
6985 tv->vval.v_list = (((ListObject *)(obj))->list);
6986 ++tv->vval.v_list->lv_refcount;
Bram Moolenaar66210042016-04-15 20:40:41 +02006987 ret = 0;
Bram Moolenaar8110a092016-04-14 15:56:09 +02006988 }
6989 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaar66210042016-04-15 20:40:41 +02006990 ret = convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaar8110a092016-04-14 15:56:09 +02006991 else
6992 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006993 PyErr_FORMAT_TYPE(
Bram Moolenaar86181df2020-05-11 23:14:04 +02006994 N_("unable to convert %s to a Vim list"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02006995 obj);
Bram Moolenaar8110a092016-04-14 15:56:09 +02006996 ret = -1;
6997 }
6998 Py_DECREF(lookup_dict);
6999 return ret;
7000}
7001
7002 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02007003ConvertFromPyObject(PyObject *obj, typval_T *tv)
7004{
7005 PyObject *lookup_dict;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007006 int ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02007007
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02007008 if (!(lookup_dict = PyDict_New()))
7009 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007010 ret = _ConvertFromPyObject(obj, tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02007011 Py_DECREF(lookup_dict);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007012 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02007013}
7014
7015 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02007016_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02007017{
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007018 if (PyType_IsSubtype(obj->ob_type, DictionaryTypePtr))
Bram Moolenaardb913952012-06-29 12:54:53 +02007019 {
7020 tv->v_type = VAR_DICT;
7021 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
7022 ++tv->vval.v_dict->dv_refcount;
7023 }
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007024 else if (PyType_IsSubtype(obj->ob_type, ListTypePtr))
Bram Moolenaardb913952012-06-29 12:54:53 +02007025 {
7026 tv->v_type = VAR_LIST;
7027 tv->vval.v_list = (((ListObject *)(obj))->list);
7028 ++tv->vval.v_list->lv_refcount;
7029 }
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01007030 else if (PyType_IsSubtype(obj->ob_type, TupleTypePtr))
7031 {
7032 tv->v_type = VAR_TUPLE;
7033 tv->vval.v_tuple = (((TupleObject *)(obj))->tuple);
7034 ++tv->vval.v_tuple->tv_refcount;
7035 }
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007036 else if (PyType_IsSubtype(obj->ob_type, FunctionTypePtr))
Bram Moolenaardb913952012-06-29 12:54:53 +02007037 {
Bram Moolenaar8110a092016-04-14 15:56:09 +02007038 FunctionObject *func = (FunctionObject *) obj;
7039 if (func->self != NULL || func->argv != NULL)
7040 {
Bram Moolenaarc799fe22019-05-28 23:08:19 +02007041 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
7042
Bram Moolenaar8110a092016-04-14 15:56:09 +02007043 set_partial(func, pt, TRUE);
7044 tv->vval.v_partial = pt;
7045 tv->v_type = VAR_PARTIAL;
7046 }
7047 else
7048 {
7049 if (set_string_copy(func->name, tv) == -1)
7050 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02007051
Bram Moolenaar8110a092016-04-14 15:56:09 +02007052 tv->v_type = VAR_FUNC;
7053 }
7054 func_ref(func->name);
Bram Moolenaardb913952012-06-29 12:54:53 +02007055 }
Bram Moolenaardb913952012-06-29 12:54:53 +02007056 else if (PyBytes_Check(obj))
7057 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007058 char_u *str;
Bram Moolenaardb913952012-06-29 12:54:53 +02007059
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007060 if (PyBytes_AsStringAndSize(obj, (char **) &str, NULL) == -1)
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02007061 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007062 if (str == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02007063 return -1;
7064
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007065 if (set_string_copy(str, tv) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02007066 return -1;
7067
7068 tv->v_type = VAR_STRING;
7069 }
7070 else if (PyUnicode_Check(obj))
7071 {
7072 PyObject *bytes;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007073 char_u *str;
Bram Moolenaardb913952012-06-29 12:54:53 +02007074
Bram Moolenaar2e2f52a2020-12-21 16:03:02 +01007075 bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, ERRORS_ENCODE_ARG);
Bram Moolenaardb913952012-06-29 12:54:53 +02007076 if (bytes == NULL)
7077 return -1;
7078
Bram Moolenaar2e2f52a2020-12-21 16:03:02 +01007079 if (PyBytes_AsStringAndSize(bytes, (char **) &str, NULL) == -1)
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02007080 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007081 if (str == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02007082 return -1;
7083
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007084 if (set_string_copy(str, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02007085 {
7086 Py_XDECREF(bytes);
7087 return -1;
7088 }
7089 Py_XDECREF(bytes);
7090
7091 tv->v_type = VAR_STRING;
7092 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02007093#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02007094 else if (PyInt_Check(obj))
7095 {
7096 tv->v_type = VAR_NUMBER;
7097 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02007098 if (PyErr_Occurred())
7099 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02007100 }
7101#endif
7102 else if (PyLong_Check(obj))
7103 {
7104 tv->v_type = VAR_NUMBER;
7105 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02007106 if (PyErr_Occurred())
7107 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02007108 }
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01007109 else if (PyTuple_Check(obj))
7110 return convert_dl(obj, tv, pytuple_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02007111 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02007112 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02007113 else if (PyFloat_Check(obj))
7114 {
7115 tv->v_type = VAR_FLOAT;
7116 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
7117 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02007118 else if (PyObject_HasAttrString(obj, "keys"))
7119 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01007120 // PyObject_GetIter can create built-in iterator for any sequence object
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02007121 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02007122 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02007123 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02007124 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02007125 else if (PyNumber_Check(obj))
7126 {
7127 PyObject *num;
7128
7129 if (!(num = PyNumber_Long(obj)))
7130 return -1;
7131
7132 tv->v_type = VAR_NUMBER;
7133 tv->vval.v_number = (varnumber_T) PyLong_AsLong(num);
7134
7135 Py_DECREF(num);
7136 }
Bram Moolenaarde323092017-11-09 19:56:08 +01007137 else if (obj == Py_None)
7138 {
7139 tv->v_type = VAR_SPECIAL;
7140 tv->vval.v_number = VVAL_NONE;
7141 }
Bram Moolenaardb913952012-06-29 12:54:53 +02007142 else
7143 {
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007144 PyErr_FORMAT_TYPE(
Bram Moolenaar86181df2020-05-11 23:14:04 +02007145 N_("unable to convert %s to a Vim structure"),
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007146 obj);
Bram Moolenaardb913952012-06-29 12:54:53 +02007147 return -1;
7148 }
7149 return 0;
7150}
7151
7152 static PyObject *
7153ConvertToPyObject(typval_T *tv)
7154{
Bram Moolenaar8110a092016-04-14 15:56:09 +02007155 typval_T *argv;
7156 int i;
Bram Moolenaardb913952012-06-29 12:54:53 +02007157 if (tv == NULL)
7158 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02007159 PyErr_SET_VIM(N_("internal error: NULL reference passed"));
Bram Moolenaardb913952012-06-29 12:54:53 +02007160 return NULL;
7161 }
7162 switch (tv->v_type)
7163 {
7164 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02007165 return PyBytes_FromString(tv->vval.v_string == NULL
7166 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02007167 case VAR_NUMBER:
7168 return PyLong_FromLong((long) tv->vval.v_number);
Bram Moolenaardb913952012-06-29 12:54:53 +02007169 case VAR_FLOAT:
7170 return PyFloat_FromDouble((double) tv->vval.v_float);
Bram Moolenaardb913952012-06-29 12:54:53 +02007171 case VAR_LIST:
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02007172 return NEW_LIST(tv->vval.v_list);
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01007173 case VAR_TUPLE:
7174 return NEW_TUPLE(tv->vval.v_tuple);
Bram Moolenaardb913952012-06-29 12:54:53 +02007175 case VAR_DICT:
Bram Moolenaara9922d62013-05-30 13:01:18 +02007176 return NEW_DICTIONARY(tv->vval.v_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02007177 case VAR_FUNC:
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02007178 return NEW_FUNCTION(tv->vval.v_string == NULL
Bram Moolenaar8110a092016-04-14 15:56:09 +02007179 ? (char_u *)"" : tv->vval.v_string,
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02007180 0, NULL, NULL, TRUE);
Bram Moolenaar4c908612016-03-24 21:58:12 +01007181 case VAR_PARTIAL:
Bram Moolenaar8110a092016-04-14 15:56:09 +02007182 if (tv->vval.v_partial->pt_argc)
7183 {
7184 argv = PyMem_New(typval_T, (size_t)tv->vval.v_partial->pt_argc);
7185 for (i = 0; i < tv->vval.v_partial->pt_argc; i++)
7186 copy_tv(&tv->vval.v_partial->pt_argv[i], &argv[i]);
7187 }
7188 else
7189 argv = NULL;
7190 if (tv->vval.v_partial->pt_dict != NULL)
7191 tv->vval.v_partial->pt_dict->dv_refcount++;
Bram Moolenaar4c908612016-03-24 21:58:12 +01007192 return NEW_FUNCTION(tv->vval.v_partial == NULL
Bram Moolenaar437bafe2016-08-01 15:40:54 +02007193 ? (char_u *)"" : partial_name(tv->vval.v_partial),
Bram Moolenaar8110a092016-04-14 15:56:09 +02007194 tv->vval.v_partial->pt_argc, argv,
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02007195 tv->vval.v_partial->pt_dict,
7196 tv->vval.v_partial->pt_auto);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01007197 case VAR_BLOB:
7198 return PyBytes_FromStringAndSize(
7199 (char*) tv->vval.v_blob->bv_ga.ga_data,
7200 (Py_ssize_t) tv->vval.v_blob->bv_ga.ga_len);
Bram Moolenaardb913952012-06-29 12:54:53 +02007201 case VAR_UNKNOWN:
Bram Moolenaar4c683752020-04-05 21:38:23 +02007202 case VAR_ANY:
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01007203 case VAR_VOID:
Bram Moolenaar4c908612016-03-24 21:58:12 +01007204 case VAR_CHANNEL:
7205 case VAR_JOB:
Bram Moolenaarf18332f2021-05-07 17:55:55 +02007206 case VAR_INSTR:
Bram Moolenaar00b28d62022-12-08 15:32:33 +00007207 case VAR_CLASS:
7208 case VAR_OBJECT:
Yegappan Lakshmananec3cebb2023-10-27 19:35:26 +02007209 case VAR_TYPEALIAS:
Bram Moolenaardb913952012-06-29 12:54:53 +02007210 Py_INCREF(Py_None);
7211 return Py_None;
Bram Moolenaar9b4a15d2020-01-11 16:05:23 +01007212 case VAR_BOOL:
Bram Moolenaar4c908612016-03-24 21:58:12 +01007213 case VAR_SPECIAL:
7214 switch (tv->vval.v_number)
7215 {
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02007216 case VVAL_FALSE: return ALWAYS_FALSE;
7217 case VVAL_TRUE: return ALWAYS_TRUE;
Bram Moolenaar4c908612016-03-24 21:58:12 +01007218 case VVAL_NONE:
Bram Moolenaar4ce5fe42020-10-21 21:01:59 +02007219 case VVAL_NULL: return ALWAYS_NONE;
Bram Moolenaar4c908612016-03-24 21:58:12 +01007220 }
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02007221 PyErr_SET_VIM(N_("internal error: invalid value type"));
Bram Moolenaardb913952012-06-29 12:54:53 +02007222 return NULL;
7223 }
Bram Moolenaar4c908612016-03-24 21:58:12 +01007224 return NULL;
Bram Moolenaardb913952012-06-29 12:54:53 +02007225}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007226
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007227DEFINE_PY_TYPE_OBJECT(CurrentType);
7228
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007229typedef struct
7230{
7231 PyObject_HEAD
7232} CurrentObject;
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007233
7234static CurrentObject TheCurrent =
7235{
7236 PyObject_HEAD_INIT_TYPE(CurrentType)
7237};
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007238
7239 static void
7240init_structs(void)
7241{
Bram Moolenaara80faa82020-04-12 19:37:17 +02007242 CLEAR_FIELD(OutputType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007243 OutputType.tp_name = "vim.message";
7244 OutputType.tp_basicsize = sizeof(OutputObject);
7245 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
7246 OutputType.tp_doc = "vim message object";
7247 OutputType.tp_methods = OutputMethods;
7248#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007249 OutputType.tp_getattro = OutputGetattro;
7250 OutputType.tp_setattro = OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007251 OutputType.tp_alloc = call_PyType_GenericAlloc;
7252 OutputType.tp_new = call_PyType_GenericNew;
7253 OutputType.tp_free = call_PyObject_Free;
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007254# ifndef USE_LIMITED_API
7255 // The std printer type is only exposed in full API. It is not essential
7256 // anyway and so in limited API we don't set it.
Bram Moolenaard4a8c982018-05-15 22:31:18 +02007257 OutputType.tp_base = &PyStdPrinter_Type;
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007258# endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007259#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007260 OutputType.tp_getattr = OutputGetattr;
7261 OutputType.tp_setattr = OutputSetattr;
Bram Moolenaard4a8c982018-05-15 22:31:18 +02007262 // Disabled, because this causes a crash in test86
7263 // OutputType.tp_base = &PyFile_Type;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007264#endif
7265
Bram Moolenaara80faa82020-04-12 19:37:17 +02007266 CLEAR_FIELD(IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02007267 IterType.tp_name = "vim.iter";
7268 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02007269 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02007270 IterType.tp_doc = "generic iterator object";
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007271 IterType.tp_iter = IterIter;
7272 IterType.tp_iternext = IterNext;
7273 IterType.tp_dealloc = IterDestructor;
7274 IterType.tp_traverse = IterTraverse;
7275 IterType.tp_clear = IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02007276
Bram Moolenaara80faa82020-04-12 19:37:17 +02007277 CLEAR_FIELD(BufferType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007278 BufferType.tp_name = "vim.buffer";
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007279 BufferType.tp_basicsize = sizeof(BufferObject);
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007280 BufferType.tp_dealloc = BufferDestructor;
7281 BufferType.tp_repr = BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007282 BufferType.tp_as_sequence = &BufferAsSeq;
7283 BufferType.tp_as_mapping = &BufferAsMapping;
7284 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
7285 BufferType.tp_doc = "vim buffer object";
7286 BufferType.tp_methods = BufferMethods;
7287#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007288 BufferType.tp_getattro = BufferGetattro;
7289 BufferType.tp_setattro = BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007290 BufferType.tp_alloc = call_PyType_GenericAlloc;
7291 BufferType.tp_new = call_PyType_GenericNew;
7292 BufferType.tp_free = call_PyObject_Free;
7293#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007294 BufferType.tp_getattr = BufferGetattr;
7295 BufferType.tp_setattr = BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007296#endif
7297
Bram Moolenaara80faa82020-04-12 19:37:17 +02007298 CLEAR_FIELD(WindowType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007299 WindowType.tp_name = "vim.window";
7300 WindowType.tp_basicsize = sizeof(WindowObject);
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007301 WindowType.tp_dealloc = WindowDestructor;
7302 WindowType.tp_repr = WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02007303 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007304 WindowType.tp_doc = "vim Window object";
7305 WindowType.tp_methods = WindowMethods;
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007306 WindowType.tp_traverse = WindowTraverse;
7307 WindowType.tp_clear = WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007308#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007309 WindowType.tp_getattro = WindowGetattro;
7310 WindowType.tp_setattro = WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007311 WindowType.tp_alloc = call_PyType_GenericAlloc;
7312 WindowType.tp_new = call_PyType_GenericNew;
7313 WindowType.tp_free = call_PyObject_Free;
7314#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007315 WindowType.tp_getattr = WindowGetattr;
7316 WindowType.tp_setattr = WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007317#endif
7318
Bram Moolenaara80faa82020-04-12 19:37:17 +02007319 CLEAR_FIELD(TabPageType);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02007320 TabPageType.tp_name = "vim.tabpage";
7321 TabPageType.tp_basicsize = sizeof(TabPageObject);
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007322 TabPageType.tp_dealloc = TabPageDestructor;
7323 TabPageType.tp_repr = TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02007324 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
7325 TabPageType.tp_doc = "vim tab page object";
7326 TabPageType.tp_methods = TabPageMethods;
7327#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007328 TabPageType.tp_getattro = TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02007329 TabPageType.tp_alloc = call_PyType_GenericAlloc;
7330 TabPageType.tp_new = call_PyType_GenericNew;
7331 TabPageType.tp_free = call_PyObject_Free;
7332#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007333 TabPageType.tp_getattr = TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02007334#endif
7335
Bram Moolenaara80faa82020-04-12 19:37:17 +02007336 CLEAR_FIELD(BufMapType);
Bram Moolenaardfa38d42013-05-15 13:38:47 +02007337 BufMapType.tp_name = "vim.bufferlist";
7338 BufMapType.tp_basicsize = sizeof(BufMapObject);
7339 BufMapType.tp_as_mapping = &BufMapAsMapping;
7340 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02007341 BufMapType.tp_iter = BufMapIter;
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007342 BufMapType.tp_doc = "vim buffer list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007343
Bram Moolenaara80faa82020-04-12 19:37:17 +02007344 CLEAR_FIELD(WinListType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007345 WinListType.tp_name = "vim.windowlist";
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007346 WinListType.tp_basicsize = sizeof(WinListObject);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007347 WinListType.tp_as_sequence = &WinListAsSeq;
7348 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
7349 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02007350 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02007351
Bram Moolenaara80faa82020-04-12 19:37:17 +02007352 CLEAR_FIELD(TabListType);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02007353 TabListType.tp_name = "vim.tabpagelist";
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007354 TabListType.tp_basicsize = sizeof(TabListObject);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02007355 TabListType.tp_as_sequence = &TabListAsSeq;
7356 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
7357 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007358
Bram Moolenaara80faa82020-04-12 19:37:17 +02007359 CLEAR_FIELD(RangeType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007360 RangeType.tp_name = "vim.range";
7361 RangeType.tp_basicsize = sizeof(RangeObject);
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007362 RangeType.tp_dealloc = RangeDestructor;
7363 RangeType.tp_repr = RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007364 RangeType.tp_as_sequence = &RangeAsSeq;
7365 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02007366 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007367 RangeType.tp_doc = "vim Range object";
7368 RangeType.tp_methods = RangeMethods;
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007369 RangeType.tp_traverse = RangeTraverse;
7370 RangeType.tp_clear = RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007371#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007372 RangeType.tp_getattro = RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007373 RangeType.tp_alloc = call_PyType_GenericAlloc;
7374 RangeType.tp_new = call_PyType_GenericNew;
7375 RangeType.tp_free = call_PyObject_Free;
7376#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007377 RangeType.tp_getattr = RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007378#endif
7379
Bram Moolenaara80faa82020-04-12 19:37:17 +02007380 CLEAR_FIELD(CurrentType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007381 CurrentType.tp_name = "vim.currentdata";
7382 CurrentType.tp_basicsize = sizeof(CurrentObject);
7383 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
7384 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02007385 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007386#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007387 CurrentType.tp_getattro = CurrentGetattro;
7388 CurrentType.tp_setattro = CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007389#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007390 CurrentType.tp_getattr = CurrentGetattr;
7391 CurrentType.tp_setattr = CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007392#endif
7393
Bram Moolenaara80faa82020-04-12 19:37:17 +02007394 CLEAR_FIELD(DictionaryType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007395 DictionaryType.tp_name = "vim.dictionary";
7396 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007397 DictionaryType.tp_dealloc = DictionaryDestructor;
Bram Moolenaara9922d62013-05-30 13:01:18 +02007398 DictionaryType.tp_as_sequence = &DictionaryAsSeq;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007399 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
Bram Moolenaara9922d62013-05-30 13:01:18 +02007400 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar86181df2020-05-11 23:14:04 +02007401 DictionaryType.tp_doc = "dictionary pushing modifications to Vim structure";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007402 DictionaryType.tp_methods = DictionaryMethods;
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007403 DictionaryType.tp_iter = DictionaryIter;
7404 DictionaryType.tp_new = DictionaryConstructor;
7405 DictionaryType.tp_alloc = PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007406#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007407 DictionaryType.tp_getattro = DictionaryGetattro;
7408 DictionaryType.tp_setattro = DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007409#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007410 DictionaryType.tp_getattr = DictionaryGetattr;
7411 DictionaryType.tp_setattr = DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007412#endif
7413
Bram Moolenaara80faa82020-04-12 19:37:17 +02007414 CLEAR_FIELD(ListType);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007415 ListType.tp_name = "vim.list";
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007416 ListType.tp_dealloc = ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007417 ListType.tp_basicsize = sizeof(ListObject);
7418 ListType.tp_as_sequence = &ListAsSeq;
7419 ListType.tp_as_mapping = &ListAsMapping;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02007420 ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar86181df2020-05-11 23:14:04 +02007421 ListType.tp_doc = "list pushing modifications to Vim structure";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007422 ListType.tp_methods = ListMethods;
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007423 ListType.tp_iter = ListIter;
7424 ListType.tp_new = ListConstructor;
7425 ListType.tp_alloc = PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007426#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007427 ListType.tp_getattro = ListGetattro;
7428 ListType.tp_setattro = ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007429#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007430 ListType.tp_getattr = ListGetattr;
7431 ListType.tp_setattr = ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007432#endif
7433
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01007434 // Tuple type
7435 CLEAR_FIELD(TupleType);
7436 TupleType.tp_name = "vim.tuple";
7437 TupleType.tp_dealloc = TupleDestructor;
7438 TupleType.tp_basicsize = sizeof(TupleObject);
7439 TupleType.tp_as_sequence = &TupleAsSeq;
7440 TupleType.tp_as_mapping = &TupleAsMapping;
7441 TupleType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
7442 TupleType.tp_doc = "tuple pushing modifications to Vim structure";
7443 TupleType.tp_methods = TupleMethods;
7444 TupleType.tp_iter = TupleIter;
7445 TupleType.tp_new = TupleConstructor;
7446 TupleType.tp_alloc = PyType_GenericAlloc;
7447#if PY_MAJOR_VERSION >= 3
7448 TupleType.tp_getattro = TupleGetattro;
7449 TupleType.tp_setattro = TupleSetattro;
7450#else
7451 TupleType.tp_getattr = TupleGetattr;
7452 TupleType.tp_setattr = TupleSetattr;
7453#endif
7454
Bram Moolenaara80faa82020-04-12 19:37:17 +02007455 CLEAR_FIELD(FunctionType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02007456 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007457 FunctionType.tp_basicsize = sizeof(FunctionObject);
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007458 FunctionType.tp_dealloc = FunctionDestructor;
7459 FunctionType.tp_call = FunctionCall;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02007460 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar86181df2020-05-11 23:14:04 +02007461 FunctionType.tp_doc = "object that calls Vim function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007462 FunctionType.tp_methods = FunctionMethods;
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007463 FunctionType.tp_repr = FunctionRepr;
7464 FunctionType.tp_new = FunctionConstructor;
7465 FunctionType.tp_alloc = PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007466#if PY_MAJOR_VERSION >= 3
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007467 FunctionType.tp_getattro = FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007468#else
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007469 FunctionType.tp_getattr = FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007470#endif
7471
Bram Moolenaara80faa82020-04-12 19:37:17 +02007472 CLEAR_FIELD(OptionsType);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007473 OptionsType.tp_name = "vim.options";
7474 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01007475 OptionsType.tp_as_sequence = &OptionsAsSeq;
Bram Moolenaar07b88642013-05-29 22:58:32 +02007476 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007477 OptionsType.tp_doc = "object for manipulating options";
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007478 OptionsType.tp_iter = OptionsIter;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007479 OptionsType.tp_as_mapping = &OptionsAsMapping;
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007480 OptionsType.tp_dealloc = OptionsDestructor;
7481 OptionsType.tp_traverse = OptionsTraverse;
7482 OptionsType.tp_clear = OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02007483
Bram Moolenaar79a494d2018-07-22 04:30:21 +02007484#if PY_VERSION_HEX < 0x030700f0
Bram Moolenaara80faa82020-04-12 19:37:17 +02007485 CLEAR_FIELD(LoaderType);
Bram Moolenaar81c40c52013-06-12 14:41:04 +02007486 LoaderType.tp_name = "vim.Loader";
7487 LoaderType.tp_basicsize = sizeof(LoaderObject);
7488 LoaderType.tp_flags = Py_TPFLAGS_DEFAULT;
7489 LoaderType.tp_doc = "vim message object";
7490 LoaderType.tp_methods = LoaderMethods;
Yee Cheng Chin02c51b12023-09-21 16:40:12 +02007491 LoaderType.tp_dealloc = LoaderDestructor;
Bram Moolenaar79a494d2018-07-22 04:30:21 +02007492#endif
Bram Moolenaar81c40c52013-06-12 14:41:04 +02007493
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007494#if PY_MAJOR_VERSION >= 3
Bram Moolenaara80faa82020-04-12 19:37:17 +02007495 CLEAR_FIELD(vimmodule);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02007496 vimmodule.m_name = "vim";
7497 vimmodule.m_doc = "Vim Python interface\n";
7498 vimmodule.m_size = -1;
7499 vimmodule.m_methods = VimMethods;
7500#endif
7501}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007502
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007503 static int
Bram Moolenaarfb97f282013-07-09 17:42:46 +02007504init_types(void)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007505{
7506 PYTYPE_READY(IterType);
7507 PYTYPE_READY(BufferType);
7508 PYTYPE_READY(RangeType);
7509 PYTYPE_READY(WindowType);
7510 PYTYPE_READY(TabPageType);
7511 PYTYPE_READY(BufMapType);
7512 PYTYPE_READY(WinListType);
7513 PYTYPE_READY(TabListType);
7514 PYTYPE_READY(CurrentType);
7515 PYTYPE_READY(DictionaryType);
7516 PYTYPE_READY(ListType);
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01007517 PYTYPE_READY(TupleType);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007518 PYTYPE_READY(FunctionType);
7519 PYTYPE_READY(OptionsType);
7520 PYTYPE_READY(OutputType);
Bram Moolenaar79a494d2018-07-22 04:30:21 +02007521#if PY_VERSION_HEX < 0x030700f0
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02007522 PYTYPE_READY(LoaderType);
Bram Moolenaar79a494d2018-07-22 04:30:21 +02007523#endif
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007524
7525#ifdef USE_LIMITED_API
7526 // We need to finish initializing all the static objects because the types
7527 // are only just allocated on the heap now.
7528 // Each PyObject_HEAD_INIT_TYPE should correspond to a
7529 // PyObject_FINISH_INIT_TYPE below.
7530 PyObject_FINISH_INIT_TYPE(Output, OutputType);
7531 PyObject_FINISH_INIT_TYPE(Error, OutputType);
7532 PyObject_FINISH_INIT_TYPE(TheBufferMap, BufMapType);
7533 PyObject_FINISH_INIT_TYPE(TheWindowList, WinListType);
7534 PyObject_FINISH_INIT_TYPE(TheCurrent, CurrentType);
7535 PyObject_FINISH_INIT_TYPE(TheTabPageList, TabListType);
7536#endif
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007537 return 0;
7538}
7539
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007540#ifdef USE_LIMITED_API
7541 static void
7542shutdown_types(void)
7543{
7544 PYTYPE_CLEANUP(IterType);
7545 PYTYPE_CLEANUP(BufferType);
7546 PYTYPE_CLEANUP(RangeType);
7547 PYTYPE_CLEANUP(WindowType);
7548 PYTYPE_CLEANUP(TabPageType);
7549 PYTYPE_CLEANUP(BufMapType);
7550 PYTYPE_CLEANUP(WinListType);
7551 PYTYPE_CLEANUP(TabListType);
7552 PYTYPE_CLEANUP(CurrentType);
7553 PYTYPE_CLEANUP(DictionaryType);
7554 PYTYPE_CLEANUP(ListType);
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01007555 PYTYPE_CLEANUP(TupleType);
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007556 PYTYPE_CLEANUP(FunctionType);
7557 PYTYPE_CLEANUP(OptionsType);
7558 PYTYPE_CLEANUP(OutputType);
7559# if PY_VERSION_HEX < 0x030700f0
7560 PYTYPE_CLEANUP(LoaderType);
7561# endif
7562}
7563#endif
7564
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007565 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02007566init_sys_path(void)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007567{
7568 PyObject *path;
7569 PyObject *path_hook;
7570 PyObject *path_hooks;
7571
7572 if (!(path_hook = PyObject_GetAttrString(vim_module, "path_hook")))
7573 return -1;
7574
7575 if (!(path_hooks = PySys_GetObject("path_hooks")))
7576 {
7577 PyErr_Clear();
7578 path_hooks = PyList_New(1);
7579 PyList_SET_ITEM(path_hooks, 0, path_hook);
7580 if (PySys_SetObject("path_hooks", path_hooks))
7581 {
7582 Py_DECREF(path_hooks);
7583 return -1;
7584 }
7585 Py_DECREF(path_hooks);
7586 }
7587 else if (PyList_Check(path_hooks))
7588 {
7589 if (PyList_Append(path_hooks, path_hook))
7590 {
7591 Py_DECREF(path_hook);
7592 return -1;
7593 }
7594 Py_DECREF(path_hook);
7595 }
7596 else
7597 {
7598 VimTryStart();
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007599 emsg(_("Failed to set path hook: sys.path_hooks is not a list\n"
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007600 "You should now do the following:\n"
7601 "- append vim.path_hook to sys.path_hooks\n"
7602 "- append vim.VIM_SPECIAL_PATH to sys.path\n"));
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01007603 VimTryEnd(); // Discard the error
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007604 Py_DECREF(path_hook);
7605 return 0;
7606 }
7607
7608 if (!(path = PySys_GetObject("path")))
7609 {
7610 PyErr_Clear();
7611 path = PyList_New(1);
7612 Py_INCREF(vim_special_path_object);
7613 PyList_SET_ITEM(path, 0, vim_special_path_object);
7614 if (PySys_SetObject("path", path))
7615 {
7616 Py_DECREF(path);
7617 return -1;
7618 }
7619 Py_DECREF(path);
7620 }
7621 else if (PyList_Check(path))
7622 {
7623 if (PyList_Append(path, vim_special_path_object))
7624 return -1;
7625 }
7626 else
7627 {
7628 VimTryStart();
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01007629 emsg(_("Failed to set path: sys.path is not a list\n"
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007630 "You should now append vim.VIM_SPECIAL_PATH to sys.path"));
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01007631 VimTryEnd(); // Discard the error
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007632 }
7633
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007634 return 0;
7635}
7636
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007637static struct numeric_constant {
7638 char *name;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007639 int val;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007640} numeric_constants[] = {
7641 {"VAR_LOCKED", VAR_LOCKED},
7642 {"VAR_FIXED", VAR_FIXED},
7643 {"VAR_SCOPE", VAR_SCOPE},
7644 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
7645};
7646
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007647struct object_constant {
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007648 char *name;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007649 PyObject *valObject;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007650};
7651
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007652#define ADD_OBJECT(m, name, obj) \
Bram Moolenaardee2e312013-06-23 16:35:47 +02007653 if (PyModule_AddObject(m, name, obj)) \
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007654 return -1;
7655
7656#define ADD_CHECKED_OBJECT(m, name, obj) \
7657 { \
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007658 PyObject *valObject = obj; \
7659 if (!valObject) \
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007660 return -1; \
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007661 ADD_OBJECT(m, name, valObject); \
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007662 }
7663
7664 static int
Bram Moolenaardee2e312013-06-23 16:35:47 +02007665populate_module(PyObject *m)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007666{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02007667 int i;
7668 PyObject *other_module;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02007669 PyObject *attr;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02007670 PyObject *imp;
Bram Moolenaar79a494d2018-07-22 04:30:21 +02007671#if PY_VERSION_HEX >= 0x030700f0
7672 PyObject *dict;
7673 PyObject *cls;
7674#endif
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007675
7676 for (i = 0; i < (int)(sizeof(numeric_constants)
7677 / sizeof(struct numeric_constant));
7678 ++i)
7679 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007680 PyInt_FromLong(numeric_constants[i].val));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007681
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007682 struct object_constant object_constants[] = {
7683 {"buffers", (PyObject *)(void *)&TheBufferMap},
7684 {"windows", (PyObject *)(void *)&TheWindowList},
7685 {"tabpages", (PyObject *)(void *)&TheTabPageList},
7686 {"current", (PyObject *)(void *)&TheCurrent},
7687
7688 {"Buffer", (PyObject *)BufferTypePtr},
7689 {"Range", (PyObject *)RangeTypePtr},
7690 {"Window", (PyObject *)WindowTypePtr},
7691 {"TabPage", (PyObject *)TabPageTypePtr},
7692 {"Dictionary", (PyObject *)DictionaryTypePtr},
7693 {"List", (PyObject *)ListTypePtr},
Yegappan Lakshmanan038be272025-03-26 18:46:21 +01007694 {"Tuple", (PyObject *)TupleTypePtr},
Yee Cheng Chinc13b3d12023-08-20 21:18:38 +02007695 {"Function", (PyObject *)FunctionTypePtr},
7696 {"Options", (PyObject *)OptionsTypePtr},
7697#if PY_VERSION_HEX < 0x030700f0
7698 {"_Loader", (PyObject *)LoaderTypePtr},
7699#endif
7700 };
7701
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007702 for (i = 0; i < (int)(sizeof(object_constants)
7703 / sizeof(struct object_constant));
7704 ++i)
7705 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007706 PyObject *valObject;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007707
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02007708 valObject = object_constants[i].valObject;
7709 Py_INCREF(valObject);
7710 ADD_OBJECT(m, object_constants[i].name, valObject);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007711 }
7712
7713 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
7714 return -1;
7715 ADD_OBJECT(m, "error", VimError);
7716
Bram Moolenaarda6c0332019-09-01 16:01:30 +02007717 ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(get_globvar_dict()));
7718 ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(get_vimvar_dict()));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007719 ADD_CHECKED_OBJECT(m, "options",
7720 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
Bram Moolenaarf4258302013-06-02 18:20:17 +02007721
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02007722 if (!(other_module = PyImport_ImportModule("os")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02007723 return -1;
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02007724 ADD_OBJECT(m, "os", other_module);
Bram Moolenaarf4258302013-06-02 18:20:17 +02007725
Bram Moolenaar22081f42016-06-01 20:38:34 +02007726#if PY_MAJOR_VERSION >= 3
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02007727 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwd")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02007728 return -1;
Bram Moolenaar22081f42016-06-01 20:38:34 +02007729#else
7730 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwdu")))
7731 return -1;
7732#endif
Bram Moolenaarf4258302013-06-02 18:20:17 +02007733 ADD_OBJECT(m, "_getcwd", py_getcwd)
7734
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02007735 if (!(py_chdir = PyObject_GetAttrString(other_module, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02007736 return -1;
7737 ADD_OBJECT(m, "_chdir", py_chdir);
Bram Moolenaardee2e312013-06-23 16:35:47 +02007738 if (!(attr = PyObject_GetAttrString(m, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02007739 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02007740 if (PyObject_SetAttrString(other_module, "chdir", attr))
7741 {
7742 Py_DECREF(attr);
7743 return -1;
7744 }
7745 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02007746
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02007747 if ((py_fchdir = PyObject_GetAttrString(other_module, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02007748 {
7749 ADD_OBJECT(m, "_fchdir", py_fchdir);
Bram Moolenaardee2e312013-06-23 16:35:47 +02007750 if (!(attr = PyObject_GetAttrString(m, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02007751 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02007752 if (PyObject_SetAttrString(other_module, "fchdir", attr))
7753 {
7754 Py_DECREF(attr);
7755 return -1;
7756 }
7757 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02007758 }
Bram Moolenaare9056b12013-06-03 20:04:48 +02007759 else
7760 PyErr_Clear();
Bram Moolenaarf4258302013-06-02 18:20:17 +02007761
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007762 if (!(vim_special_path_object = PyString_FromString(vim_special_path)))
7763 return -1;
7764
7765 ADD_OBJECT(m, "VIM_SPECIAL_PATH", vim_special_path_object);
7766
Bram Moolenaar79a494d2018-07-22 04:30:21 +02007767#if PY_VERSION_HEX >= 0x030700f0
7768 if (!(imp = PyImport_ImportModule("importlib.machinery")))
7769 return -1;
7770
7771 dict = PyModule_GetDict(imp);
7772
7773 if (!(cls = PyDict_GetItemString(dict, "PathFinder")))
7774 {
7775 Py_DECREF(imp);
7776 return -1;
7777 }
7778
7779 if (!(py_find_spec = PyObject_GetAttrString(cls, "find_spec")))
7780 {
7781 Py_DECREF(imp);
7782 return -1;
7783 }
7784
Christian Brabandtf0905a82024-05-17 18:30:01 +02007785# if PY_VERSION_HEX < 0x30c00a7
7786 // find_module has been removed as of Python 3.12.0a7
Bram Moolenaarb999ba22019-02-14 13:28:45 +01007787 if ((py_find_module = PyObject_GetAttrString(cls, "find_module")))
Bram Moolenaar9f1983d2022-05-12 20:35:35 +01007788 ADD_OBJECT(m, "_find_module", py_find_module);
Christian Brabandtf0905a82024-05-17 18:30:01 +02007789# endif
Bram Moolenaarb999ba22019-02-14 13:28:45 +01007790
Bram Moolenaar79a494d2018-07-22 04:30:21 +02007791 Py_DECREF(imp);
7792
7793 ADD_OBJECT(m, "_find_spec", py_find_spec);
7794#else
Bram Moolenaar81c40c52013-06-12 14:41:04 +02007795 if (!(imp = PyImport_ImportModule("imp")))
7796 return -1;
7797
7798 if (!(py_find_module = PyObject_GetAttrString(imp, "find_module")))
7799 {
7800 Py_DECREF(imp);
7801 return -1;
7802 }
7803
7804 if (!(py_load_module = PyObject_GetAttrString(imp, "load_module")))
7805 {
7806 Py_DECREF(py_find_module);
7807 Py_DECREF(imp);
7808 return -1;
7809 }
7810
7811 Py_DECREF(imp);
7812
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02007813 ADD_OBJECT(m, "_find_module", py_find_module);
7814 ADD_OBJECT(m, "_load_module", py_load_module);
Bram Moolenaar79a494d2018-07-22 04:30:21 +02007815#endif
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02007816
Bram Moolenaar1dc28782013-05-21 19:11:01 +02007817 return 0;
7818}