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