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