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