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