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