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