1 /* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Lua interface by Luis Carvalho
6 *
7 * Do ":help uganda" in Vim to read copying and usage conditions.
8 * Do ":help credits" in Vim to see a list of people who contributed.
9 * See README.txt for an overview of the Vim source code.
10 */
11
12 #include "vim.h"
13 #include "version.h"
14
15 #include <lua.h>
16 #include <lualib.h>
17 #include <lauxlib.h>
18
19 // Only do the following when the feature is enabled. Needed for "make
20 // depend".
21 #if defined(FEAT_LUA) || defined(PROTO)
22
23 #define LUAVIM_CHUNKNAME "vim chunk"
24 #define LUAVIM_NAME "vim"
25 #define LUAVIM_EVALNAME "luaeval"
26 #define LUAVIM_EVALHEADER "local _A=select(1,...) return "
27
28 #ifdef LUA_RELEASE
29 # define LUAVIM_VERSION LUA_RELEASE
30 #else
31 # define LUAVIM_VERSION LUA_VERSION
32 #endif
33
34 typedef buf_T *luaV_Buffer;
35 typedef win_T *luaV_Window;
36 typedef dict_T *luaV_Dict;
37 typedef list_T *luaV_List;
38 typedef blob_T *luaV_Blob;
39 typedef struct {
40 char_u *name; // funcref
41 dict_T *self; // selfdict
42 } luaV_Funcref;
43 typedef int (*msgfunc_T)(char *);
44
45 typedef struct {
46 int lua_funcref; // ref to a lua func
47 int lua_tableref; // ref to a lua table if metatable else LUA_NOREF. used
48 // for __call
49 lua_State *L;
50 } luaV_CFuncState;
51
52 static const char LUAVIM_DICT[] = "dict";
53 static const char LUAVIM_LIST[] = "list";
54 static const char LUAVIM_BLOB[] = "blob";
55 static const char LUAVIM_FUNCREF[] = "funcref";
56 static const char LUAVIM_BUFFER[] = "buffer";
57 static const char LUAVIM_WINDOW[] = "window";
58 static const char LUAVIM_FREE[] = "luaV_free";
59 static const char LUAVIM_LUAEVAL[] = "luaV_luaeval";
60 static const char LUAVIM_SETREF[] = "luaV_setref";
61
62 static const char LUA___CALL[] = "__call";
63
64 // most functions are closures with a cache table as first upvalue;
65 // get/setudata manage references to vim userdata in cache table through
66 // object pointers (light userdata)
67 #define luaV_getudata(L, v) \
68 lua_pushlightuserdata((L), (void *) (v)); \
69 lua_rawget((L), lua_upvalueindex(1))
70 #define luaV_setudata(L, v) \
71 lua_pushlightuserdata((L), (void *) (v)); \
72 lua_pushvalue((L), -2); \
73 lua_rawset((L), lua_upvalueindex(1))
74 #define luaV_getfield(L, s) \
75 lua_pushlightuserdata((L), (void *)(s)); \
76 lua_rawget((L), LUA_REGISTRYINDEX)
77 #define luaV_checksandbox(L) \
78 if (sandbox) luaL_error((L), "not allowed in sandbox")
79 #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
80 #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
81 #define luaV_checktypval(L, a, v, msg) \
82 do { \
83 if (luaV_totypval(L, a, v) == FAIL) \
84 luaL_error(L, msg ": cannot convert value"); \
85 } while (0)
86
87 static luaV_List *luaV_pushlist(lua_State *L, list_T *lis);
88 static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic);
89 static luaV_Blob *luaV_pushblob(lua_State *L, blob_T *blo);
90 static luaV_Funcref *luaV_pushfuncref(lua_State *L, char_u *name);
91 static int luaV_call_lua_func(int argcount, typval_T *argvars, typval_T *rettv, void *state);
92 static void luaV_call_lua_func_free(void *state);
93
94 #if LUA_VERSION_NUM <= 501
95 #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n)
96 #define luaL_typeerror luaL_typerror
97 #else
98 #define luaV_openlib luaL_setfuncs
99 #endif
100
101 #ifdef DYNAMIC_LUA
102
103 #ifndef MSWIN
104 # include <dlfcn.h>
105 # define HANDLE void*
106 # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
107 # define symbol_from_dll dlsym
108 # define close_dll dlclose
109 # define load_dll_error dlerror
110 #else
111 # define load_dll vimLoadLib
112 # define symbol_from_dll GetProcAddress
113 # define close_dll FreeLibrary
114 # define load_dll_error GetWin32Error
115 #endif
116
117 // lauxlib
118 #if LUA_VERSION_NUM <= 501
119 #define luaL_register dll_luaL_register
120 #define luaL_prepbuffer dll_luaL_prepbuffer
121 #define luaL_openlib dll_luaL_openlib
122 #define luaL_typerror dll_luaL_typerror
123 #define luaL_loadfile dll_luaL_loadfile
124 #define luaL_loadbuffer dll_luaL_loadbuffer
125 #else
126 #define luaL_prepbuffsize dll_luaL_prepbuffsize
127 #define luaL_setfuncs dll_luaL_setfuncs
128 #define luaL_loadfilex dll_luaL_loadfilex
129 #define luaL_loadbufferx dll_luaL_loadbufferx
130 #define luaL_argerror dll_luaL_argerror
131 #endif
132 #if LUA_VERSION_NUM >= 504
133 #define luaL_typeerror dll_luaL_typeerror
134 #endif
135 #define luaL_checkany dll_luaL_checkany
136 #define luaL_checklstring dll_luaL_checklstring
137 #define luaL_checkinteger dll_luaL_checkinteger
138 #define luaL_optinteger dll_luaL_optinteger
139 #define luaL_checktype dll_luaL_checktype
140 #define luaL_error dll_luaL_error
141 #define luaL_newstate dll_luaL_newstate
142 #define luaL_buffinit dll_luaL_buffinit
143 #define luaL_addlstring dll_luaL_addlstring
144 #define luaL_pushresult dll_luaL_pushresult
145 #define luaL_loadstring dll_luaL_loadstring
146 #define luaL_ref dll_luaL_ref
147 #define luaL_unref dll_luaL_unref
148 // lua
149 #if LUA_VERSION_NUM <= 501
150 #define lua_tonumber dll_lua_tonumber
151 #define lua_tointeger dll_lua_tointeger
152 #define lua_call dll_lua_call
153 #define lua_pcall dll_lua_pcall
154 #else
155 #define lua_tonumberx dll_lua_tonumberx
156 #define lua_tointegerx dll_lua_tointegerx
157 #define lua_callk dll_lua_callk
158 #define lua_pcallk dll_lua_pcallk
159 #define lua_getglobal dll_lua_getglobal
160 #define lua_setglobal dll_lua_setglobal
161 #endif
162 #if LUA_VERSION_NUM <= 502
163 #define lua_replace dll_lua_replace
164 #define lua_remove dll_lua_remove
165 #endif
166 #if LUA_VERSION_NUM >= 503
167 #define lua_rotate dll_lua_rotate
168 #define lua_copy dll_lua_copy
169 #endif
170 #define lua_typename dll_lua_typename
171 #define lua_close dll_lua_close
172 #define lua_gettop dll_lua_gettop
173 #define lua_settop dll_lua_settop
174 #define lua_pushvalue dll_lua_pushvalue
175 #define lua_isnumber dll_lua_isnumber
176 #define lua_isstring dll_lua_isstring
177 #define lua_type dll_lua_type
178 #define lua_rawequal dll_lua_rawequal
179 #define lua_toboolean dll_lua_toboolean
180 #define lua_tolstring dll_lua_tolstring
181 #define lua_touserdata dll_lua_touserdata
182 #define lua_pushnil dll_lua_pushnil
183 #define lua_pushnumber dll_lua_pushnumber
184 #define lua_pushinteger dll_lua_pushinteger
185 #define lua_pushlstring dll_lua_pushlstring
186 #define lua_pushstring dll_lua_pushstring
187 #define lua_pushfstring dll_lua_pushfstring
188 #define lua_pushcclosure dll_lua_pushcclosure
189 #define lua_pushboolean dll_lua_pushboolean
190 #define lua_pushlightuserdata dll_lua_pushlightuserdata
191 #define lua_getfield dll_lua_getfield
192 #define lua_rawget dll_lua_rawget
193 #define lua_rawgeti dll_lua_rawgeti
194 #define lua_createtable dll_lua_createtable
195 #define lua_settable dll_lua_settable
196 #if LUA_VERSION_NUM >= 504
197 #define lua_newuserdatauv dll_lua_newuserdatauv
198 #else
199 #define lua_newuserdata dll_lua_newuserdata
200 #endif
201 #define lua_getmetatable dll_lua_getmetatable
202 #define lua_setfield dll_lua_setfield
203 #define lua_rawset dll_lua_rawset
204 #define lua_rawseti dll_lua_rawseti
205 #define lua_setmetatable dll_lua_setmetatable
206 #define lua_next dll_lua_next
207 // libs
208 #define luaopen_base dll_luaopen_base
209 #define luaopen_table dll_luaopen_table
210 #define luaopen_string dll_luaopen_string
211 #define luaopen_math dll_luaopen_math
212 #define luaopen_io dll_luaopen_io
213 #define luaopen_os dll_luaopen_os
214 #define luaopen_package dll_luaopen_package
215 #define luaopen_debug dll_luaopen_debug
216 #define luaL_openlibs dll_luaL_openlibs
217
218 // lauxlib
219 #if LUA_VERSION_NUM <= 501
220 void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
221 char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
222 void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup);
223 int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
224 int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
225 int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
226 #else
227 char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
228 void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
229 int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode);
230 int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
231 int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
232 #endif
233 #if LUA_VERSION_NUM >= 504
234 int (*dll_luaL_typeerror) (lua_State *L, int narg, const char *tname);
235 #endif
236 void (*dll_luaL_checkany) (lua_State *L, int narg);
237 const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
238 lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
239 lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
240 void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
241 int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
242 lua_State *(*dll_luaL_newstate) (void);
243 void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
244 void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
245 void (*dll_luaL_pushresult) (luaL_Buffer *B);
246 int (*dll_luaL_loadstring) (lua_State *L, const char *s);
247 int (*dll_luaL_ref) (lua_State *L, int idx);
248 #if LUA_VERSION_NUM <= 502
249 void (*dll_luaL_unref) (lua_State *L, int idx, int n);
250 #else
251 void (*dll_luaL_unref) (lua_State *L, int idx, lua_Integer n);
252 #endif
253 // lua
254 #if LUA_VERSION_NUM <= 501
255 lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
256 lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
257 void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
258 int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
259 #else
260 lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum);
261 lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum);
262 void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
263 lua_CFunction k);
264 int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
265 int ctx, lua_CFunction k);
266 void (*dll_lua_getglobal) (lua_State *L, const char *var);
267 void (*dll_lua_setglobal) (lua_State *L, const char *var);
268 #endif
269 #if LUA_VERSION_NUM <= 502
270 void (*dll_lua_replace) (lua_State *L, int idx);
271 void (*dll_lua_remove) (lua_State *L, int idx);
272 #endif
273 #if LUA_VERSION_NUM >= 503
274 void (*dll_lua_rotate) (lua_State *L, int idx, int n);
275 void (*dll_lua_copy) (lua_State *L, int fromidx, int toidx);
276 #endif
277 const char *(*dll_lua_typename) (lua_State *L, int tp);
278 void (*dll_lua_close) (lua_State *L);
279 int (*dll_lua_gettop) (lua_State *L);
280 void (*dll_lua_settop) (lua_State *L, int idx);
281 void (*dll_lua_pushvalue) (lua_State *L, int idx);
282 int (*dll_lua_isnumber) (lua_State *L, int idx);
283 int (*dll_lua_isstring) (lua_State *L, int idx);
284 int (*dll_lua_type) (lua_State *L, int idx);
285 int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
286 int (*dll_lua_toboolean) (lua_State *L, int idx);
287 const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
288 void *(*dll_lua_touserdata) (lua_State *L, int idx);
289 void (*dll_lua_pushnil) (lua_State *L);
290 void (*dll_lua_pushnumber) (lua_State *L, lua_Number n);
291 void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n);
292 void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l);
293 void (*dll_lua_pushstring) (lua_State *L, const char *s);
294 const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...);
295 void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
296 void (*dll_lua_pushboolean) (lua_State *L, int b);
297 void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
298 void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
299 #if LUA_VERSION_NUM <= 502
300 void (*dll_lua_rawget) (lua_State *L, int idx);
301 void (*dll_lua_rawgeti) (lua_State *L, int idx, int n);
302 #else
303 int (*dll_lua_rawget) (lua_State *L, int idx);
304 int (*dll_lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
305 #endif
306 void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
307 void (*dll_lua_settable) (lua_State *L, int idx);
308 #if LUA_VERSION_NUM >= 504
309 void *(*dll_lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
310 #else
311 void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
312 #endif
313 int (*dll_lua_getmetatable) (lua_State *L, int objindex);
314 void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
315 void (*dll_lua_rawset) (lua_State *L, int idx);
316 #if LUA_VERSION_NUM <= 502
317 void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
318 #else
319 void (*dll_lua_rawseti) (lua_State *L, int idx, lua_Integer n);
320 #endif
321 int (*dll_lua_setmetatable) (lua_State *L, int objindex);
322 int (*dll_lua_next) (lua_State *L, int idx);
323 // libs
324 int (*dll_luaopen_base) (lua_State *L);
325 int (*dll_luaopen_table) (lua_State *L);
326 int (*dll_luaopen_string) (lua_State *L);
327 int (*dll_luaopen_math) (lua_State *L);
328 int (*dll_luaopen_io) (lua_State *L);
329 int (*dll_luaopen_os) (lua_State *L);
330 int (*dll_luaopen_package) (lua_State *L);
331 int (*dll_luaopen_debug) (lua_State *L);
332 void (*dll_luaL_openlibs) (lua_State *L);
333
334 typedef void **luaV_function;
335 typedef struct {
336 const char *name;
337 luaV_function func;
338 } luaV_Reg;
339
340 static const luaV_Reg luaV_dll[] = {
341 // lauxlib
342 #if LUA_VERSION_NUM <= 501
343 {"luaL_register", (luaV_function) &dll_luaL_register},
344 {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
345 {"luaL_openlib", (luaV_function) &dll_luaL_openlib},
346 {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
347 {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
348 {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
349 #else
350 {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize},
351 {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs},
352 {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex},
353 {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx},
354 {"luaL_argerror", (luaV_function) &dll_luaL_argerror},
355 #endif
356 #if LUA_VERSION_NUM >= 504
357 {"luaL_typeerror", (luaV_function) &dll_luaL_typeerror},
358 #endif
359 {"luaL_checkany", (luaV_function) &dll_luaL_checkany},
360 {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
361 {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
362 {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
363 {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
364 {"luaL_error", (luaV_function) &dll_luaL_error},
365 {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
366 {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
367 {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
368 {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
369 {"luaL_loadstring", (luaV_function) &dll_luaL_loadstring},
370 {"luaL_ref", (luaV_function) &dll_luaL_ref},
371 {"luaL_unref", (luaV_function) &dll_luaL_unref},
372 // lua
373 #if LUA_VERSION_NUM <= 501
374 {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
375 {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
376 {"lua_call", (luaV_function) &dll_lua_call},
377 {"lua_pcall", (luaV_function) &dll_lua_pcall},
378 #else
379 {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx},
380 {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx},
381 {"lua_callk", (luaV_function) &dll_lua_callk},
382 {"lua_pcallk", (luaV_function) &dll_lua_pcallk},
383 {"lua_getglobal", (luaV_function) &dll_lua_getglobal},
384 {"lua_setglobal", (luaV_function) &dll_lua_setglobal},
385 #endif
386 #if LUA_VERSION_NUM <= 502
387 {"lua_replace", (luaV_function) &dll_lua_replace},
388 {"lua_remove", (luaV_function) &dll_lua_remove},
389 #endif
390 #if LUA_VERSION_NUM >= 503
391 {"lua_rotate", (luaV_function) &dll_lua_rotate},
392 {"lua_copy", (luaV_function) &dll_lua_copy},
393 #endif
394 {"lua_typename", (luaV_function) &dll_lua_typename},
395 {"lua_close", (luaV_function) &dll_lua_close},
396 {"lua_gettop", (luaV_function) &dll_lua_gettop},
397 {"lua_settop", (luaV_function) &dll_lua_settop},
398 {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
399 {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
400 {"lua_isstring", (luaV_function) &dll_lua_isstring},
401 {"lua_type", (luaV_function) &dll_lua_type},
402 {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
403 {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
404 {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
405 {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
406 {"lua_pushnil", (luaV_function) &dll_lua_pushnil},
407 {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber},
408 {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger},
409 {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring},
410 {"lua_pushstring", (luaV_function) &dll_lua_pushstring},
411 {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring},
412 {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure},
413 {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean},
414 {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
415 {"lua_getfield", (luaV_function) &dll_lua_getfield},
416 {"lua_rawget", (luaV_function) &dll_lua_rawget},
417 {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti},
418 {"lua_createtable", (luaV_function) &dll_lua_createtable},
419 {"lua_settable", (luaV_function) &dll_lua_settable},
420 #if LUA_VERSION_NUM >= 504
421 {"lua_newuserdatauv", (luaV_function) &dll_lua_newuserdatauv},
422 #else
423 {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
424 #endif
425 {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
426 {"lua_setfield", (luaV_function) &dll_lua_setfield},
427 {"lua_rawset", (luaV_function) &dll_lua_rawset},
428 {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
429 {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
430 {"lua_next", (luaV_function) &dll_lua_next},
431 // libs
432 {"luaopen_base", (luaV_function) &dll_luaopen_base},
433 {"luaopen_table", (luaV_function) &dll_luaopen_table},
434 {"luaopen_string", (luaV_function) &dll_luaopen_string},
435 {"luaopen_math", (luaV_function) &dll_luaopen_math},
436 {"luaopen_io", (luaV_function) &dll_luaopen_io},
437 {"luaopen_os", (luaV_function) &dll_luaopen_os},
438 {"luaopen_package", (luaV_function) &dll_luaopen_package},
439 {"luaopen_debug", (luaV_function) &dll_luaopen_debug},
440 {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs},
441 {NULL, NULL}
442 };
443
444 static HANDLE hinstLua = NULL;
445
446 static int
lua_link_init(char * libname,int verbose)447 lua_link_init(char *libname, int verbose)
448 {
449 const luaV_Reg *reg;
450 if (hinstLua) return OK;
451 hinstLua = load_dll(libname);
452 if (!hinstLua)
453 {
454 if (verbose)
455 semsg(_(e_loadlib), libname, load_dll_error());
456 return FAIL;
457 }
458 for (reg = luaV_dll; reg->func; reg++)
459 {
460 if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL)
461 {
462 close_dll(hinstLua);
463 hinstLua = 0;
464 if (verbose)
465 semsg(_(e_loadfunc), reg->name);
466 return FAIL;
467 }
468 }
469 return OK;
470 }
471 #endif // DYNAMIC_LUA
472
473 #if defined(DYNAMIC_LUA) || defined(PROTO)
474 int
lua_enabled(int verbose)475 lua_enabled(int verbose)
476 {
477 return lua_link_init((char *)p_luadll, verbose) == OK;
478 }
479 #endif
480
481 #if LUA_VERSION_NUM > 501 && LUA_VERSION_NUM < 504
482 static int
luaL_typeerror(lua_State * L,int narg,const char * tname)483 luaL_typeerror(lua_State *L, int narg, const char *tname)
484 {
485 const char *msg = lua_pushfstring(L, "%s expected, got %s",
486 tname, luaL_typename(L, narg));
487 return luaL_argerror(L, narg, msg);
488 }
489 #endif
490
491
492 // ======= Internal =======
493
494 static void
luaV_newmetatable(lua_State * L,const char * tname)495 luaV_newmetatable(lua_State *L, const char *tname)
496 {
497 lua_newtable(L);
498 lua_pushlightuserdata(L, (void *) tname);
499 lua_pushvalue(L, -2);
500 lua_rawset(L, LUA_REGISTRYINDEX);
501 }
502
503 static void *
luaV_toudata(lua_State * L,int ud,const char * tname)504 luaV_toudata(lua_State *L, int ud, const char *tname)
505 {
506 void *p = lua_touserdata(L, ud);
507
508 if (p != NULL) // value is userdata?
509 {
510 if (lua_getmetatable(L, ud)) // does it have a metatable?
511 {
512 luaV_getfield(L, tname); // get metatable
513 if (lua_rawequal(L, -1, -2)) // MTs match?
514 {
515 lua_pop(L, 2); // MTs
516 return p;
517 }
518 }
519 }
520 return NULL;
521 }
522
523 static void *
luaV_checkcache(lua_State * L,void * p)524 luaV_checkcache(lua_State *L, void *p)
525 {
526 luaV_getudata(L, p);
527 if (lua_isnil(L, -1)) luaL_error(L, "invalid object");
528 lua_pop(L, 1);
529 return p;
530 }
531
532 #define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud))))
533
534 #define luaV_checkvalid(L,luatyp,ud) \
535 luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud)))
536
537 static void *
luaV_checkudata(lua_State * L,int ud,const char * tname)538 luaV_checkudata(lua_State *L, int ud, const char *tname)
539 {
540 void *p = luaV_toudata(L, ud, tname);
541 if (p == NULL) luaL_typeerror(L, ud, tname);
542 return p;
543 }
544
545 static void
luaV_pushtypval(lua_State * L,typval_T * tv)546 luaV_pushtypval(lua_State *L, typval_T *tv)
547 {
548 if (tv == NULL)
549 {
550 lua_pushnil(L);
551 return;
552 }
553 switch (tv->v_type)
554 {
555 case VAR_STRING:
556 lua_pushstring(L, tv->vval.v_string == NULL
557 ? "" : (char *)tv->vval.v_string);
558 break;
559 case VAR_NUMBER:
560 lua_pushinteger(L, (int) tv->vval.v_number);
561 break;
562 #ifdef FEAT_FLOAT
563 case VAR_FLOAT:
564 lua_pushnumber(L, (lua_Number) tv->vval.v_float);
565 break;
566 #endif
567 case VAR_LIST:
568 luaV_pushlist(L, tv->vval.v_list);
569 break;
570 case VAR_DICT:
571 luaV_pushdict(L, tv->vval.v_dict);
572 break;
573 case VAR_BOOL:
574 case VAR_SPECIAL:
575 if (tv->vval.v_number <= VVAL_TRUE)
576 lua_pushinteger(L, (int) tv->vval.v_number);
577 else
578 lua_pushnil(L);
579 break;
580 case VAR_FUNC:
581 luaV_pushfuncref(L, tv->vval.v_string);
582 break;
583 case VAR_PARTIAL:
584 // TODO: handle partial arguments
585 luaV_pushfuncref(L, partial_name(tv->vval.v_partial));
586 break;
587
588 case VAR_BLOB:
589 luaV_pushblob(L, tv->vval.v_blob);
590 break;
591 default:
592 lua_pushnil(L);
593 }
594 }
595
596 /*
597 * Converts lua value at 'pos' to typval 'tv'.
598 * Returns OK or FAIL.
599 */
600 static int
luaV_totypval(lua_State * L,int pos,typval_T * tv)601 luaV_totypval(lua_State *L, int pos, typval_T *tv)
602 {
603 int status = OK;
604
605 tv->v_lock = 0;
606
607 switch (lua_type(L, pos))
608 {
609 case LUA_TBOOLEAN:
610 tv->v_type = VAR_BOOL;
611 tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
612 break;
613 case LUA_TNIL:
614 tv->v_type = VAR_SPECIAL;
615 tv->vval.v_number = VVAL_NULL;
616 break;
617 case LUA_TSTRING:
618 tv->v_type = VAR_STRING;
619 tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos));
620 break;
621 case LUA_TNUMBER:
622 #ifdef FEAT_FLOAT
623 {
624 const lua_Number n = lua_tonumber(L, pos);
625
626 if (n > (lua_Number)INT64_MAX || n < (lua_Number)INT64_MIN
627 || ((lua_Number)((varnumber_T)n)) != n)
628 {
629 tv->v_type = VAR_FLOAT;
630 tv->vval.v_float = (float_T)n;
631 }
632 else
633 {
634 tv->v_type = VAR_NUMBER;
635 tv->vval.v_number = (varnumber_T)n;
636 }
637 }
638 #else
639 tv->v_type = VAR_NUMBER;
640 tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
641 #endif
642 break;
643 case LUA_TFUNCTION:
644 {
645 char_u *name;
646 luaV_CFuncState *state;
647
648 lua_pushvalue(L, pos);
649 state = ALLOC_CLEAR_ONE(luaV_CFuncState);
650 state->lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
651 state->L = L;
652 state->lua_tableref = LUA_NOREF;
653 name = register_cfunc(&luaV_call_lua_func,
654 &luaV_call_lua_func_free, state);
655 tv->v_type = VAR_FUNC;
656 tv->vval.v_string = vim_strsave(name);
657 break;
658 }
659 case LUA_TTABLE:
660 {
661 int lua_tableref;
662
663 lua_pushvalue(L, pos);
664 lua_tableref = luaL_ref(L, LUA_REGISTRYINDEX);
665 if (lua_getmetatable(L, pos)) {
666 lua_getfield(L, -1, LUA___CALL);
667 if (lua_isfunction(L, -1)) {
668 char_u *name;
669 int lua_funcref = luaL_ref(L, LUA_REGISTRYINDEX);
670 luaV_CFuncState *state = ALLOC_CLEAR_ONE(luaV_CFuncState);
671
672 state->lua_funcref = lua_funcref;
673 state->L = L;
674 state->lua_tableref = lua_tableref;
675 name = register_cfunc(&luaV_call_lua_func,
676 &luaV_call_lua_func_free, state);
677 tv->v_type = VAR_FUNC;
678 tv->vval.v_string = vim_strsave(name);
679 break;
680 }
681 }
682 tv->v_type = VAR_NUMBER;
683 tv->vval.v_number = 0;
684 status = FAIL;
685 break;
686 }
687 case LUA_TUSERDATA:
688 {
689 void *p = lua_touserdata(L, pos);
690
691 if (lua_getmetatable(L, pos)) // has metatable?
692 {
693 // check list
694 luaV_getfield(L, LUAVIM_LIST);
695 if (lua_rawequal(L, -1, -2))
696 {
697 tv->v_type = VAR_LIST;
698 tv->vval.v_list = *((luaV_List *) p);
699 ++tv->vval.v_list->lv_refcount;
700 lua_pop(L, 2); // MTs
701 break;
702 }
703 // check dict
704 luaV_getfield(L, LUAVIM_DICT);
705 if (lua_rawequal(L, -1, -3))
706 {
707 tv->v_type = VAR_DICT;
708 tv->vval.v_dict = *((luaV_Dict *) p);
709 ++tv->vval.v_dict->dv_refcount;
710 lua_pop(L, 3); // MTs
711 break;
712 }
713 // check blob
714 luaV_getfield(L, LUAVIM_BLOB);
715 if (lua_rawequal(L, -1, -4))
716 {
717 tv->v_type = VAR_BLOB;
718 tv->vval.v_blob = *((luaV_Blob *) p);
719 ++tv->vval.v_blob->bv_refcount;
720 lua_pop(L, 4); // MTs
721 break;
722 }
723 // check funcref
724 luaV_getfield(L, LUAVIM_FUNCREF);
725 if (lua_rawequal(L, -1, -5))
726 {
727 luaV_Funcref *f = (luaV_Funcref *) p;
728
729 func_ref(f->name);
730 tv->v_type = VAR_FUNC;
731 tv->vval.v_string = vim_strsave(f->name);
732 lua_pop(L, 5); // MTs
733 break;
734 }
735 lua_pop(L, 4); // MTs
736 }
737 }
738 // FALLTHROUGH
739 default:
740 tv->v_type = VAR_NUMBER;
741 tv->vval.v_number = 0;
742 status = FAIL;
743 }
744 return status;
745 }
746
747 /*
748 * similar to luaL_addlstring, but replaces \0 with \n if toline and
749 * \n with \0 otherwise
750 */
751 static void
luaV_addlstring(luaL_Buffer * b,const char * s,size_t l,int toline)752 luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline)
753 {
754 while (l--)
755 {
756 if (*s == '\0' && toline)
757 luaL_addchar(b, '\n');
758 else if (*s == '\n' && !toline)
759 luaL_addchar(b, '\0');
760 else
761 luaL_addchar(b, *s);
762 s++;
763 }
764 }
765
766 static void
luaV_pushline(lua_State * L,buf_T * buf,linenr_T n)767 luaV_pushline(lua_State *L, buf_T *buf, linenr_T n)
768 {
769 const char *s = (const char *) ml_get_buf(buf, n, FALSE);
770 luaL_Buffer b;
771 luaL_buffinit(L, &b);
772 luaV_addlstring(&b, s, strlen(s), 0);
773 luaL_pushresult(&b);
774 }
775
776 static char_u *
luaV_toline(lua_State * L,int pos)777 luaV_toline(lua_State *L, int pos)
778 {
779 size_t l;
780 const char *s = lua_tolstring(L, pos, &l);
781
782 luaL_Buffer b;
783 luaL_buffinit(L, &b);
784 luaV_addlstring(&b, s, l, 1);
785 luaL_pushresult(&b);
786 return (char_u *) lua_tostring(L, -1);
787 }
788
789 /*
790 * pops a string s from the top of the stack and calls mf(t) for pieces t of
791 * s separated by newlines
792 */
793 static void
luaV_msgfunc(lua_State * L,msgfunc_T mf)794 luaV_msgfunc(lua_State *L, msgfunc_T mf)
795 {
796 luaL_Buffer b;
797 size_t l;
798 const char *p, *s = lua_tolstring(L, -1, &l);
799 luaL_buffinit(L, &b);
800 luaV_addlstring(&b, s, l, 0);
801 luaL_pushresult(&b);
802 // break string
803 p = s = lua_tolstring(L, -1, &l);
804 while (l--)
805 {
806 if (*p++ == '\0') // break?
807 {
808 mf((char *)s);
809 s = p;
810 }
811 }
812 mf((char *)s);
813 lua_pop(L, 2); // original and modified strings
814 }
815
816 #define luaV_newtype(typ,tname,luatyp,luatname) \
817 static luatyp * \
818 luaV_new##tname(lua_State *L, typ *obj) \
819 { \
820 luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \
821 *o = obj; \
822 luaV_setudata(L, obj); /* cache[obj] = udata */ \
823 luaV_getfield(L, luatname); \
824 lua_setmetatable(L, -2); \
825 return o; \
826 }
827
828 #define luaV_pushtype(typ,tname,luatyp) \
829 static luatyp * \
830 luaV_push##tname(lua_State *L, typ *obj) \
831 { \
832 luatyp *o = NULL; \
833 if (obj == NULL) \
834 lua_pushnil(L); \
835 else { \
836 luaV_getudata(L, obj); \
837 if (lua_isnil(L, -1)) /* not interned? */ \
838 { \
839 lua_pop(L, 1); \
840 o = luaV_new##tname(L, obj); \
841 } \
842 else \
843 o = (luatyp *) lua_touserdata(L, -1); \
844 } \
845 return o; \
846 }
847
848 #define luaV_type_tostring(tname,luatname) \
849 static int \
850 luaV_##tname##_tostring(lua_State *L) \
851 { \
852 lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \
853 return 1; \
854 }
855
856 // ======= List type =======
857
858 static luaV_List *
luaV_newlist(lua_State * L,list_T * lis)859 luaV_newlist(lua_State *L, list_T *lis)
860 {
861 luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List));
862 *l = lis;
863 lis->lv_refcount++; // reference in Lua
864 luaV_setudata(L, lis); // cache[lis] = udata
865 luaV_getfield(L, LUAVIM_LIST);
866 lua_setmetatable(L, -2);
867 return l;
868 }
869
luaV_pushtype(list_T,list,luaV_List)870 luaV_pushtype(list_T, list, luaV_List)
871 luaV_type_tostring(list, LUAVIM_LIST)
872
873 static int
874 luaV_list_len(lua_State *L)
875 {
876 list_T *l = luaV_unbox(L, luaV_List, 1);
877 lua_pushinteger(L, (int) list_len(l));
878 return 1;
879 }
880
881 static int
luaV_list_iter(lua_State * L)882 luaV_list_iter(lua_State *L)
883 {
884 listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2));
885 if (li == NULL) return 0;
886 luaV_pushtypval(L, &li->li_tv);
887 lua_pushlightuserdata(L, (void *) li->li_next);
888 lua_replace(L, lua_upvalueindex(2));
889 return 1;
890 }
891
892 static int
luaV_list_call(lua_State * L)893 luaV_list_call(lua_State *L)
894 {
895 list_T *l = luaV_unbox(L, luaV_List, 1);
896 lua_pushvalue(L, lua_upvalueindex(1)); // pass cache table along
897 lua_pushlightuserdata(L, (void *) l->lv_first);
898 lua_pushcclosure(L, luaV_list_iter, 2);
899 return 1;
900 }
901
902 static int
luaV_list_index(lua_State * L)903 luaV_list_index(lua_State *L)
904 {
905 list_T *l = luaV_unbox(L, luaV_List, 1);
906 if (lua_isnumber(L, 2)) // list item?
907 {
908 long n = (long) luaL_checkinteger(L, 2);
909 listitem_T *li;
910
911 // Lua array index starts with 1 while Vim uses 0, subtract 1 to
912 // normalize.
913 n -= 1;
914 li = list_find(l, n);
915 if (li == NULL)
916 lua_pushnil(L);
917 else
918 luaV_pushtypval(L, &li->li_tv);
919 }
920 else if (lua_isstring(L, 2)) // method?
921 {
922 const char *s = lua_tostring(L, 2);
923 if (strncmp(s, "add", 3) == 0
924 || strncmp(s, "insert", 6) == 0)
925 {
926 lua_getmetatable(L, 1);
927 lua_getfield(L, -1, s);
928 }
929 else
930 lua_pushnil(L);
931 }
932 else
933 lua_pushnil(L);
934 return 1;
935 }
936
937 static int
luaV_list_newindex(lua_State * L)938 luaV_list_newindex(lua_State *L)
939 {
940 list_T *l = luaV_unbox(L, luaV_List, 1);
941 long n = (long) luaL_checkinteger(L, 2);
942 listitem_T *li;
943
944 // Lua array index starts with 1 while Vim uses 0, subtract 1 to normalize.
945 n -= 1;
946
947 if (l->lv_lock)
948 luaL_error(L, "list is locked");
949 li = list_find(l, n);
950 if (li == NULL)
951 {
952 if (!lua_isnil(L, 3))
953 {
954 typval_T v;
955 luaV_checktypval(L, 3, &v, "inserting list item");
956 if (list_insert_tv(l, &v, li) == FAIL)
957 luaL_error(L, "failed to add item to list");
958 clear_tv(&v);
959 }
960 }
961 else
962 {
963 if (lua_isnil(L, 3)) // remove?
964 {
965 vimlist_remove(l, li, li);
966 listitem_free(l, li);
967 }
968 else
969 {
970 typval_T v;
971 luaV_checktypval(L, 3, &v, "setting list item");
972 clear_tv(&li->li_tv);
973 li->li_tv = v;
974 }
975 }
976 return 0;
977 }
978
979 static int
luaV_list_add(lua_State * L)980 luaV_list_add(lua_State *L)
981 {
982 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
983 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
984 typval_T v;
985 if (l->lv_lock)
986 luaL_error(L, "list is locked");
987 lua_settop(L, 2);
988 luaV_checktypval(L, 2, &v, "adding list item");
989 if (list_append_tv(l, &v) == FAIL)
990 luaL_error(L, "failed to add item to list");
991 clear_tv(&v);
992 lua_settop(L, 1);
993 return 1;
994 }
995
996 static int
luaV_list_insert(lua_State * L)997 luaV_list_insert(lua_State *L)
998 {
999 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST);
1000 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis);
1001 long pos = (long) luaL_optinteger(L, 3, 0);
1002 listitem_T *li = NULL;
1003 typval_T v;
1004 if (l->lv_lock)
1005 luaL_error(L, "list is locked");
1006 if (pos < l->lv_len)
1007 {
1008 li = list_find(l, pos);
1009 if (li == NULL)
1010 luaL_error(L, "invalid position");
1011 }
1012 lua_settop(L, 2);
1013 luaV_checktypval(L, 2, &v, "inserting list item");
1014 if (list_insert_tv(l, &v, li) == FAIL)
1015 luaL_error(L, "failed to add item to list");
1016 clear_tv(&v);
1017 lua_settop(L, 1);
1018 return 1;
1019 }
1020
1021 static const luaL_Reg luaV_List_mt[] = {
1022 {"__tostring", luaV_list_tostring},
1023 {"__len", luaV_list_len},
1024 {"__call", luaV_list_call},
1025 {"__index", luaV_list_index},
1026 {"__newindex", luaV_list_newindex},
1027 {"add", luaV_list_add},
1028 {"insert", luaV_list_insert},
1029 {NULL, NULL}
1030 };
1031
1032
1033 // ======= Dict type =======
1034
1035 static luaV_Dict *
luaV_newdict(lua_State * L,dict_T * dic)1036 luaV_newdict(lua_State *L, dict_T *dic)
1037 {
1038 luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict));
1039 *d = dic;
1040 dic->dv_refcount++; // reference in Lua
1041 luaV_setudata(L, dic); // cache[dic] = udata
1042 luaV_getfield(L, LUAVIM_DICT);
1043 lua_setmetatable(L, -2);
1044 return d;
1045 }
1046
luaV_pushtype(dict_T,dict,luaV_Dict)1047 luaV_pushtype(dict_T, dict, luaV_Dict)
1048 luaV_type_tostring(dict, LUAVIM_DICT)
1049
1050 static int
1051 luaV_dict_len(lua_State *L)
1052 {
1053 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1054 lua_pushinteger(L, (int) dict_len(d));
1055 return 1;
1056 }
1057
1058 static int
luaV_dict_iter(lua_State * L UNUSED)1059 luaV_dict_iter(lua_State *L UNUSED)
1060 {
1061 #ifdef FEAT_EVAL
1062 hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2));
1063 int n = lua_tointeger(L, lua_upvalueindex(3));
1064 dictitem_T *di;
1065 if (n <= 0) return 0;
1066 while (HASHITEM_EMPTY(hi)) hi++;
1067 di = dict_lookup(hi);
1068 lua_pushstring(L, (char *) hi->hi_key);
1069 luaV_pushtypval(L, &di->di_tv);
1070 lua_pushlightuserdata(L, (void *) (hi + 1));
1071 lua_replace(L, lua_upvalueindex(2));
1072 lua_pushinteger(L, n - 1);
1073 lua_replace(L, lua_upvalueindex(3));
1074 return 2;
1075 #else
1076 return 0;
1077 #endif
1078 }
1079
1080 static int
luaV_dict_call(lua_State * L)1081 luaV_dict_call(lua_State *L)
1082 {
1083 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1084 hashtab_T *ht = &d->dv_hashtab;
1085 lua_pushvalue(L, lua_upvalueindex(1)); // pass cache table along
1086 lua_pushlightuserdata(L, (void *) ht->ht_array);
1087 lua_pushinteger(L, ht->ht_used); // # remaining items
1088 lua_pushcclosure(L, luaV_dict_iter, 3);
1089 return 1;
1090 }
1091
1092 static int
luaV_dict_index(lua_State * L)1093 luaV_dict_index(lua_State *L)
1094 {
1095 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1096 char_u *key = (char_u *) luaL_checkstring(L, 2);
1097 dictitem_T *di = dict_find(d, key, -1);
1098
1099 if (di == NULL)
1100 lua_pushnil(L);
1101 else
1102 {
1103 luaV_pushtypval(L, &di->di_tv);
1104 if (di->di_tv.v_type == VAR_FUNC) // funcref?
1105 {
1106 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1);
1107 f->self = d; // keep "self" reference
1108 d->dv_refcount++;
1109 }
1110 }
1111 return 1;
1112 }
1113
1114 static int
luaV_dict_newindex(lua_State * L)1115 luaV_dict_newindex(lua_State *L)
1116 {
1117 dict_T *d = luaV_unbox(L, luaV_Dict, 1);
1118 char_u *key = (char_u *) luaL_checkstring(L, 2);
1119 dictitem_T *di;
1120 typval_T tv;
1121
1122 if (d->dv_lock)
1123 luaL_error(L, "dict is locked");
1124 if (key == NULL)
1125 return 0;
1126 if (*key == NUL)
1127 luaL_error(L, "empty key");
1128 if (!lua_isnil(L, 3)) // read value?
1129 {
1130 luaV_checktypval(L, 3, &tv, "setting dict item");
1131 if (d->dv_scope == VAR_DEF_SCOPE && tv.v_type == VAR_FUNC)
1132 {
1133 clear_tv(&tv);
1134 luaL_error(L, "cannot assign funcref to builtin scope");
1135 }
1136 }
1137 di = dict_find(d, key, -1);
1138 if (di == NULL) // non-existing key?
1139 {
1140 if (lua_isnil(L, 3))
1141 return 0;
1142 di = dictitem_alloc(key);
1143 if (di == NULL)
1144 {
1145 clear_tv(&tv);
1146 return 0;
1147 }
1148 if (dict_add(d, di) == FAIL)
1149 {
1150 vim_free(di);
1151 clear_tv(&tv);
1152 return 0;
1153 }
1154 }
1155 else
1156 clear_tv(&di->di_tv);
1157 if (lua_isnil(L, 3)) // remove?
1158 {
1159 hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key);
1160 hash_remove(&d->dv_hashtab, hi);
1161 dictitem_free(di);
1162 }
1163 else
1164 di->di_tv = tv;
1165 return 0;
1166 }
1167
1168 static const luaL_Reg luaV_Dict_mt[] = {
1169 {"__tostring", luaV_dict_tostring},
1170 {"__len", luaV_dict_len},
1171 {"__call", luaV_dict_call},
1172 {"__index", luaV_dict_index},
1173 {"__newindex", luaV_dict_newindex},
1174 {NULL, NULL}
1175 };
1176
1177
1178 // ======= Blob type =======
1179
1180 static luaV_Blob *
luaV_newblob(lua_State * L,blob_T * blo)1181 luaV_newblob(lua_State *L, blob_T *blo)
1182 {
1183 luaV_Blob *b = (luaV_Blob *) lua_newuserdata(L, sizeof(luaV_Blob));
1184 *b = blo;
1185 blo->bv_refcount++; // reference in Lua
1186 luaV_setudata(L, blo); // cache[blo] = udata
1187 luaV_getfield(L, LUAVIM_BLOB);
1188 lua_setmetatable(L, -2);
1189 return b;
1190 }
1191
luaV_pushtype(blob_T,blob,luaV_Blob)1192 luaV_pushtype(blob_T, blob, luaV_Blob)
1193 luaV_type_tostring(blob, LUAVIM_BLOB)
1194
1195 static int
1196 luaV_blob_gc(lua_State *L)
1197 {
1198 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1199 blob_unref(b);
1200 return 0;
1201 }
1202
1203 static int
luaV_blob_len(lua_State * L)1204 luaV_blob_len(lua_State *L)
1205 {
1206 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1207 lua_pushinteger(L, (int) blob_len(b));
1208 return 1;
1209 }
1210
1211 static int
luaV_blob_index(lua_State * L)1212 luaV_blob_index(lua_State *L)
1213 {
1214 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1215 if (lua_isnumber(L, 2))
1216 {
1217 int idx = luaL_checkinteger(L, 2);
1218 if (idx < blob_len(b))
1219 lua_pushnumber(L, (lua_Number) blob_get(b, idx));
1220 else
1221 lua_pushnil(L);
1222 }
1223 else if (lua_isstring(L, 2))
1224 {
1225 const char *s = lua_tostring(L, 2);
1226 if (strncmp(s, "add", 3) == 0)
1227 {
1228 lua_getmetatable(L, 1);
1229 lua_getfield(L, -1, s);
1230 }
1231 else
1232 lua_pushnil(L);
1233 }
1234 else
1235 lua_pushnil(L);
1236 return 1;
1237 }
1238
1239 static int
luaV_blob_newindex(lua_State * L)1240 luaV_blob_newindex(lua_State *L)
1241 {
1242 blob_T *b = luaV_unbox(L, luaV_Blob, 1);
1243 if (b->bv_lock)
1244 luaL_error(L, "blob is locked");
1245 if (lua_isnumber(L, 2))
1246 {
1247 long len = blob_len(b);
1248 int idx = luaL_checkinteger(L, 2);
1249 int val = luaL_checkinteger(L, 3);
1250 if (idx < len || (idx == len && ga_grow(&b->bv_ga, 1) == OK))
1251 {
1252 blob_set(b, idx, (char_u) val);
1253 if (idx == len)
1254 ++b->bv_ga.ga_len;
1255 }
1256 else
1257 luaL_error(L, "index out of range");
1258 }
1259 return 0;
1260 }
1261
1262 static int
luaV_blob_add(lua_State * L)1263 luaV_blob_add(lua_State *L)
1264 {
1265 luaV_Blob *blo = luaV_checkudata(L, 1, LUAVIM_BLOB);
1266 blob_T *b = (blob_T *) luaV_checkcache(L, (void *) *blo);
1267 if (b->bv_lock)
1268 luaL_error(L, "blob is locked");
1269 lua_settop(L, 2);
1270 if (!lua_isstring(L, 2))
1271 luaL_error(L, "string expected, got %s", luaL_typename(L, 2));
1272 else
1273 {
1274 size_t i, l = 0;
1275 const char *s = lua_tolstring(L, 2, &l);
1276
1277 if (ga_grow(&b->bv_ga, (int)l) == OK)
1278 for (i = 0; i < l; ++i)
1279 ga_append(&b->bv_ga, s[i]);
1280 }
1281 lua_settop(L, 1);
1282 return 1;
1283 }
1284
1285 static const luaL_Reg luaV_Blob_mt[] = {
1286 {"__tostring", luaV_blob_tostring},
1287 {"__gc", luaV_blob_gc},
1288 {"__len", luaV_blob_len},
1289 {"__index", luaV_blob_index},
1290 {"__newindex", luaV_blob_newindex},
1291 {"add", luaV_blob_add},
1292 {NULL, NULL}
1293 };
1294
1295
1296 // ======= Funcref type =======
1297
1298 static luaV_Funcref *
luaV_newfuncref(lua_State * L,char_u * name)1299 luaV_newfuncref(lua_State *L, char_u *name)
1300 {
1301 luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref));
1302
1303 if (name != NULL)
1304 {
1305 func_ref(name);
1306 f->name = vim_strsave(name);
1307 }
1308 f->self = NULL;
1309 luaV_getfield(L, LUAVIM_FUNCREF);
1310 lua_setmetatable(L, -2);
1311 return f;
1312 }
1313
1314 static luaV_Funcref *
luaV_pushfuncref(lua_State * L,char_u * name)1315 luaV_pushfuncref(lua_State *L, char_u *name)
1316 {
1317 return luaV_newfuncref(L, name);
1318 }
1319
1320
luaV_type_tostring(funcref,LUAVIM_FUNCREF)1321 luaV_type_tostring(funcref, LUAVIM_FUNCREF)
1322
1323 static int
1324 luaV_funcref_gc(lua_State *L)
1325 {
1326 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1327
1328 func_unref(f->name);
1329 vim_free(f->name);
1330 // NOTE: Don't call "dict_unref(f->self)", because the dict of "f->self"
1331 // will be (or has been already) freed by Vim's garbage collection.
1332 return 0;
1333 }
1334
1335 // equivalent to string(funcref)
1336 static int
luaV_funcref_len(lua_State * L)1337 luaV_funcref_len(lua_State *L)
1338 {
1339 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1340
1341 lua_pushstring(L, (const char *) f->name);
1342 return 1;
1343 }
1344
1345 static int
luaV_funcref_call(lua_State * L)1346 luaV_funcref_call(lua_State *L)
1347 {
1348 luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
1349 int i, n = lua_gettop(L) - 1; // #args
1350 int status = FAIL;
1351 typval_T args;
1352 typval_T rettv;
1353
1354 args.v_type = VAR_LIST;
1355 args.vval.v_list = list_alloc();
1356 rettv.v_type = VAR_UNKNOWN; // as in clear_tv
1357 if (args.vval.v_list != NULL)
1358 {
1359 typval_T v;
1360
1361 for (i = 0; i < n; i++)
1362 {
1363 luaV_checktypval(L, i + 2, &v, "calling funcref");
1364 list_append_tv(args.vval.v_list, &v);
1365 clear_tv(&v);
1366 }
1367 status = func_call(f->name, &args, NULL, f->self, &rettv);
1368 if (status == OK)
1369 luaV_pushtypval(L, &rettv);
1370 clear_tv(&args);
1371 clear_tv(&rettv);
1372 }
1373 if (status != OK)
1374 luaL_error(L, "cannot call funcref");
1375 return 1;
1376 }
1377
1378 static const luaL_Reg luaV_Funcref_mt[] = {
1379 {"__tostring", luaV_funcref_tostring},
1380 {"__gc", luaV_funcref_gc},
1381 {"__len", luaV_funcref_len},
1382 {"__call", luaV_funcref_call},
1383 {NULL, NULL}
1384 };
1385
1386
1387 // ======= Buffer type =======
1388
luaV_newtype(buf_T,buffer,luaV_Buffer,LUAVIM_BUFFER)1389 luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER)
1390 luaV_pushtype(buf_T, buffer, luaV_Buffer)
1391 luaV_type_tostring(buffer, LUAVIM_BUFFER)
1392
1393 static int
1394 luaV_buffer_len(lua_State *L)
1395 {
1396 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
1397 lua_pushinteger(L, b->b_ml.ml_line_count);
1398 return 1;
1399 }
1400
1401 static int
luaV_buffer_call(lua_State * L)1402 luaV_buffer_call(lua_State *L)
1403 {
1404 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
1405 lua_settop(L, 1);
1406 set_curbuf(b, DOBUF_SPLIT);
1407 return 1;
1408 }
1409
1410 static int
luaV_buffer_index(lua_State * L)1411 luaV_buffer_index(lua_State *L)
1412 {
1413 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
1414 linenr_T n = (linenr_T) lua_tointeger(L, 2);
1415 if (n > 0 && n <= b->b_ml.ml_line_count)
1416 luaV_pushline(L, b, n);
1417 else if (lua_isstring(L, 2))
1418 {
1419 const char *s = lua_tostring(L, 2);
1420 if (strncmp(s, "name", 4) == 0)
1421 lua_pushstring(L, (b->b_sfname == NULL)
1422 ? "" : (char *) b->b_sfname);
1423 else if (strncmp(s, "fname", 5) == 0)
1424 lua_pushstring(L, (b->b_ffname == NULL)
1425 ? "" : (char *) b->b_ffname);
1426 else if (strncmp(s, "number", 6) == 0)
1427 lua_pushinteger(L, b->b_fnum);
1428 // methods
1429 else if (strncmp(s, "insert", 6) == 0
1430 || strncmp(s, "next", 4) == 0
1431 || strncmp(s, "previous", 8) == 0
1432 || strncmp(s, "isvalid", 7) == 0)
1433 {
1434 lua_getmetatable(L, 1);
1435 lua_getfield(L, -1, s);
1436 }
1437 else
1438 lua_pushnil(L);
1439 }
1440 else
1441 lua_pushnil(L);
1442 return 1;
1443 }
1444
1445 static int
luaV_buffer_newindex(lua_State * L)1446 luaV_buffer_newindex(lua_State *L)
1447 {
1448 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1);
1449 linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
1450 #ifdef HAVE_SANDBOX
1451 luaV_checksandbox(L);
1452 #endif
1453 if (n < 1 || n > b->b_ml.ml_line_count)
1454 luaL_error(L, "invalid line number");
1455 if (lua_isnil(L, 3)) // delete line
1456 {
1457 buf_T *buf = curbuf;
1458 curbuf = b;
1459 if (u_savedel(n, 1L) == FAIL)
1460 {
1461 curbuf = buf;
1462 luaL_error(L, "cannot save undo information");
1463 }
1464 else if (ml_delete(n) == FAIL)
1465 {
1466 curbuf = buf;
1467 luaL_error(L, "cannot delete line");
1468 }
1469 else
1470 {
1471 deleted_lines_mark(n, 1L);
1472 if (b == curwin->w_buffer) // fix cursor in current window?
1473 {
1474 if (curwin->w_cursor.lnum >= n)
1475 {
1476 if (curwin->w_cursor.lnum > n)
1477 {
1478 curwin->w_cursor.lnum -= 1;
1479 check_cursor_col();
1480 }
1481 else
1482 check_cursor();
1483 changed_cline_bef_curs();
1484 }
1485 invalidate_botline();
1486 }
1487 }
1488 curbuf = buf;
1489 }
1490 else if (lua_isstring(L, 3)) // update line
1491 {
1492 buf_T *buf = curbuf;
1493 curbuf = b;
1494 if (u_savesub(n) == FAIL)
1495 {
1496 curbuf = buf;
1497 luaL_error(L, "cannot save undo information");
1498 }
1499 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL)
1500 {
1501 curbuf = buf;
1502 luaL_error(L, "cannot replace line");
1503 }
1504 else changed_bytes(n, 0);
1505 curbuf = buf;
1506 if (b == curwin->w_buffer)
1507 check_cursor_col();
1508 }
1509 else
1510 luaL_error(L, "wrong argument to change line");
1511 return 0;
1512 }
1513
1514 static int
luaV_buffer_insert(lua_State * L)1515 luaV_buffer_insert(lua_State *L)
1516 {
1517 luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER);
1518 buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb);
1519 linenr_T last = b->b_ml.ml_line_count;
1520 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
1521 buf_T *buf;
1522 luaL_checktype(L, 2, LUA_TSTRING);
1523 #ifdef HAVE_SANDBOX
1524 luaV_checksandbox(L);
1525 #endif
1526 // fix insertion line
1527 if (n < 0) n = 0;
1528 if (n > last) n = last;
1529 // insert
1530 buf = curbuf;
1531 curbuf = b;
1532 if (u_save(n, n + 1) == FAIL)
1533 {
1534 curbuf = buf;
1535 luaL_error(L, "cannot save undo information");
1536 }
1537 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL)
1538 {
1539 curbuf = buf;
1540 luaL_error(L, "cannot insert line");
1541 }
1542 else
1543 appended_lines_mark(n, 1L);
1544 curbuf = buf;
1545 update_screen(VALID);
1546 return 0;
1547 }
1548
1549 static int
luaV_buffer_next(lua_State * L)1550 luaV_buffer_next(lua_State *L)
1551 {
1552 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
1553 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
1554 luaV_pushbuffer(L, buf->b_next);
1555 return 1;
1556 }
1557
1558 static int
luaV_buffer_previous(lua_State * L)1559 luaV_buffer_previous(lua_State *L)
1560 {
1561 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
1562 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b);
1563 luaV_pushbuffer(L, buf->b_prev);
1564 return 1;
1565 }
1566
1567 static int
luaV_buffer_isvalid(lua_State * L)1568 luaV_buffer_isvalid(lua_State *L)
1569 {
1570 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
1571 luaV_getudata(L, *b);
1572 lua_pushboolean(L, !lua_isnil(L, -1));
1573 return 1;
1574 }
1575
1576 static const luaL_Reg luaV_Buffer_mt[] = {
1577 {"__tostring", luaV_buffer_tostring},
1578 {"__len", luaV_buffer_len},
1579 {"__call", luaV_buffer_call},
1580 {"__index", luaV_buffer_index},
1581 {"__newindex", luaV_buffer_newindex},
1582 {"insert", luaV_buffer_insert},
1583 {"next", luaV_buffer_next},
1584 {"previous", luaV_buffer_previous},
1585 {"isvalid", luaV_buffer_isvalid},
1586 {NULL, NULL}
1587 };
1588
1589
1590 // ======= Window type =======
1591
luaV_newtype(win_T,window,luaV_Window,LUAVIM_WINDOW)1592 luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW)
1593 luaV_pushtype(win_T, window, luaV_Window)
1594 luaV_type_tostring(window, LUAVIM_WINDOW)
1595
1596 static int
1597 luaV_window_call(lua_State *L)
1598 {
1599 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
1600 lua_settop(L, 1);
1601 win_goto(w);
1602 return 1;
1603 }
1604
1605 static int
luaV_window_index(lua_State * L)1606 luaV_window_index(lua_State *L)
1607 {
1608 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
1609 const char *s = luaL_checkstring(L, 2);
1610 if (strncmp(s, "buffer", 6) == 0)
1611 luaV_pushbuffer(L, w->w_buffer);
1612 else if (strncmp(s, "line", 4) == 0)
1613 lua_pushinteger(L, w->w_cursor.lnum);
1614 else if (strncmp(s, "col", 3) == 0)
1615 lua_pushinteger(L, w->w_cursor.col + 1);
1616 else if (strncmp(s, "width", 5) == 0)
1617 lua_pushinteger(L, w->w_width);
1618 else if (strncmp(s, "height", 6) == 0)
1619 lua_pushinteger(L, w->w_height);
1620 // methods
1621 else if (strncmp(s, "next", 4) == 0
1622 || strncmp(s, "previous", 8) == 0
1623 || strncmp(s, "isvalid", 7) == 0)
1624 {
1625 lua_getmetatable(L, 1);
1626 lua_getfield(L, -1, s);
1627 }
1628 else
1629 lua_pushnil(L);
1630 return 1;
1631 }
1632
1633 static int
luaV_window_newindex(lua_State * L)1634 luaV_window_newindex(lua_State *L)
1635 {
1636 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1);
1637 const char *s = luaL_checkstring(L, 2);
1638 int v = luaL_checkinteger(L, 3);
1639 if (strncmp(s, "line", 4) == 0)
1640 {
1641 #ifdef HAVE_SANDBOX
1642 luaV_checksandbox(L);
1643 #endif
1644 if (v < 1 || v > w->w_buffer->b_ml.ml_line_count)
1645 luaL_error(L, "line out of range");
1646 w->w_cursor.lnum = v;
1647 update_screen(VALID);
1648 }
1649 else if (strncmp(s, "col", 3) == 0)
1650 {
1651 #ifdef HAVE_SANDBOX
1652 luaV_checksandbox(L);
1653 #endif
1654 w->w_cursor.col = v - 1;
1655 w->w_set_curswant = TRUE;
1656 update_screen(VALID);
1657 }
1658 else if (strncmp(s, "width", 5) == 0)
1659 {
1660 win_T *win = curwin;
1661 #ifdef FEAT_GUI
1662 need_mouse_correct = TRUE;
1663 #endif
1664 curwin = w;
1665 win_setwidth(v);
1666 curwin = win;
1667 }
1668 else if (strncmp(s, "height", 6) == 0)
1669 {
1670 win_T *win = curwin;
1671 #ifdef FEAT_GUI
1672 need_mouse_correct = TRUE;
1673 #endif
1674 curwin = w;
1675 win_setheight(v);
1676 curwin = win;
1677 }
1678 else
1679 luaL_error(L, "invalid window property: `%s'", s);
1680 return 0;
1681 }
1682
1683 static int
luaV_window_next(lua_State * L)1684 luaV_window_next(lua_State *L)
1685 {
1686 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
1687 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
1688 luaV_pushwindow(L, win->w_next);
1689 return 1;
1690 }
1691
1692 static int
luaV_window_previous(lua_State * L)1693 luaV_window_previous(lua_State *L)
1694 {
1695 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
1696 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w);
1697 luaV_pushwindow(L, win->w_prev);
1698 return 1;
1699 }
1700
1701 static int
luaV_window_isvalid(lua_State * L)1702 luaV_window_isvalid(lua_State *L)
1703 {
1704 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
1705 luaV_getudata(L, *w);
1706 lua_pushboolean(L, !lua_isnil(L, -1));
1707 return 1;
1708 }
1709
1710 static const luaL_Reg luaV_Window_mt[] = {
1711 {"__tostring", luaV_window_tostring},
1712 {"__call", luaV_window_call},
1713 {"__index", luaV_window_index},
1714 {"__newindex", luaV_window_newindex},
1715 {"next", luaV_window_next},
1716 {"previous", luaV_window_previous},
1717 {"isvalid", luaV_window_isvalid},
1718 {NULL, NULL}
1719 };
1720
1721
1722 // ======= Vim module =======
1723
1724 static int
luaV_print(lua_State * L)1725 luaV_print(lua_State *L)
1726 {
1727 int i, n = lua_gettop(L); // nargs
1728 const char *s;
1729 size_t l;
1730 garray_T msg_ga;
1731
1732 ga_init2(&msg_ga, 1, 128);
1733 lua_getglobal(L, "tostring");
1734 for (i = 1; i <= n; i++)
1735 {
1736 lua_pushvalue(L, -1); // tostring
1737 lua_pushvalue(L, i); // arg
1738 lua_call(L, 1, 1);
1739 s = lua_tolstring(L, -1, &l);
1740 if (s == NULL)
1741 return luaL_error(L, "cannot convert to string");
1742 if (i > 1)
1743 ga_append(&msg_ga, ' '); // use space instead of tab
1744 ga_concat_len(&msg_ga, (char_u *)s, l);
1745 lua_pop(L, 1);
1746 }
1747 // Replace any "\n" with "\0"
1748 for (i = 0; i < msg_ga.ga_len; i++)
1749 if (((char *)msg_ga.ga_data)[i] == '\n')
1750 ((char *)msg_ga.ga_data)[i] = '\0';
1751 lua_pushlstring(L, msg_ga.ga_data, msg_ga.ga_len);
1752 if (!got_int)
1753 luaV_msg(L);
1754
1755 ga_clear(&msg_ga);
1756 return 0;
1757 }
1758
1759 static int
luaV_debug(lua_State * L)1760 luaV_debug(lua_State *L)
1761 {
1762 lua_settop(L, 0);
1763 lua_getglobal(L, "vim");
1764 lua_getfield(L, -1, "eval");
1765 lua_remove(L, -2); // vim.eval at position 1
1766 for (;;)
1767 {
1768 const char *input;
1769 size_t l;
1770 lua_pushvalue(L, 1); // vim.eval
1771 lua_pushliteral(L, "input('lua_debug> ')");
1772 lua_call(L, 1, 1); // return string
1773 input = lua_tolstring(L, -1, &l);
1774 if (l == 0 || strcmp(input, "cont") == 0)
1775 return 0;
1776 msg_putchar('\n'); // avoid outputting on input line
1777 if (luaL_loadbuffer(L, input, l, "=(debug command)")
1778 || lua_pcall(L, 0, 0, 0))
1779 luaV_emsg(L);
1780 lua_settop(L, 1); // remove eventual returns, but keep vim.eval
1781 }
1782 }
1783
1784 static dict_T *
luaV_get_var_scope(lua_State * L)1785 luaV_get_var_scope(lua_State *L)
1786 {
1787 const char *scope = luaL_checkstring(L, 1);
1788 dict_T *dict = NULL;
1789
1790 if (STRICMP((char *)scope, "g") == 0)
1791 dict = get_globvar_dict();
1792 else if (STRICMP((char *)scope, "v") == 0)
1793 dict = get_vimvar_dict();
1794 else if (STRICMP((char *)scope, "b") == 0)
1795 dict = curbuf->b_vars;
1796 else if (STRICMP((char *)scope, "w") == 0)
1797 dict = curwin->w_vars;
1798 else if (STRICMP((char *)scope, "t") == 0)
1799 dict = curtab->tp_vars;
1800 else
1801 {
1802 luaL_error(L, "invalid scope %s", scope);
1803 return NULL;
1804 }
1805
1806 return dict;
1807 }
1808
1809 static int
luaV_setvar(lua_State * L)1810 luaV_setvar(lua_State *L)
1811 {
1812 dict_T *dict;
1813 dictitem_T *di;
1814 size_t len;
1815 char *name;
1816 int del;
1817 char *error = NULL;
1818
1819 name = (char *)luaL_checklstring(L, 3, &len);
1820 del = (lua_gettop(L) < 4) || lua_isnil(L, 4);
1821
1822 dict = luaV_get_var_scope(L);
1823 if (dict == NULL)
1824 return 0;
1825
1826 di = dict_find(dict, (char_u *)name, (int)len);
1827 if (di != NULL)
1828 {
1829 if (di->di_flags & DI_FLAGS_RO)
1830 error = "variable is read-only";
1831 else if (di->di_flags & DI_FLAGS_LOCK)
1832 error = "variable is locked";
1833 else if (del && di->di_flags & DI_FLAGS_FIX)
1834 error = "variable is fixed";
1835 if (error != NULL)
1836 return luaL_error(L, error);
1837 }
1838 else if (dict->dv_lock)
1839 return luaL_error(L, "Dictionary is locked");
1840
1841 if (del)
1842 {
1843 // Delete the key
1844 if (di == NULL)
1845 // Doesn't exist, nothing to do
1846 return 0;
1847 else
1848 // Delete the entry
1849 dictitem_remove(dict, di);
1850 }
1851 else
1852 {
1853 // Update the key
1854 typval_T tv;
1855
1856 // Convert the lua value to a Vim script type in the temporary variable
1857 lua_pushvalue(L, 4);
1858 if (luaV_totypval(L, -1, &tv) == FAIL)
1859 return luaL_error(L, "Couldn't convert lua value");
1860
1861 if (di == NULL)
1862 {
1863 // Need to create an entry
1864 di = dictitem_alloc((char_u *)name);
1865 if (di == NULL)
1866 {
1867 clear_tv(&tv);
1868 return 0;
1869 }
1870 // Update the value
1871 copy_tv(&tv, &di->di_tv);
1872 if (dict_add(dict, di) == FAIL)
1873 {
1874 dictitem_free(di);
1875 clear_tv(&tv);
1876 return luaL_error(L, "Couldn't add to dictionary");
1877 }
1878 }
1879 else
1880 {
1881 // Clear the old value
1882 clear_tv(&di->di_tv);
1883 // Update the value
1884 copy_tv(&tv, &di->di_tv);
1885 }
1886
1887 // Clear the temporary variable
1888 clear_tv(&tv);
1889 }
1890
1891 return 0;
1892 }
1893
1894 static int
luaV_getvar(lua_State * L)1895 luaV_getvar(lua_State *L)
1896 {
1897 dict_T *dict = luaV_get_var_scope(L);
1898 size_t len;
1899 const char *name = luaL_checklstring(L, 3, &len);
1900 dictitem_T *di = dict_find(dict, (char_u *)name, (int)len);
1901
1902 if (di == NULL)
1903 return 0; // nil
1904
1905 luaV_pushtypval(L, &di->di_tv);
1906 return 1;
1907 }
1908
1909 static int
luaV_command(lua_State * L)1910 luaV_command(lua_State *L)
1911 {
1912 char_u *s = vim_strsave((char_u *)luaL_checkstring(L, 1));
1913
1914 execute_cmds_from_string(s);
1915 vim_free(s);
1916 update_screen(VALID);
1917 return 0;
1918 }
1919
1920 static int
luaV_eval(lua_State * L)1921 luaV_eval(lua_State *L)
1922 {
1923 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL);
1924
1925 if (tv == NULL) luaL_error(L, "invalid expression");
1926 luaV_pushtypval(L, tv);
1927 free_tv(tv);
1928 return 1;
1929 }
1930
1931 static int
luaV_beep(lua_State * L UNUSED)1932 luaV_beep(lua_State *L UNUSED)
1933 {
1934 vim_beep(BO_LANG);
1935 return 0;
1936 }
1937
1938 static int
luaV_line(lua_State * L)1939 luaV_line(lua_State *L)
1940 {
1941 luaV_pushline(L, curbuf, curwin->w_cursor.lnum);
1942 return 1;
1943 }
1944
1945 static int
luaV_list(lua_State * L)1946 luaV_list(lua_State *L)
1947 {
1948 list_T *l;
1949 int initarg = !lua_isnoneornil(L, 1);
1950
1951 if (initarg && lua_type(L, 1) != LUA_TTABLE)
1952 luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1953 l = list_alloc();
1954 if (l == NULL)
1955 lua_pushnil(L);
1956 else
1957 {
1958 luaV_newlist(L, l);
1959 if (initarg) // traverse table to init list
1960 {
1961 int notnil, i = 0;
1962 typval_T v;
1963 do
1964 {
1965 lua_rawgeti(L, 1, ++i);
1966 notnil = !lua_isnil(L, -1);
1967 if (notnil)
1968 {
1969 luaV_checktypval(L, -1, &v, "vim.list");
1970 list_append_tv(l, &v);
1971 clear_tv(&v);
1972 }
1973 lua_pop(L, 1); // value
1974 } while (notnil);
1975 }
1976 }
1977 return 1;
1978 }
1979
1980 static int
luaV_dict(lua_State * L)1981 luaV_dict(lua_State *L)
1982 {
1983 dict_T *d;
1984 int initarg = !lua_isnoneornil(L, 1);
1985
1986 if (initarg && lua_type(L, 1) != LUA_TTABLE)
1987 luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
1988 d = dict_alloc();
1989 if (d == NULL)
1990 lua_pushnil(L);
1991 else
1992 {
1993 luaV_newdict(L, d);
1994 if (initarg) // traverse table to init dict
1995 {
1996 lua_pushnil(L);
1997 while (lua_next(L, 1))
1998 {
1999 char_u *key;
2000 dictitem_T *di;
2001 typval_T v;
2002
2003 lua_pushvalue(L, -2); // dup key in case it's a number
2004 key = (char_u *) lua_tostring(L, -1);
2005 if (key == NULL)
2006 {
2007 lua_pushnil(L);
2008 return 1;
2009 }
2010 if (*key == NUL)
2011 luaL_error(L, "table has empty key");
2012 luaV_checktypval(L, -2, &v, "vim.dict"); // value
2013 di = dictitem_alloc(key);
2014 if (di == NULL || dict_add(d, di) == FAIL)
2015 {
2016 vim_free(di);
2017 lua_pushnil(L);
2018 return 1;
2019 }
2020 di->di_tv = v;
2021 lua_pop(L, 2); // key copy and value
2022 }
2023 }
2024 }
2025 return 1;
2026 }
2027
2028 static int
luaV_blob(lua_State * L)2029 luaV_blob(lua_State *L)
2030 {
2031 blob_T *b;
2032 int initarg = !lua_isnoneornil(L, 1);
2033
2034 if (initarg && !lua_isstring(L, 1))
2035 luaL_error(L, "string expected, got %s", luaL_typename(L, 1));
2036 b = blob_alloc();
2037 if (b == NULL)
2038 lua_pushnil(L);
2039 else
2040 {
2041 luaV_newblob(L, b);
2042 if (initarg)
2043 {
2044 size_t i, l = 0;
2045 const char *s = lua_tolstring(L, 1, &l);
2046
2047 if (ga_grow(&b->bv_ga, (int)l) == OK)
2048 for (i = 0; i < l; ++i)
2049 ga_append(&b->bv_ga, s[i]);
2050 }
2051 }
2052 return 1;
2053 }
2054
2055 static int
luaV_funcref(lua_State * L)2056 luaV_funcref(lua_State *L)
2057 {
2058 const char *name = luaL_checkstring(L, 1);
2059 // note: not checking if function exists (needs function_exists)
2060 if (name == NULL || *name == NUL || VIM_ISDIGIT(*name))
2061 luaL_error(L, "invalid function name: %s", name);
2062 luaV_newfuncref(L, (char_u *) name);
2063 return 1;
2064 }
2065
2066 static int
luaV_buffer(lua_State * L)2067 luaV_buffer(lua_State *L)
2068 {
2069 buf_T *buf;
2070 if (lua_isstring(L, 1)) // get by number or name?
2071 {
2072 if (lua_isnumber(L, 1)) // by number?
2073 {
2074 int n = lua_tointeger(L, 1);
2075 FOR_ALL_BUFFERS(buf)
2076 if (buf->b_fnum == n) break;
2077 }
2078 else // by name
2079 {
2080 size_t l;
2081 const char *s = lua_tolstring(L, 1, &l);
2082 FOR_ALL_BUFFERS(buf)
2083 {
2084 if (buf->b_ffname == NULL || buf->b_sfname == NULL)
2085 {
2086 if (l == 0) break;
2087 }
2088 else if (strncmp(s, (char *)buf->b_ffname, l) == 0
2089 || strncmp(s, (char *)buf->b_sfname, l) == 0)
2090 break;
2091 }
2092 }
2093 }
2094 else
2095 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; // first buffer?
2096 luaV_pushbuffer(L, buf);
2097 return 1;
2098 }
2099
2100 static int
luaV_window(lua_State * L)2101 luaV_window(lua_State *L)
2102 {
2103 win_T *win;
2104 if (lua_isnumber(L, 1)) // get by number?
2105 {
2106 int n = lua_tointeger(L, 1);
2107 for (win = firstwin; win != NULL; win = win->w_next, n--)
2108 if (n == 1) break;
2109 }
2110 else
2111 win = (lua_toboolean(L, 1)) ? firstwin : curwin; // first window?
2112 luaV_pushwindow(L, win);
2113 return 1;
2114 }
2115
2116 static int
luaV_open(lua_State * L)2117 luaV_open(lua_State *L)
2118 {
2119 char_u *s = NULL;
2120 #ifdef HAVE_SANDBOX
2121 luaV_checksandbox(L);
2122 #endif
2123 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1);
2124 luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED));
2125 return 1;
2126 }
2127
2128 static int
luaV_type(lua_State * L)2129 luaV_type(lua_State *L)
2130 {
2131 luaL_checkany(L, 1);
2132 if (lua_type(L, 1) == LUA_TUSERDATA) // check vim udata?
2133 {
2134 lua_settop(L, 1);
2135 if (lua_getmetatable(L, 1))
2136 {
2137 luaV_getfield(L, LUAVIM_LIST);
2138 if (lua_rawequal(L, -1, 2))
2139 {
2140 lua_pushstring(L, "list");
2141 return 1;
2142 }
2143 luaV_getfield(L, LUAVIM_DICT);
2144 if (lua_rawequal(L, -1, 2))
2145 {
2146 lua_pushstring(L, "dict");
2147 return 1;
2148 }
2149 luaV_getfield(L, LUAVIM_BLOB);
2150 if (lua_rawequal(L, -1, 2))
2151 {
2152 lua_pushstring(L, "blob");
2153 return 1;
2154 }
2155 luaV_getfield(L, LUAVIM_FUNCREF);
2156 if (lua_rawequal(L, -1, 2))
2157 {
2158 lua_pushstring(L, "funcref");
2159 return 1;
2160 }
2161 luaV_getfield(L, LUAVIM_BUFFER);
2162 if (lua_rawequal(L, -1, 2))
2163 {
2164 lua_pushstring(L, "buffer");
2165 return 1;
2166 }
2167 luaV_getfield(L, LUAVIM_WINDOW);
2168 if (lua_rawequal(L, -1, 2))
2169 {
2170 lua_pushstring(L, "window");
2171 return 1;
2172 }
2173 }
2174 }
2175 lua_pushstring(L, luaL_typename(L, 1)); // fallback
2176 return 1;
2177 }
2178
2179 static int
luaV_call(lua_State * L)2180 luaV_call(lua_State *L)
2181 {
2182 int argc = lua_gettop(L) - 1;
2183 size_t funcname_len;
2184 char_u *funcname;
2185 char *error = NULL;
2186 typval_T rettv;
2187 typval_T argv[MAX_FUNC_ARGS + 1];
2188 int i = 0;
2189
2190 if (argc > MAX_FUNC_ARGS)
2191 return luaL_error(L, "Function called with too many arguments");
2192
2193 funcname = (char_u *)luaL_checklstring(L, 1, &funcname_len);
2194
2195 for (; i < argc; i++)
2196 {
2197 if (luaV_totypval(L, i + 2, &argv[i]) == FAIL)
2198 {
2199 error = "lua: cannot convert value";
2200 goto free_vim_args;
2201 }
2202 }
2203
2204 argv[argc].v_type = VAR_UNKNOWN;
2205
2206 if (call_vim_function(funcname, argc, argv, &rettv) == FAIL)
2207 {
2208 error = "lua: call_vim_function failed";
2209 goto free_vim_args;
2210 }
2211
2212 luaV_pushtypval(L, &rettv);
2213 clear_tv(&rettv);
2214
2215 free_vim_args:
2216 while (i > 0)
2217 clear_tv(&argv[--i]);
2218
2219 if (error == NULL)
2220 return 1;
2221 else
2222 return luaL_error(L, error);
2223 }
2224
2225 /*
2226 * Return the Vim version as a Lua table
2227 */
2228 static int
luaV_version(lua_State * L)2229 luaV_version(lua_State *L)
2230 {
2231 lua_newtable(L);
2232 lua_pushstring(L, "major");
2233 lua_pushinteger(L, VIM_VERSION_MAJOR);
2234 lua_settable(L, -3);
2235 lua_pushstring(L, "minor");
2236 lua_pushinteger(L, VIM_VERSION_MINOR);
2237 lua_settable(L, -3);
2238 lua_pushstring(L, "patch");
2239 lua_pushinteger(L, highest_patch());
2240 lua_settable(L, -3);
2241 return 1;
2242 }
2243
2244 static const luaL_Reg luaV_module[] = {
2245 {"command", luaV_command},
2246 {"eval", luaV_eval},
2247 {"beep", luaV_beep},
2248 {"line", luaV_line},
2249 {"list", luaV_list},
2250 {"dict", luaV_dict},
2251 {"blob", luaV_blob},
2252 {"funcref", luaV_funcref},
2253 {"buffer", luaV_buffer},
2254 {"window", luaV_window},
2255 {"open", luaV_open},
2256 {"type", luaV_type},
2257 {"call", luaV_call},
2258 {"_getvar", luaV_getvar},
2259 {"_setvar", luaV_setvar},
2260 {"version", luaV_version},
2261 {"lua_version", NULL},
2262 {NULL, NULL}
2263 };
2264
2265 /*
2266 * for freeing list, dict, buffer and window objects; lightuserdata as arg
2267 */
2268 static int
luaV_free(lua_State * L)2269 luaV_free(lua_State *L)
2270 {
2271 lua_pushnil(L);
2272 luaV_setudata(L, lua_touserdata(L, 1));
2273 return 0;
2274 }
2275
2276 static int
luaV_luaeval(lua_State * L)2277 luaV_luaeval(lua_State *L)
2278 {
2279 luaL_Buffer b;
2280 size_t l;
2281 const char *str = lua_tolstring(L, 1, &l);
2282 typval_T *arg = (typval_T *) lua_touserdata(L, 2);
2283 typval_T *rettv = (typval_T *) lua_touserdata(L, 3);
2284 luaL_buffinit(L, &b);
2285 luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1);
2286 luaL_addlstring(&b, str, l);
2287 luaL_pushresult(&b);
2288 str = lua_tolstring(L, -1, &l);
2289 if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) // compile error?
2290 {
2291 luaV_emsg(L);
2292 return 0;
2293 }
2294 luaV_pushtypval(L, arg);
2295 if (lua_pcall(L, 1, 1, 0)) // running error?
2296 {
2297 luaV_emsg(L);
2298 return 0;
2299 }
2300 if (luaV_totypval(L, -1, rettv) == FAIL)
2301 emsg("luaeval: cannot convert value");
2302 return 0;
2303 }
2304
2305 static int
luaV_setref(lua_State * L)2306 luaV_setref(lua_State *L)
2307 {
2308 int copyID = lua_tointeger(L, 1);
2309 int abort = FALSE;
2310
2311 luaV_getfield(L, LUAVIM_LIST);
2312 luaV_getfield(L, LUAVIM_DICT);
2313 luaV_getfield(L, LUAVIM_FUNCREF);
2314 lua_pushnil(L);
2315 // traverse cache table
2316 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0)
2317 {
2318 lua_getmetatable(L, -1);
2319 if (lua_rawequal(L, -1, 2)) // list?
2320 {
2321 list_T *l = (list_T *)lua_touserdata(L, 5); // key
2322
2323 abort = set_ref_in_list(l, copyID);
2324 }
2325 else if (lua_rawequal(L, -1, 3)) // dict?
2326 {
2327 dict_T *d = (dict_T *)lua_touserdata(L, 5); // key
2328
2329 abort = set_ref_in_dict(d, copyID);
2330 }
2331 else if (lua_rawequal(L, -1, 4)) // funcref?
2332 {
2333 luaV_Funcref *f = (luaV_Funcref *)lua_touserdata(L, 5); // key
2334
2335 abort = set_ref_in_dict(f->self, copyID);
2336 }
2337 lua_pop(L, 2); // metatable and value
2338 }
2339 lua_pushinteger(L, abort);
2340 return 1;
2341 }
2342
2343 static int
luaV_pushversion(lua_State * L)2344 luaV_pushversion(lua_State *L)
2345 {
2346 int major = 0;
2347 int minor = 0;
2348 int patch = 0;
2349 char s[16];
2350
2351 sscanf(LUAVIM_VERSION, "Lua %d.%d.%d", &major, &minor, &patch);
2352 vim_snprintf(s, sizeof(s), "%d.%d.%d", major, minor, patch);
2353 lua_pushstring(L, s);
2354 return 0;
2355 }
2356
2357 #define LUA_VIM_FN_CODE \
2358 "vim.fn = setmetatable({}, {\n"\
2359 " __index = function (t, key)\n"\
2360 " local function _fn(...)\n"\
2361 " return vim.call(key, ...)\n"\
2362 " end\n"\
2363 " t[key] = _fn\n"\
2364 " return _fn\n"\
2365 " end\n"\
2366 " })"
2367
2368 #define LUA_VIM_UPDATE_PACKAGE_PATHS \
2369 "local last_vim_paths = {}\n"\
2370 "vim._update_package_paths = function ()\n"\
2371 " local cur_vim_paths = {}\n"\
2372 " local function split(s, delimiter)\n"\
2373 " result = {}\n"\
2374 " for match in (s..delimiter):gmatch(\"(.-)\"..delimiter) do\n"\
2375 " table.insert(result, match)\n"\
2376 " end\n"\
2377 " return result\n"\
2378 " end\n"\
2379 " local rtps = split(vim.eval('&runtimepath'), ',')\n"\
2380 " local sep = package.config:sub(1, 1)\n"\
2381 " for _, key in ipairs({'path', 'cpath'}) do\n"\
2382 " local orig_str = package[key] .. ';'\n"\
2383 " local pathtrails_ordered = {}\n"\
2384 " -- Note: ignores trailing item without trailing `;`. Not using something\n"\
2385 " -- simpler in order to preserve empty items (stand for default path).\n"\
2386 " local orig = {}\n"\
2387 " for s in orig_str:gmatch('[^;]*;') do\n"\
2388 " s = s:sub(1, -2) -- Strip trailing semicolon\n"\
2389 " orig[#orig + 1] = s\n"\
2390 " end\n"\
2391 " if key == 'path' then\n"\
2392 " -- /?.lua and /?/init.lua\n"\
2393 " pathtrails_ordered = {sep .. '?.lua', sep .. '?' .. sep .. 'init.lua'}\n"\
2394 " else\n"\
2395 " local pathtrails = {}\n"\
2396 " for _, s in ipairs(orig) do\n"\
2397 " -- Find out path patterns. pathtrail should contain something like\n"\
2398 " -- /?.so, \?.dll. This allows not to bother determining what correct\n"\
2399 " -- suffixes are.\n"\
2400 " local pathtrail = s:match('[/\\\\][^/\\\\]*%?.*$')\n"\
2401 " if pathtrail and not pathtrails[pathtrail] then\n"\
2402 " pathtrails[pathtrail] = true\n"\
2403 " pathtrails_ordered[#pathtrails_ordered + 1] = pathtrail\n"\
2404 " end\n"\
2405 " end\n"\
2406 " end\n"\
2407 " local new = {}\n"\
2408 " for _, rtp in ipairs(rtps) do\n"\
2409 " if not rtp:match(';') then\n"\
2410 " for _, pathtrail in pairs(pathtrails_ordered) do\n"\
2411 " local new_path = rtp .. sep .. 'lua' .. pathtrail\n"\
2412 " -- Always keep paths from &runtimepath at the start:\n"\
2413 " -- append them here disregarding orig possibly containing one of them.\n"\
2414 " new[#new + 1] = new_path\n"\
2415 " cur_vim_paths[new_path] = true\n"\
2416 " end\n"\
2417 " end\n"\
2418 " end\n"\
2419 " for _, orig_path in ipairs(orig) do\n"\
2420 " -- Handle removing obsolete paths originating from &runtimepath: such\n"\
2421 " -- paths either belong to cur_nvim_paths and were already added above or\n"\
2422 " -- to last_nvim_paths and should not be added at all if corresponding\n"\
2423 " -- entry was removed from &runtimepath list.\n"\
2424 " if not (cur_vim_paths[orig_path] or last_vim_paths[orig_path]) then\n"\
2425 " new[#new + 1] = orig_path\n"\
2426 " end\n"\
2427 " end\n"\
2428 " package[key] = table.concat(new, ';')\n"\
2429 " end\n"\
2430 " last_vim_paths = cur_vim_paths\n"\
2431 "end"
2432
2433 #define LUA_VIM_SETUP_VARIABLE_DICTS \
2434 "do\n"\
2435 " local function make_dict_accessor(scope)\n"\
2436 " local mt = {}\n"\
2437 " function mt:__newindex(k, v)\n"\
2438 " return vim._setvar(scope, 0, k, v)\n"\
2439 " end\n"\
2440 " function mt:__index(k)\n"\
2441 " return vim._getvar(scope, 0, k)\n"\
2442 " end\n"\
2443 " return setmetatable({}, mt)\n"\
2444 " end\n"\
2445 " vim.g = make_dict_accessor('g')\n"\
2446 " vim.v = make_dict_accessor('v')\n"\
2447 " vim.b = make_dict_accessor('b')\n"\
2448 " vim.w = make_dict_accessor('w')\n"\
2449 " vim.t = make_dict_accessor('t')\n"\
2450 "end"
2451
2452 static int
luaopen_vim(lua_State * L)2453 luaopen_vim(lua_State *L)
2454 {
2455 // set cache table
2456 lua_newtable(L);
2457 lua_newtable(L);
2458 lua_pushstring(L, "v");
2459 lua_setfield(L, -2, "__mode");
2460 lua_setmetatable(L, -2); // cache is weak-valued
2461 // print
2462 lua_pushcfunction(L, luaV_print);
2463 lua_setglobal(L, "print");
2464 // debug.debug
2465 lua_getglobal(L, "debug");
2466 lua_pushcfunction(L, luaV_debug);
2467 lua_setfield(L, -2, "debug");
2468 lua_pop(L, 1);
2469 // free
2470 lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
2471 lua_pushvalue(L, 1); // cache table
2472 lua_pushcclosure(L, luaV_free, 1);
2473 lua_rawset(L, LUA_REGISTRYINDEX);
2474 // luaeval
2475 lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL);
2476 lua_pushvalue(L, 1); // cache table
2477 lua_pushcclosure(L, luaV_luaeval, 1);
2478 lua_rawset(L, LUA_REGISTRYINDEX);
2479 // setref
2480 lua_pushlightuserdata(L, (void *) LUAVIM_SETREF);
2481 lua_pushvalue(L, 1); // cache table
2482 lua_pushcclosure(L, luaV_setref, 1);
2483 lua_rawset(L, LUA_REGISTRYINDEX);
2484 // register
2485 luaV_newmetatable(L, LUAVIM_LIST);
2486 lua_pushvalue(L, 1);
2487 luaV_openlib(L, luaV_List_mt, 1);
2488 luaV_newmetatable(L, LUAVIM_DICT);
2489 lua_pushvalue(L, 1);
2490 luaV_openlib(L, luaV_Dict_mt, 1);
2491 luaV_newmetatable(L, LUAVIM_BLOB);
2492 lua_pushvalue(L, 1);
2493 luaV_openlib(L, luaV_Blob_mt, 1);
2494 luaV_newmetatable(L, LUAVIM_FUNCREF);
2495 lua_pushvalue(L, 1);
2496 luaV_openlib(L, luaV_Funcref_mt, 1);
2497 luaV_newmetatable(L, LUAVIM_BUFFER);
2498 lua_pushvalue(L, 1); // cache table
2499 luaV_openlib(L, luaV_Buffer_mt, 1);
2500 luaV_newmetatable(L, LUAVIM_WINDOW);
2501 lua_pushvalue(L, 1); // cache table
2502 luaV_openlib(L, luaV_Window_mt, 1);
2503 lua_newtable(L); // vim table
2504 lua_pushvalue(L, 1); // cache table
2505 luaV_openlib(L, luaV_module, 1);
2506 luaV_pushversion(L);
2507 lua_setfield(L, -2, "lua_version");
2508 lua_setglobal(L, LUAVIM_NAME);
2509 // custom code
2510 (void)luaL_dostring(L, LUA_VIM_FN_CODE);
2511 (void)luaL_dostring(L, LUA_VIM_UPDATE_PACKAGE_PATHS);
2512 (void)luaL_dostring(L, LUA_VIM_SETUP_VARIABLE_DICTS);
2513
2514 lua_getglobal(L, "vim");
2515 lua_getfield(L, -1, "_update_package_paths");
2516
2517 if (lua_pcall(L, 0, 0, 0))
2518 luaV_emsg(L);
2519
2520 return 0;
2521 }
2522
2523 static lua_State *
luaV_newstate(void)2524 luaV_newstate(void)
2525 {
2526 lua_State *L = luaL_newstate();
2527 luaL_openlibs(L); // core libs
2528 lua_pushcfunction(L, luaopen_vim); // vim
2529 lua_call(L, 0, 0);
2530 return L;
2531 }
2532
2533 static void
luaV_setrange(lua_State * L,int line1,int line2)2534 luaV_setrange(lua_State *L, int line1, int line2)
2535 {
2536 lua_getglobal(L, LUAVIM_NAME);
2537 lua_pushinteger(L, line1);
2538 lua_setfield(L, -2, "firstline");
2539 lua_pushinteger(L, line2);
2540 lua_setfield(L, -2, "lastline");
2541 lua_pop(L, 1); // vim table
2542 }
2543
2544
2545 // ======= Interface =======
2546
2547 static lua_State *L = NULL;
2548
2549 static int
lua_isopen(void)2550 lua_isopen(void)
2551 {
2552 return L != NULL;
2553 }
2554
2555 static int
lua_init(void)2556 lua_init(void)
2557 {
2558 if (!lua_isopen())
2559 {
2560 #ifdef DYNAMIC_LUA
2561 if (!lua_enabled(TRUE))
2562 {
2563 emsg(_("Lua library cannot be loaded."));
2564 return FAIL;
2565 }
2566 #endif
2567 L = luaV_newstate();
2568 }
2569 return OK;
2570 }
2571
2572 void
lua_end(void)2573 lua_end(void)
2574 {
2575 if (lua_isopen())
2576 {
2577 lua_close(L);
2578 L = NULL;
2579 }
2580 }
2581
2582 /*
2583 * ex commands
2584 */
2585 void
ex_lua(exarg_T * eap)2586 ex_lua(exarg_T *eap)
2587 {
2588 char *script = (char *)script_get(eap, eap->arg);
2589
2590 if (!eap->skip && lua_init() == OK)
2591 {
2592 char *s = script != NULL ? script : (char *)eap->arg;
2593
2594 luaV_setrange(L, eap->line1, eap->line2);
2595 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME)
2596 || lua_pcall(L, 0, 0, 0))
2597 luaV_emsg(L);
2598 }
2599 if (script != NULL)
2600 vim_free(script);
2601 }
2602
2603 void
ex_luado(exarg_T * eap)2604 ex_luado(exarg_T *eap)
2605 {
2606 linenr_T l;
2607 const char *s = (const char *) eap->arg;
2608 luaL_Buffer b;
2609 size_t len;
2610 buf_T *was_curbuf = curbuf;
2611
2612 if (lua_init() == FAIL) return;
2613 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
2614 {
2615 emsg(_("cannot save undo information"));
2616 return;
2617 }
2618 luaV_setrange(L, eap->line1, eap->line2);
2619 luaL_buffinit(L, &b);
2620 luaL_addlstring(&b, "return function(line, linenr) ", 30); // header
2621 luaL_addlstring(&b, s, strlen(s));
2622 luaL_addlstring(&b, " end", 4); // footer
2623 luaL_pushresult(&b);
2624 s = lua_tolstring(L, -1, &len);
2625 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME))
2626 {
2627 luaV_emsg(L);
2628 lua_pop(L, 1); // function body
2629 return;
2630 }
2631 lua_call(L, 0, 1);
2632 lua_replace(L, -2); // function -> body
2633 for (l = eap->line1; l <= eap->line2; l++)
2634 {
2635 // Check the line number, the command may have deleted lines.
2636 if (l > curbuf->b_ml.ml_line_count)
2637 break;
2638
2639 lua_pushvalue(L, -1); // function
2640 luaV_pushline(L, curbuf, l); // current line as arg
2641 lua_pushinteger(L, l); // current line number as arg
2642 if (lua_pcall(L, 2, 1, 0))
2643 {
2644 luaV_emsg(L);
2645 break;
2646 }
2647 // Catch the command switching to another buffer.
2648 if (curbuf != was_curbuf)
2649 break;
2650 if (lua_isstring(L, -1)) // update line?
2651 {
2652 #ifdef HAVE_SANDBOX
2653 luaV_checksandbox(L);
2654 #endif
2655 ml_replace(l, luaV_toline(L, -1), TRUE);
2656 changed_bytes(l, 0);
2657 lua_pop(L, 1); // result from luaV_toline
2658 }
2659 lua_pop(L, 1); // line
2660 }
2661 lua_pop(L, 1); // function
2662 check_cursor();
2663 update_screen(NOT_VALID);
2664 }
2665
2666 void
ex_luafile(exarg_T * eap)2667 ex_luafile(exarg_T *eap)
2668 {
2669 if (lua_init() == FAIL)
2670 return;
2671 if (!eap->skip)
2672 {
2673 luaV_setrange(L, eap->line1, eap->line2);
2674 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0))
2675 luaV_emsg(L);
2676 }
2677 }
2678
2679 #define luaV_freetype(typ,tname) \
2680 void \
2681 lua_##tname##_free(typ *o) \
2682 { \
2683 if (!lua_isopen()) return; \
2684 luaV_getfield(L, LUAVIM_FREE); \
2685 lua_pushlightuserdata(L, (void *) o); \
2686 lua_call(L, 1, 0); \
2687 }
2688
luaV_freetype(buf_T,buffer)2689 luaV_freetype(buf_T, buffer)
2690 luaV_freetype(win_T, window)
2691
2692 void
2693 do_luaeval(char_u *str, typval_T *arg, typval_T *rettv)
2694 {
2695 lua_init();
2696 luaV_getfield(L, LUAVIM_LUAEVAL);
2697 lua_pushstring(L, (char *) str);
2698 lua_pushlightuserdata(L, (void *) arg);
2699 lua_pushlightuserdata(L, (void *) rettv);
2700 lua_call(L, 3, 0);
2701 }
2702
2703 int
set_ref_in_lua(int copyID)2704 set_ref_in_lua(int copyID)
2705 {
2706 int aborted = 0;
2707
2708 if (lua_isopen())
2709 {
2710 luaV_getfield(L, LUAVIM_SETREF);
2711 // call the function with 1 arg, getting 1 result back
2712 lua_pushinteger(L, copyID);
2713 lua_call(L, 1, 1);
2714 // get the result
2715 aborted = lua_tointeger(L, -1);
2716 // pop result off the stack
2717 lua_pop(L, 1);
2718 }
2719 return aborted;
2720 }
2721
2722 void
update_package_paths_in_lua()2723 update_package_paths_in_lua()
2724 {
2725 if (lua_isopen())
2726 {
2727 lua_getglobal(L, "vim");
2728 lua_getfield(L, -1, "_update_package_paths");
2729
2730 if (lua_pcall(L, 0, 0, 0))
2731 luaV_emsg(L);
2732 }
2733 }
2734
2735 /*
2736 * Native C function callback
2737 */
2738 static int
luaV_call_lua_func(int argcount,typval_T * argvars,typval_T * rettv,void * state)2739 luaV_call_lua_func(
2740 int argcount,
2741 typval_T *argvars,
2742 typval_T *rettv,
2743 void *state)
2744 {
2745 int i;
2746 int luaargcount = argcount;
2747 luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
2748 lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
2749
2750 if (funcstate->lua_tableref != LUA_NOREF)
2751 {
2752 // First arg for metatable __call method is a table
2753 luaargcount += 1;
2754 lua_rawgeti(funcstate->L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
2755 }
2756
2757 for (i = 0; i < argcount; ++i)
2758 luaV_pushtypval(funcstate->L, &argvars[i]);
2759
2760 if (lua_pcall(funcstate->L, luaargcount, 1, 0))
2761 {
2762 luaV_emsg(funcstate->L);
2763 return FCERR_OTHER;
2764 }
2765
2766 luaV_checktypval(funcstate->L, -1, rettv, "get return value");
2767 return FCERR_NONE;
2768 }
2769
2770 /*
2771 * Free up any lua references held by the func state.
2772 */
2773 static void
luaV_call_lua_func_free(void * state)2774 luaV_call_lua_func_free(void *state)
2775 {
2776 luaV_CFuncState *funcstate = (luaV_CFuncState*)state;
2777 luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_funcref);
2778 funcstate->L = NULL;
2779 if (funcstate->lua_tableref != LUA_NOREF)
2780 luaL_unref(L, LUA_REGISTRYINDEX, funcstate->lua_tableref);
2781 VIM_CLEAR(funcstate);
2782 }
2783
2784 #endif
2785