xref: /vim-8.2.3635/src/if_lua.c (revision 0ee8df9c)
1 /* vi:set ts=8 sts=4 sw=4:
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 <stdio.h>
13 #include <string.h>
14 #include <lua.h>
15 #include <lualib.h>
16 #include <lauxlib.h>
17 #include "vim.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 
26 typedef buf_T *luaV_Buffer;
27 typedef win_T *luaV_Window;
28 typedef void (*msgfunc_T)(char_u *);
29 
30 static const char LUAVIM_BUFFER[] = "buffer";
31 static const char LUAVIM_WINDOW[] = "window";
32 static const char LUAVIM_FREE[] = "luaV_free";
33 
34 #define luaV_getfield(L, s) \
35     lua_pushlightuserdata((L), (void *)(s)); \
36     lua_rawget((L), LUA_REGISTRYINDEX)
37 #define luaV_checksandbox(L) \
38     if (sandbox) luaL_error((L), "not allowed in sandbox")
39 #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
40 #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
41 
42 
43 #ifdef DYNAMIC_LUA
44 
45 #ifndef WIN3264
46 # include <dlfcn.h>
47 # define HANDLE void*
48 # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
49 # define symbol_from_dll dlsym
50 # define close_dll dlclose
51 #else
52 # define load_dll LoadLibrary
53 # define symbol_from_dll GetProcAddress
54 # define close_dll FreeLibrary
55 #endif
56 
57 /* lauxlib */
58 #define luaL_register dll_luaL_register
59 #define luaL_typerror dll_luaL_typerror
60 #define luaL_checklstring dll_luaL_checklstring
61 #define luaL_checkinteger dll_luaL_checkinteger
62 #define luaL_optinteger dll_luaL_optinteger
63 #define luaL_checktype dll_luaL_checktype
64 #define luaL_error dll_luaL_error
65 #define luaL_loadfile dll_luaL_loadfile
66 #define luaL_loadbuffer dll_luaL_loadbuffer
67 #define luaL_newstate dll_luaL_newstate
68 #define luaL_buffinit dll_luaL_buffinit
69 #define luaL_prepbuffer dll_luaL_prepbuffer
70 #define luaL_addlstring dll_luaL_addlstring
71 #define luaL_pushresult dll_luaL_pushresult
72 /* lua */
73 #define lua_close dll_lua_close
74 #define lua_gettop dll_lua_gettop
75 #define lua_settop dll_lua_settop
76 #define lua_pushvalue dll_lua_pushvalue
77 #define lua_replace dll_lua_replace
78 #define lua_isnumber dll_lua_isnumber
79 #define lua_isstring dll_lua_isstring
80 #define lua_type dll_lua_type
81 #define lua_rawequal dll_lua_rawequal
82 #define lua_tonumber dll_lua_tonumber
83 #define lua_tointeger dll_lua_tointeger
84 #define lua_toboolean dll_lua_toboolean
85 #define lua_tolstring dll_lua_tolstring
86 #define lua_touserdata dll_lua_touserdata
87 #define lua_pushnil dll_lua_pushnil
88 #define lua_pushnumber dll_lua_pushnumber
89 #define lua_pushinteger dll_lua_pushinteger
90 #define lua_pushlstring dll_lua_pushlstring
91 #define lua_pushstring dll_lua_pushstring
92 #define lua_pushfstring dll_lua_pushfstring
93 #define lua_pushcclosure dll_lua_pushcclosure
94 #define lua_pushboolean dll_lua_pushboolean
95 #define lua_pushlightuserdata dll_lua_pushlightuserdata
96 #define lua_getfield dll_lua_getfield
97 #define lua_rawget dll_lua_rawget
98 #define lua_createtable dll_lua_createtable
99 #define lua_newuserdata dll_lua_newuserdata
100 #define lua_getmetatable dll_lua_getmetatable
101 #define lua_setfield dll_lua_setfield
102 #define lua_rawset dll_lua_rawset
103 #define lua_rawseti dll_lua_rawseti
104 #define lua_setmetatable dll_lua_setmetatable
105 #define lua_call dll_lua_call
106 #define lua_pcall dll_lua_pcall
107 /* libs */
108 #define luaopen_base dll_luaopen_base
109 #define luaopen_table dll_luaopen_table
110 #define luaopen_string dll_luaopen_string
111 #define luaopen_math dll_luaopen_math
112 #define luaopen_io dll_luaopen_io
113 #define luaopen_os dll_luaopen_os
114 #define luaopen_package dll_luaopen_package
115 #define luaopen_debug dll_luaopen_debug
116 #define luaL_openlibs dll_luaL_openlibs
117 
118 /* lauxlib */
119 void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l);
120 int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname);
121 const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l);
122 lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg);
123 lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def);
124 void (*dll_luaL_checktype) (lua_State *L, int narg, int t);
125 int (*dll_luaL_error) (lua_State *L, const char *fmt, ...);
126 int (*dll_luaL_loadfile) (lua_State *L, const char *filename);
127 int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name);
128 lua_State *(*dll_luaL_newstate) (void);
129 void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B);
130 char *(*dll_luaL_prepbuffer) (luaL_Buffer *B);
131 void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
132 void (*dll_luaL_pushresult) (luaL_Buffer *B);
133 /* lua */
134 void       (*dll_lua_close) (lua_State *L);
135 int (*dll_lua_gettop) (lua_State *L);
136 void (*dll_lua_settop) (lua_State *L, int idx);
137 void (*dll_lua_pushvalue) (lua_State *L, int idx);
138 void (*dll_lua_replace) (lua_State *L, int idx);
139 int (*dll_lua_isnumber) (lua_State *L, int idx);
140 int (*dll_lua_isstring) (lua_State *L, int idx);
141 int (*dll_lua_type) (lua_State *L, int idx);
142 int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2);
143 lua_Number (*dll_lua_tonumber) (lua_State *L, int idx);
144 lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx);
145 int (*dll_lua_toboolean) (lua_State *L, int idx);
146 const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len);
147 void *(*dll_lua_touserdata) (lua_State *L, int idx);
148 void (*dll_lua_pushnil) (lua_State *L);
149 void (*dll_lua_pushnumber) (lua_State *L, lua_Number n);
150 void (*dll_lua_pushinteger) (lua_State *L, lua_Integer n);
151 void (*dll_lua_pushlstring) (lua_State *L, const char *s, size_t l);
152 void (*dll_lua_pushstring) (lua_State *L, const char *s);
153 const char *(*dll_lua_pushfstring) (lua_State *L, const char *fmt, ...);
154 void (*dll_lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
155 void (*dll_lua_pushboolean) (lua_State *L, int b);
156 void (*dll_lua_pushlightuserdata) (lua_State *L, void *p);
157 void (*dll_lua_getfield) (lua_State *L, int idx, const char *k);
158 void (*dll_lua_rawget) (lua_State *L, int idx);
159 void (*dll_lua_createtable) (lua_State *L, int narr, int nrec);
160 void *(*dll_lua_newuserdata) (lua_State *L, size_t sz);
161 int (*dll_lua_getmetatable) (lua_State *L, int objindex);
162 void (*dll_lua_setfield) (lua_State *L, int idx, const char *k);
163 void (*dll_lua_rawset) (lua_State *L, int idx);
164 void (*dll_lua_rawseti) (lua_State *L, int idx, int n);
165 int (*dll_lua_setmetatable) (lua_State *L, int objindex);
166 void (*dll_lua_call) (lua_State *L, int nargs, int nresults);
167 int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
168 /* libs */
169 int (*dll_luaopen_base) (lua_State *L);
170 int (*dll_luaopen_table) (lua_State *L);
171 int (*dll_luaopen_string) (lua_State *L);
172 int (*dll_luaopen_math) (lua_State *L);
173 int (*dll_luaopen_io) (lua_State *L);
174 int (*dll_luaopen_os) (lua_State *L);
175 int (*dll_luaopen_package) (lua_State *L);
176 int (*dll_luaopen_debug) (lua_State *L);
177 void (*dll_luaL_openlibs) (lua_State *L);
178 
179 typedef void **luaV_function;
180 typedef struct {
181     const char *name;
182     luaV_function func;
183 } luaV_Reg;
184 
185 static const luaV_Reg luaV_dll[] = {
186     /* lauxlib */
187     {"luaL_register", (luaV_function) &dll_luaL_register},
188     {"luaL_typerror", (luaV_function) &dll_luaL_typerror},
189     {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring},
190     {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger},
191     {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger},
192     {"luaL_checktype", (luaV_function) &dll_luaL_checktype},
193     {"luaL_error", (luaV_function) &dll_luaL_error},
194     {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile},
195     {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer},
196     {"luaL_newstate", (luaV_function) &dll_luaL_newstate},
197     {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit},
198     {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer},
199     {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring},
200     {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult},
201     /* lua */
202     {"lua_close", (luaV_function) &dll_lua_close},
203     {"lua_gettop", (luaV_function) &dll_lua_gettop},
204     {"lua_settop", (luaV_function) &dll_lua_settop},
205     {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue},
206     {"lua_replace", (luaV_function) &dll_lua_replace},
207     {"lua_isnumber", (luaV_function) &dll_lua_isnumber},
208     {"lua_isstring", (luaV_function) &dll_lua_isstring},
209     {"lua_type", (luaV_function) &dll_lua_type},
210     {"lua_rawequal", (luaV_function) &dll_lua_rawequal},
211     {"lua_tonumber", (luaV_function) &dll_lua_tonumber},
212     {"lua_tointeger", (luaV_function) &dll_lua_tointeger},
213     {"lua_toboolean", (luaV_function) &dll_lua_toboolean},
214     {"lua_tolstring", (luaV_function) &dll_lua_tolstring},
215     {"lua_touserdata", (luaV_function) &dll_lua_touserdata},
216     {"lua_pushnil", (luaV_function) &dll_lua_pushnil},
217     {"lua_pushnumber", (luaV_function) &dll_lua_pushnumber},
218     {"lua_pushinteger", (luaV_function) &dll_lua_pushinteger},
219     {"lua_pushlstring", (luaV_function) &dll_lua_pushlstring},
220     {"lua_pushstring", (luaV_function) &dll_lua_pushstring},
221     {"lua_pushfstring", (luaV_function) &dll_lua_pushfstring},
222     {"lua_pushcclosure", (luaV_function) &dll_lua_pushcclosure},
223     {"lua_pushboolean", (luaV_function) &dll_lua_pushboolean},
224     {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata},
225     {"lua_getfield", (luaV_function) &dll_lua_getfield},
226     {"lua_rawget", (luaV_function) &dll_lua_rawget},
227     {"lua_createtable", (luaV_function) &dll_lua_createtable},
228     {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata},
229     {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable},
230     {"lua_setfield", (luaV_function) &dll_lua_setfield},
231     {"lua_rawset", (luaV_function) &dll_lua_rawset},
232     {"lua_rawseti", (luaV_function) &dll_lua_rawseti},
233     {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable},
234     {"lua_call", (luaV_function) &dll_lua_call},
235     {"lua_pcall", (luaV_function) &dll_lua_pcall},
236     /* libs */
237     {"luaopen_base", (luaV_function) &dll_luaopen_base},
238     {"luaopen_table", (luaV_function) &dll_luaopen_table},
239     {"luaopen_string", (luaV_function) &dll_luaopen_string},
240     {"luaopen_math", (luaV_function) &dll_luaopen_math},
241     {"luaopen_io", (luaV_function) &dll_luaopen_io},
242     {"luaopen_os", (luaV_function) &dll_luaopen_os},
243     {"luaopen_package", (luaV_function) &dll_luaopen_package},
244     {"luaopen_debug", (luaV_function) &dll_luaopen_debug},
245     {"luaL_openlibs", (luaV_function) &dll_luaL_openlibs},
246     {NULL, NULL}
247 };
248 
249 static HANDLE hinstLua = NULL;
250 
251     static void
252 end_dynamic_lua(void)
253 {
254     if (hinstLua)
255     {
256 	close_dll(hinstLua);
257 	hinstLua = 0;
258     }
259 }
260 
261     static int
262 lua_link_init(char *libname, int verbose)
263 {
264     const luaV_Reg *reg;
265     if (hinstLua) return OK;
266     hinstLua = load_dll(libname);
267     if (!hinstLua)
268     {
269 	if (verbose)
270 	    EMSG2(_(e_loadlib), libname);
271 	return FAIL;
272     }
273     for (reg = luaV_dll; reg->func; reg++)
274     {
275 	if ((*reg->func = symbol_from_dll(hinstLua, reg->name)) == NULL)
276 	{
277 	    close_dll(hinstLua);
278 	    hinstLua = 0;
279 	    if (verbose)
280 		EMSG2(_(e_loadfunc), reg->name);
281 	    return FAIL;
282 	}
283     }
284     return OK;
285 }
286 
287     int
288 lua_enabled(int verbose)
289 {
290     return lua_link_init(DYNAMIC_LUA_DLL, verbose) == OK;
291 }
292 
293 #endif /* DYNAMIC_LUA */
294 
295 
296 /* =======   Internal   ======= */
297 
298     static void
299 luaV_newmetatable(lua_State *L, const char *tname)
300 {
301     lua_newtable(L);
302     lua_pushlightuserdata(L, (void *) tname);
303     lua_pushvalue(L, -2);
304     lua_rawset(L, LUA_REGISTRYINDEX);
305 }
306 
307     static void *
308 luaV_toudata(lua_State *L, int ud, const char *tname)
309 {
310     void *p = lua_touserdata(L, ud);
311 
312     if (p != NULL) /* value is userdata? */
313     {
314 	if (lua_getmetatable(L, ud)) /* does it have a metatable? */
315 	{
316 	    luaV_getfield(L, tname); /* get metatable */
317 	    if (lua_rawequal(L, -1, -2)) /* MTs match? */
318 	    {
319 		lua_pop(L, 2); /* MTs */
320 		return p;
321 	    }
322 	}
323     }
324     return NULL;
325 }
326 
327     static void *
328 luaV_checkudata(lua_State *L, int ud, const char *tname)
329 {
330     void *p = luaV_toudata(L, ud, tname);
331     if (p == NULL) luaL_typerror(L, ud, tname);
332     return p;
333 }
334 
335     static void
336 luaV_pushtypval(lua_State *L, typval_T *tv)
337 {
338     if (tv == NULL) luaL_error(L, "null type");
339     switch (tv->v_type)
340     {
341 	case VAR_STRING:
342 	    lua_pushstring(L, (char *) tv->vval.v_string);
343 	    break;
344 	case VAR_NUMBER:
345 	    lua_pushinteger(L, (int) tv->vval.v_number);
346 	    break;
347 #ifdef FEAT_FLOAT
348 	case VAR_FLOAT:
349 	    lua_pushnumber(L, (lua_Number) tv->vval.v_float);
350 	    break;
351 #endif
352 	case VAR_LIST: {
353 	    list_T *l = tv->vval.v_list;
354 
355 	    if (l != NULL)
356 	    {
357 		/* check cache */
358 		lua_pushlightuserdata(L, (void *) l);
359 		lua_rawget(L, LUA_ENVIRONINDEX);
360 		if (lua_isnil(L, -1)) /* not interned? */
361 		{
362 		    listitem_T *li;
363 		    int n = 0;
364 		    lua_pop(L, 1); /* nil */
365 		    lua_newtable(L);
366 		    lua_pushlightuserdata(L, (void *) l);
367 		    lua_pushvalue(L, -2);
368 		    lua_rawset(L, LUA_ENVIRONINDEX);
369 		    for (li = l->lv_first; li != NULL; li = li->li_next)
370 		    {
371 			luaV_pushtypval(L, &li->li_tv);
372 			lua_rawseti(L, -2, ++n);
373 		    }
374 		}
375 	    }
376 	    else lua_pushnil(L);
377 	    break;
378 		       }
379 	case VAR_DICT: {
380 	    dict_T *d = tv->vval.v_dict;
381 
382 	    if (d != NULL)
383 	    {
384 		/* check cache */
385 		lua_pushlightuserdata(L, (void *) d);
386 		lua_rawget(L, LUA_ENVIRONINDEX);
387 		if (lua_isnil(L, -1)) /* not interned? */
388 		{
389 		    hashtab_T *ht = &d->dv_hashtab;
390 		    hashitem_T *hi;
391 		    int n = ht->ht_used; /* remaining items */
392 		    lua_pop(L, 1); /* nil */
393 		    lua_newtable(L);
394 		    lua_pushlightuserdata(L, (void *) d);
395 		    lua_pushvalue(L, -2);
396 		    lua_rawset(L, LUA_ENVIRONINDEX);
397 		    for (hi = ht->ht_array; n > 0; hi++)
398 		    {
399 			if (!HASHITEM_EMPTY(hi))
400 			{
401 			    dictitem_T *di = dict_lookup(hi);
402 			    luaV_pushtypval(L, &di->di_tv);
403 			    lua_setfield(L, -2, (char *) hi->hi_key);
404 			    n--;
405 			}
406 		    }
407 		}
408 	    }
409 	    else lua_pushnil(L);
410 	    break;
411 	}
412 	default:
413 	    luaL_error(L, "invalid type");
414     }
415 }
416 
417 /* similar to luaL_addlstring, but replaces \0 with \n if toline and
418  * \n with \0 otherwise */
419     static void
420 luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline)
421 {
422     while (l--)
423     {
424 	if (*s == '\0' && toline)
425 	    luaL_addchar(b, '\n');
426 	else if (*s == '\n' && !toline)
427 	    luaL_addchar(b, '\0');
428 	else
429 	    luaL_addchar(b, *s);
430 	s++;
431     }
432 }
433 
434     static void
435 luaV_pushline(lua_State *L, buf_T *buf, linenr_T n)
436 {
437     const char *s = (const char *) ml_get_buf(buf, n, FALSE);
438     luaL_Buffer b;
439     luaL_buffinit(L, &b);
440     luaV_addlstring(&b, s, strlen(s), 0);
441     luaL_pushresult(&b);
442 }
443 
444     static char_u *
445 luaV_toline(lua_State *L, int pos)
446 {
447     size_t l;
448     const char *s = lua_tolstring(L, pos, &l);
449 
450     luaL_Buffer b;
451     luaL_buffinit(L, &b);
452     luaV_addlstring(&b, s, l, 1);
453     luaL_pushresult(&b);
454     return (char_u *) lua_tostring(L, -1);
455 }
456 
457 /* pops a string s from the top of the stack and calls mf(t) for pieces t of
458  * s separated by newlines */
459     static void
460 luaV_msgfunc(lua_State *L, msgfunc_T mf)
461 {
462     luaL_Buffer b;
463     size_t l;
464     const char *p, *s = lua_tolstring(L, -1, &l);
465     luaL_buffinit(L, &b);
466     luaV_addlstring(&b, s, l, 0);
467     luaL_pushresult(&b);
468     /* break string */
469     p = s = lua_tolstring(L, -1, &l);
470     while (l--)
471     {
472 	if (*p++ == '\0') /* break? */
473 	{
474 	    mf((char_u *) s);
475 	    s = p;
476 	}
477     }
478     mf((char_u *) s);
479     lua_pop(L, 2); /* original and modified strings */
480 }
481 
482 
483 /* =======   Buffer type   ======= */
484 
485     static luaV_Buffer *
486 luaV_newbuffer(lua_State *L, buf_T *buf)
487 {
488     luaV_Buffer *b = (luaV_Buffer *) lua_newuserdata(L, sizeof(luaV_Buffer));
489     *b = buf;
490     lua_pushlightuserdata(L, (void *) buf);
491     lua_pushvalue(L, -2);
492     lua_rawset(L, LUA_ENVIRONINDEX); /* env[buf] = udata */
493     /* to avoid GC, store as key in env */
494     lua_pushvalue(L, -1);
495     lua_pushboolean(L, 1);
496     lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */
497     /* set metatable */
498     luaV_getfield(L, LUAVIM_BUFFER);
499     lua_setmetatable(L, -2);
500     return b;
501 }
502 
503     static luaV_Buffer *
504 luaV_pushbuffer (lua_State *L, buf_T *buf)
505 {
506     luaV_Buffer *b = NULL;
507     if (buf == NULL)
508 	lua_pushnil(L);
509     else {
510 	lua_pushlightuserdata(L, (void *) buf);
511 	lua_rawget(L, LUA_ENVIRONINDEX);
512 	if (lua_isnil(L, -1)) /* not interned? */
513 	{
514 	    lua_pop(L, 1);
515 	    b = luaV_newbuffer(L, buf);
516 	}
517 	else
518 	    b = (luaV_Buffer *) lua_touserdata(L, -1);
519     }
520     return b;
521 }
522 
523 /* Buffer metamethods */
524 
525     static int
526 luaV_buffer_tostring(lua_State *L)
527 {
528     lua_pushfstring(L, "%s: %p", LUAVIM_BUFFER, lua_touserdata(L, 1));
529     return 1;
530 }
531 
532     static int
533 luaV_buffer_len(lua_State *L)
534 {
535     luaV_Buffer *b = lua_touserdata(L, 1);
536     lua_pushinteger(L, (*b)->b_ml.ml_line_count);
537     return 1;
538 }
539 
540     static int
541 luaV_buffer_call(lua_State *L)
542 {
543     luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
544     lua_settop(L, 1);
545     set_curbuf(*b, DOBUF_SPLIT);
546     return 1;
547 }
548 
549     static int
550 luaV_buffer_index(lua_State *L)
551 {
552     luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
553     linenr_T n = (linenr_T) lua_tointeger(L, 2);
554     if (n > 0 && n <= (*b)->b_ml.ml_line_count)
555 	luaV_pushline(L, *b, n);
556     else if (lua_isstring(L, 2))
557     {
558 	const char *s = lua_tostring(L, 2);
559 	if (strncmp(s, "name", 4) == 0)
560 	    lua_pushstring(L, (char *) (*b)->b_sfname);
561 	else if (strncmp(s, "fname", 5) == 0)
562 	    lua_pushstring(L, (char *) (*b)->b_ffname);
563 	else if (strncmp(s, "number", 6) == 0)
564 	    lua_pushinteger(L, (*b)->b_fnum);
565 	/* methods */
566 	else if (strncmp(s,   "insert", 6) == 0
567 		|| strncmp(s, "next", 4) == 0
568 		|| strncmp(s, "previous", 8) == 0
569 		|| strncmp(s, "isvalid", 7) == 0)
570 	{
571 	    lua_getmetatable(L, 1);
572 	    lua_getfield(L, -1, s);
573 	}
574 	else
575 	    lua_pushnil(L);
576     }
577     else
578 	lua_pushnil(L);
579     return 1;
580 }
581 
582     static int
583 luaV_buffer_newindex(lua_State *L)
584 {
585     luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1);
586     linenr_T n = (linenr_T) luaL_checkinteger(L, 2);
587 #ifdef HAVE_SANDBOX
588     luaV_checksandbox(L);
589 #endif
590     if (n < 1 || n > (*b)->b_ml.ml_line_count)
591 	luaL_error(L, "invalid line number");
592     if (lua_isnil(L, 3)) /* delete line */
593     {
594 	buf_T *buf = curbuf;
595 	curbuf = *b;
596 	if (u_savedel(n, 1L) == FAIL)
597 	{
598 	    curbuf = buf;
599 	    luaL_error(L, "cannot save undo information");
600 	}
601 	else if (ml_delete(n, FALSE) == FAIL)
602 	{
603 	    curbuf = buf;
604 	    luaL_error(L, "cannot delete line");
605 	}
606 	else {
607 	    deleted_lines_mark(n, 1L);
608 	    if (*b == curwin->w_buffer) /* fix cursor in current window? */
609 	    {
610 		if (curwin->w_cursor.lnum >= n)
611 		{
612 		    if (curwin->w_cursor.lnum > n)
613 		    {
614 			curwin->w_cursor.lnum -= 1;
615 			check_cursor_col();
616 		    }
617 		    else check_cursor();
618 		    changed_cline_bef_curs();
619 		}
620 		invalidate_botline();
621 	    }
622 	}
623 	curbuf = buf;
624     }
625     else if (lua_isstring(L, 3)) /* update line */
626     {
627 	buf_T *buf = curbuf;
628 	curbuf = *b;
629 	if (u_savesub(n) == FAIL)
630 	{
631 	    curbuf = buf;
632 	    luaL_error(L, "cannot save undo information");
633 	}
634 	else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL)
635 	{
636 	    curbuf = buf;
637 	    luaL_error(L, "cannot replace line");
638 	}
639 	else changed_bytes(n, 0);
640 	curbuf = buf;
641 	if (*b == curwin->w_buffer)
642 	    check_cursor_col();
643     }
644     else
645 	luaL_error(L, "wrong argument to change line");
646     return 0;
647 }
648 
649     static int
650 luaV_buffer_insert(lua_State *L)
651 {
652     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
653     linenr_T last = (*b)->b_ml.ml_line_count;
654     linenr_T n = (linenr_T) luaL_optinteger(L, 3, last);
655     buf_T *buf;
656     luaL_checktype(L, 2, LUA_TSTRING);
657 #ifdef HAVE_SANDBOX
658     luaV_checksandbox(L);
659 #endif
660     /* fix insertion line */
661     if (n < 0) n = 0;
662     if (n > last) n = last;
663     /* insert */
664     buf = curbuf;
665     curbuf = *b;
666     if (u_save(n, n + 1) == FAIL)
667     {
668 	curbuf = buf;
669 	luaL_error(L, "cannot save undo information");
670     }
671     else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL)
672     {
673 	curbuf = buf;
674 	luaL_error(L, "cannot insert line");
675     }
676     else
677 	appended_lines_mark(n, 1L);
678     curbuf = buf;
679     update_screen(VALID);
680     return 0;
681 }
682 
683     static int
684 luaV_buffer_next(lua_State *L)
685 {
686     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
687     luaV_pushbuffer(L, (*b)->b_next);
688     return 1;
689 }
690 
691     static int
692 luaV_buffer_previous(lua_State *L)
693 {
694     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
695     luaV_pushbuffer(L, (*b)->b_prev);
696     return 1;
697 }
698 
699     static int
700 luaV_buffer_isvalid(lua_State *L)
701 {
702     luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER);
703     lua_pushlightuserdata(L, (void *) (*b));
704     lua_rawget(L, LUA_ENVIRONINDEX);
705     lua_pushboolean(L, !lua_isnil(L, -1));
706     return 1;
707 }
708 
709 static const luaL_Reg luaV_Buffer_mt[] = {
710     {"__tostring", luaV_buffer_tostring},
711     {"__len", luaV_buffer_len},
712     {"__call", luaV_buffer_call},
713     {"__index", luaV_buffer_index},
714     {"__newindex", luaV_buffer_newindex},
715     {"insert", luaV_buffer_insert},
716     {"next", luaV_buffer_next},
717     {"previous", luaV_buffer_previous},
718     {"isvalid", luaV_buffer_isvalid},
719     {NULL, NULL}
720 };
721 
722 
723 /* =======   Window type   ======= */
724 
725     static luaV_Window *
726 luaV_newwindow(lua_State *L, win_T *win)
727 {
728     luaV_Window *w = (luaV_Window *) lua_newuserdata(L, sizeof(luaV_Window));
729     *w = win;
730     lua_pushlightuserdata(L, (void *) win);
731     lua_pushvalue(L, -2);
732     lua_rawset(L, LUA_ENVIRONINDEX); /* env[win] = udata */
733     /* to avoid GC, store as key in env */
734     lua_pushvalue(L, -1);
735     lua_pushboolean(L, 1);
736     lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */
737     /* set metatable */
738     luaV_getfield(L, LUAVIM_WINDOW);
739     lua_setmetatable(L, -2);
740     return w;
741 }
742 
743     static luaV_Window *
744 luaV_pushwindow(lua_State *L, win_T *win)
745 {
746     luaV_Window *w = NULL;
747     if (win == NULL)
748 	lua_pushnil(L);
749     else {
750 	lua_pushlightuserdata(L, (void *) win);
751 	lua_rawget(L, LUA_ENVIRONINDEX);
752 	if (lua_isnil(L, -1)) /* not interned? */
753 	{
754 	    lua_pop(L, 1);
755 	    w = luaV_newwindow(L, win);
756 	}
757 	else w = (luaV_Window *) lua_touserdata(L, -1);
758     }
759     return w;
760 }
761 
762 /* Window metamethods */
763 
764     static int
765 luaV_window_tostring(lua_State *L)
766 {
767     lua_pushfstring(L, "%s: %p", LUAVIM_WINDOW, lua_touserdata(L, 1));
768     return 1;
769 }
770 
771     static int
772 luaV_window_call(lua_State *L)
773 {
774     luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
775     lua_settop(L, 1);
776     win_goto(*w);
777     return 1;
778 }
779 
780     static int
781 luaV_window_index(lua_State *L)
782 {
783     luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
784     const char *s = luaL_checkstring(L, 2);
785     if (strncmp(s, "buffer", 6) == 0)
786 	luaV_pushbuffer(L, (*w)->w_buffer);
787     else if (strncmp(s, "line", 4) == 0)
788 	lua_pushinteger(L, (*w)->w_cursor.lnum);
789     else if (strncmp(s, "col", 3) == 0)
790 	lua_pushinteger(L, (*w)->w_cursor.col + 1);
791 #ifdef FEAT_VERTSPLIT
792     else if (strncmp(s, "width", 5) == 0)
793 	lua_pushinteger(L, W_WIDTH((*w)));
794 #endif
795     else if (strncmp(s, "height", 6) == 0)
796 	lua_pushinteger(L, (*w)->w_height);
797     /* methods */
798     else if (strncmp(s,   "next", 4) == 0
799 	    || strncmp(s, "previous", 8) == 0
800 	    || strncmp(s, "isvalid", 7) == 0)
801     {
802 	lua_getmetatable(L, 1);
803 	lua_getfield(L, -1, s);
804     }
805     else
806 	lua_pushnil(L);
807     return 1;
808 }
809 
810     static int
811 luaV_window_newindex (lua_State *L)
812 {
813     luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1);
814     const char *s = luaL_checkstring(L, 2);
815     int v = luaL_checkinteger(L, 3);
816     if (strncmp(s, "line", 4) == 0)
817     {
818 #ifdef HAVE_SANDBOX
819 	luaV_checksandbox(L);
820 #endif
821 	if (v < 1 || v > (*w)->w_buffer->b_ml.ml_line_count)
822 	    luaL_error(L, "line out of range");
823 	(*w)->w_cursor.lnum = v;
824 	update_screen(VALID);
825     }
826     else if (strncmp(s, "col", 3) == 0)
827     {
828 #ifdef HAVE_SANDBOX
829 	luaV_checksandbox(L);
830 #endif
831 	(*w)->w_cursor.col = v - 1;
832 	update_screen(VALID);
833     }
834 #ifdef FEAT_VERTSPLIT
835     else if (strncmp(s, "width", 5) == 0)
836     {
837 	win_T *win = curwin;
838 #ifdef FEAT_GUI
839 	need_mouse_correct = TRUE;
840 #endif
841 	curwin = *w;
842 	win_setwidth(v);
843 	curwin = win;
844     }
845 #endif
846     else if (strncmp(s, "height", 6) == 0)
847     {
848 	win_T *win = curwin;
849 #ifdef FEAT_GUI
850 	need_mouse_correct = TRUE;
851 #endif
852 	curwin = *w;
853 	win_setheight(v);
854 	curwin = win;
855     }
856     else
857 	luaL_error(L, "invalid window property: `%s'", s);
858     return 0;
859 }
860 
861     static int
862 luaV_window_next(lua_State *L)
863 {
864     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
865     luaV_pushwindow(L, (*w)->w_next);
866     return 1;
867 }
868 
869     static int
870 luaV_window_previous(lua_State *L)
871 {
872     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
873     luaV_pushwindow(L, (*w)->w_prev);
874     return 1;
875 }
876 
877     static int
878 luaV_window_isvalid(lua_State *L)
879 {
880     luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW);
881     lua_pushlightuserdata(L, (void *) (*w));
882     lua_rawget(L, LUA_ENVIRONINDEX);
883     lua_pushboolean(L, !lua_isnil(L, -1));
884     return 1;
885 }
886 
887 static const luaL_Reg luaV_Window_mt[] = {
888     {"__tostring", luaV_window_tostring},
889     {"__call", luaV_window_call},
890     {"__index", luaV_window_index},
891     {"__newindex", luaV_window_newindex},
892     {"next", luaV_window_next},
893     {"previous", luaV_window_previous},
894     {"isvalid", luaV_window_isvalid},
895     {NULL, NULL}
896 };
897 
898 
899 /* =======   Vim module   ======= */
900 
901     static int
902 luaV_print(lua_State *L)
903 {
904     int i, n = lua_gettop(L); /* nargs */
905     const char *s;
906     size_t l;
907     luaL_Buffer b;
908     luaL_buffinit(L, &b);
909     lua_getglobal(L, "tostring");
910     for (i = 1; i <= n; i++)
911     {
912 	lua_pushvalue(L, -1); /* tostring */
913 	lua_pushvalue(L, i); /* arg */
914 	lua_call(L, 1, 1);
915 	s = lua_tolstring(L, -1, &l);
916 	if (s == NULL)
917 	    return luaL_error(L, "cannot convert to string");
918 	if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */
919 	luaV_addlstring(&b, s, l, 0);
920 	lua_pop(L, 1);
921     }
922     luaL_pushresult(&b);
923     luaV_msg(L);
924     return 0;
925 }
926 
927     static int
928 luaV_command(lua_State *L)
929 {
930     do_cmdline_cmd((char_u *) luaL_checkstring(L, 1));
931     update_screen(VALID);
932     return 0;
933 }
934 
935     static int
936 luaV_eval(lua_State *L)
937 {
938     typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL);
939     if (tv == NULL) luaL_error(L, "invalid expression");
940     luaV_pushtypval(L, tv);
941     return 1;
942 }
943 
944     static int
945 luaV_beep(lua_State *L UNUSED)
946 {
947     vim_beep();
948     return 0;
949 }
950 
951     static int
952 luaV_line(lua_State *L)
953 {
954     luaV_pushline(L, curbuf, curwin->w_cursor.lnum);
955     return 1;
956 }
957 
958     static int
959 luaV_buffer(lua_State *L)
960 {
961     buf_T *buf;
962     if (lua_isstring(L, 1)) /* get by number or name? */
963     {
964 	if (lua_isnumber(L, 1)) /* by number? */
965 	{
966 	    int n = lua_tointeger(L, 1);
967 	    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
968 		if (buf->b_fnum == n) break;
969 	}
970 	else { /* by name */
971 	    size_t l;
972 	    const char *s = lua_tolstring(L, 1, &l);
973 	    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
974 	    {
975 		if (buf->b_ffname == NULL || buf->b_sfname == NULL)
976 		{
977 		    if (l == 0) break;
978 		}
979 		else if (strncmp(s, (char *)buf->b_ffname, l) == 0
980 			|| strncmp(s, (char *)buf->b_sfname, l) == 0)
981 		    break;
982 	    }
983 	}
984 	if (buf == NULL) /* not found? */
985 	    lua_pushnil(L);
986 	else
987 	    luaV_pushbuffer(L, buf);
988     }
989     else {
990 	buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */
991 	luaV_pushbuffer(L, buf);
992     }
993     return 1;
994 }
995 
996     static int
997 luaV_window(lua_State *L)
998 {
999     win_T *win;
1000     if (lua_isnumber(L, 1)) /* get by number? */
1001     {
1002 	int n = lua_tointeger(L, 1);
1003 	for (win = firstwin; win != NULL; win = win->w_next, n--)
1004 	    if (n == 1) break;
1005 	if (win == NULL) /* not found? */
1006 	    lua_pushnil(L);
1007 	else
1008 	    luaV_pushwindow(L, win);
1009     }
1010     else {
1011 	win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */
1012 	luaV_pushwindow(L, win);
1013     }
1014     return 1;
1015 }
1016 
1017     static int
1018 luaV_open(lua_State *L)
1019 {
1020     luaV_Buffer *b;
1021     char_u *s = NULL;
1022 #ifdef HAVE_SANDBOX
1023     luaV_checksandbox(L);
1024 #endif
1025     if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1);
1026     b = luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED));
1027     return 1;
1028 }
1029 
1030     static int
1031 luaV_isbuffer(lua_State *L)
1032 {
1033     lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_BUFFER) != NULL);
1034     return 1;
1035 }
1036 
1037     static int
1038 luaV_iswindow(lua_State *L)
1039 {
1040     lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_WINDOW) != NULL);
1041     return 1;
1042 }
1043 
1044 /* for freeing buffer and window objects; lightuserdata as arg */
1045     static int
1046 luaV_free(lua_State *L)
1047 {
1048     lua_pushvalue(L, 1); /* lightudata */
1049     lua_rawget(L, LUA_ENVIRONINDEX);
1050     if (!lua_isnil(L, -1))
1051     {
1052 	lua_pushnil(L);
1053 	lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = nil */
1054 	lua_pushnil(L);
1055 	lua_rawset(L, LUA_ENVIRONINDEX); /* env[lightudata] = nil */
1056     }
1057     return 0;
1058 }
1059 
1060 static const luaL_Reg luaV_module[] = {
1061     {"command", luaV_command},
1062     {"eval", luaV_eval},
1063     {"beep", luaV_beep},
1064     {"line", luaV_line},
1065     {"buffer", luaV_buffer},
1066     {"window", luaV_window},
1067     {"open", luaV_open},
1068     {"isbuffer", luaV_isbuffer},
1069     {"iswindow", luaV_iswindow},
1070     {NULL, NULL}
1071 };
1072 
1073     static int
1074 luaopen_vim(lua_State *L)
1075 {
1076     /* set environment */
1077     lua_newtable(L);
1078     lua_newtable(L);
1079     lua_pushliteral(L, "v");
1080     lua_setfield(L, -2, "__mode");
1081     lua_setmetatable(L, -2);
1082     lua_replace(L, LUA_ENVIRONINDEX);
1083     /* print */
1084     lua_pushcfunction(L, luaV_print);
1085     lua_setglobal(L, "print");
1086     /* free */
1087     lua_pushlightuserdata(L, (void *) LUAVIM_FREE);
1088     lua_pushcfunction(L, luaV_free);
1089     lua_rawset(L, LUA_REGISTRYINDEX);
1090     /* register */
1091     luaV_newmetatable(L, LUAVIM_BUFFER);
1092     luaL_register(L, NULL, luaV_Buffer_mt);
1093     luaV_newmetatable(L, LUAVIM_WINDOW);
1094     luaL_register(L, NULL, luaV_Window_mt);
1095     luaL_register(L, LUAVIM_NAME, luaV_module);
1096     return 0;
1097 }
1098 
1099     static lua_State *
1100 luaV_newstate(void)
1101 {
1102     lua_State *L = luaL_newstate();
1103     luaL_openlibs(L); /* core libs */
1104     lua_pushcfunction(L, luaopen_vim); /* vim */
1105     lua_call(L, 0, 0);
1106     return L;
1107 }
1108 
1109     static void
1110 luaV_setrange(lua_State *L, int line1, int line2)
1111 {
1112     lua_getglobal(L, LUAVIM_NAME);
1113     lua_pushinteger(L, line1);
1114     lua_setfield(L, -2, "firstline");
1115     lua_pushinteger(L, line2);
1116     lua_setfield(L, -2, "lastline");
1117     lua_pop(L, 1); /* vim table */
1118 }
1119 
1120 
1121 /* =======   Interface   ======= */
1122 
1123 static lua_State *L = NULL;
1124 
1125     static int
1126 lua_init(void)
1127 {
1128     if (L == NULL)
1129     {
1130 #ifdef DYNAMIC_LUA
1131 	if (!lua_enabled(TRUE))
1132 	{
1133 	    EMSG(_("Lua library cannot be loaded."));
1134 	    return FAIL;
1135 	}
1136 #endif
1137 	L = luaV_newstate();
1138     }
1139     return OK;
1140 }
1141 
1142     void
1143 lua_end(void)
1144 {
1145     if (L != NULL)
1146     {
1147 	lua_close(L);
1148 	L = NULL;
1149 #ifdef DYNAMIC_LUA
1150 	end_dynamic_lua();
1151 #endif
1152     }
1153 }
1154 
1155 /* ex commands */
1156     void
1157 ex_lua(exarg_T *eap)
1158 {
1159     char *script;
1160     if (lua_init() == FAIL) return;
1161     script = (char *) script_get(eap, eap->arg);
1162     if (!eap->skip)
1163     {
1164 	char *s = (script) ? script :  (char *) eap->arg;
1165 	luaV_setrange(L, eap->line1, eap->line2);
1166 	if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME)
1167 		|| lua_pcall(L, 0, 0, 0))
1168 	    luaV_emsg(L);
1169     }
1170     if (script != NULL) vim_free(script);
1171 }
1172 
1173     void
1174 ex_luado(exarg_T *eap)
1175 {
1176     linenr_T l;
1177     const char *s = (const char *) eap->arg;
1178     luaL_Buffer b;
1179     size_t len;
1180     if (lua_init() == FAIL) return;
1181     if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
1182     {
1183 	EMSG(_("cannot save undo information"));
1184 	return;
1185     }
1186     luaV_setrange(L, eap->line1, eap->line2);
1187     luaL_buffinit(L, &b);
1188     luaL_addlstring(&b, "return function(line) ", 22); /* header */
1189     luaL_addlstring(&b, s, strlen(s));
1190     luaL_addlstring(&b, " end", 4); /* footer */
1191     luaL_pushresult(&b);
1192     s = lua_tolstring(L, -1, &len);
1193     if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME))
1194     {
1195 	luaV_emsg(L);
1196 	lua_pop(L, 1); /* function body */
1197 	return;
1198     }
1199     lua_call(L, 0, 1);
1200     lua_replace(L, -2); /* function -> body */
1201     for (l = eap->line1; l <= eap->line2; l++)
1202     {
1203 	lua_pushvalue(L, -1); /* function */
1204 	luaV_pushline(L, curbuf, l); /* current line as arg */
1205 	if (lua_pcall(L, 1, 1, 0))
1206 	{
1207 	    luaV_emsg(L);
1208 	    break;
1209 	}
1210 	if (lua_isstring(L, -1)) /* update line? */
1211 	{
1212 #ifdef HAVE_SANDBOX
1213 	    luaV_checksandbox(L);
1214 #endif
1215 	    ml_replace(l, luaV_toline(L, -1), TRUE);
1216 	    changed_bytes(l, 0);
1217 	    lua_pop(L, 1); /* result from luaV_toline */
1218 	}
1219 	lua_pop(L, 1); /* line */
1220     }
1221     lua_pop(L, 1); /* function */
1222     check_cursor();
1223     update_screen(NOT_VALID);
1224 }
1225 
1226     void
1227 ex_luafile(exarg_T *eap)
1228 {
1229     if (lua_init() == FAIL)
1230 	return;
1231     if (!eap->skip)
1232     {
1233 	luaV_setrange(L, eap->line1, eap->line2);
1234 	if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0))
1235 	    luaV_emsg(L);
1236     }
1237 }
1238 
1239 /* buffer */
1240     void
1241 lua_buffer_free(buf_T *buf)
1242 {
1243     if (lua_init() == FAIL) return;
1244     luaV_getfield(L, LUAVIM_FREE);
1245     lua_pushlightuserdata(L, (void *) buf);
1246     lua_call(L, 1, 0);
1247 }
1248 
1249 /* window */
1250     void
1251 lua_window_free(win_T *win)
1252 {
1253     if (lua_init() == FAIL) return;
1254     luaV_getfield(L, LUAVIM_FREE);
1255     lua_pushlightuserdata(L, (void *) win);
1256     lua_call(L, 1, 0);
1257 }
1258 
1259 #endif
1260