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