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 return lua_link_init((char *)p_luadll, verbose) == OK; 406 } 407 408 #endif /* DYNAMIC_LUA */ 409 410 #if LUA_VERSION_NUM > 501 411 static int 412 luaL_typeerror (lua_State *L, int narg, const char *tname) 413 { 414 const char *msg = lua_pushfstring(L, "%s expected, got %s", 415 tname, luaL_typename(L, narg)); 416 return luaL_argerror(L, narg, msg); 417 } 418 #endif 419 420 421 /* ======= Internal ======= */ 422 423 static void 424 luaV_newmetatable(lua_State *L, const char *tname) 425 { 426 lua_newtable(L); 427 lua_pushlightuserdata(L, (void *) tname); 428 lua_pushvalue(L, -2); 429 lua_rawset(L, LUA_REGISTRYINDEX); 430 } 431 432 static void * 433 luaV_toudata(lua_State *L, int ud, const char *tname) 434 { 435 void *p = lua_touserdata(L, ud); 436 437 if (p != NULL) /* value is userdata? */ 438 { 439 if (lua_getmetatable(L, ud)) /* does it have a metatable? */ 440 { 441 luaV_getfield(L, tname); /* get metatable */ 442 if (lua_rawequal(L, -1, -2)) /* MTs match? */ 443 { 444 lua_pop(L, 2); /* MTs */ 445 return p; 446 } 447 } 448 } 449 return NULL; 450 } 451 452 static void * 453 luaV_checkcache(lua_State *L, void *p) 454 { 455 luaV_getudata(L, p); 456 if (lua_isnil(L, -1)) luaL_error(L, "invalid object"); 457 lua_pop(L, 1); 458 return p; 459 } 460 461 #define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud)))) 462 463 #define luaV_checkvalid(L,luatyp,ud) \ 464 luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud))) 465 466 static void * 467 luaV_checkudata(lua_State *L, int ud, const char *tname) 468 { 469 void *p = luaV_toudata(L, ud, tname); 470 if (p == NULL) luaL_typeerror(L, ud, tname); 471 return p; 472 } 473 474 static void 475 luaV_pushtypval(lua_State *L, typval_T *tv) 476 { 477 if (tv == NULL) 478 { 479 lua_pushnil(L); 480 return; 481 } 482 switch (tv->v_type) 483 { 484 case VAR_STRING: 485 lua_pushstring(L, tv->vval.v_string == NULL 486 ? "" : (char *)tv->vval.v_string); 487 break; 488 case VAR_NUMBER: 489 lua_pushinteger(L, (int) tv->vval.v_number); 490 break; 491 #ifdef FEAT_FLOAT 492 case VAR_FLOAT: 493 lua_pushnumber(L, (lua_Number) tv->vval.v_float); 494 break; 495 #endif 496 case VAR_LIST: 497 luaV_pushlist(L, tv->vval.v_list); 498 break; 499 case VAR_DICT: 500 luaV_pushdict(L, tv->vval.v_dict); 501 break; 502 default: 503 lua_pushnil(L); 504 } 505 } 506 507 /* converts lua value at 'pos' to typval 'tv' */ 508 static void 509 luaV_totypval (lua_State *L, int pos, typval_T *tv) 510 { 511 switch(lua_type(L, pos)) { 512 case LUA_TBOOLEAN: 513 tv->v_type = VAR_NUMBER; 514 tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos); 515 break; 516 case LUA_TSTRING: 517 tv->v_type = VAR_STRING; 518 tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos)); 519 break; 520 case LUA_TNUMBER: 521 #ifdef FEAT_FLOAT 522 tv->v_type = VAR_FLOAT; 523 tv->vval.v_float = (float_T) lua_tonumber(L, pos); 524 #else 525 tv->v_type = VAR_NUMBER; 526 tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos); 527 #endif 528 break; 529 case LUA_TUSERDATA: { 530 void *p = lua_touserdata(L, pos); 531 if (lua_getmetatable(L, pos)) /* has metatable? */ 532 { 533 /* check list */ 534 luaV_getfield(L, LUAVIM_LIST); 535 if (lua_rawequal(L, -1, -2)) 536 { 537 tv->v_type = VAR_LIST; 538 tv->vval.v_list = *((luaV_List *) p); 539 ++tv->vval.v_list->lv_refcount; 540 lua_pop(L, 2); /* MTs */ 541 return; 542 } 543 /* check dict */ 544 luaV_getfield(L, LUAVIM_DICT); 545 if (lua_rawequal(L, -1, -3)) 546 { 547 tv->v_type = VAR_DICT; 548 tv->vval.v_dict = *((luaV_Dict *) p); 549 ++tv->vval.v_dict->dv_refcount; 550 lua_pop(L, 3); /* MTs */ 551 return; 552 } 553 lua_pop(L, 3); /* MTs */ 554 } 555 break; 556 } 557 default: 558 tv->v_type = VAR_NUMBER; 559 tv->vval.v_number = 0; 560 } 561 } 562 563 /* similar to luaL_addlstring, but replaces \0 with \n if toline and 564 * \n with \0 otherwise */ 565 static void 566 luaV_addlstring(luaL_Buffer *b, const char *s, size_t l, int toline) 567 { 568 while (l--) 569 { 570 if (*s == '\0' && toline) 571 luaL_addchar(b, '\n'); 572 else if (*s == '\n' && !toline) 573 luaL_addchar(b, '\0'); 574 else 575 luaL_addchar(b, *s); 576 s++; 577 } 578 } 579 580 static void 581 luaV_pushline(lua_State *L, buf_T *buf, linenr_T n) 582 { 583 const char *s = (const char *) ml_get_buf(buf, n, FALSE); 584 luaL_Buffer b; 585 luaL_buffinit(L, &b); 586 luaV_addlstring(&b, s, strlen(s), 0); 587 luaL_pushresult(&b); 588 } 589 590 static char_u * 591 luaV_toline(lua_State *L, int pos) 592 { 593 size_t l; 594 const char *s = lua_tolstring(L, pos, &l); 595 596 luaL_Buffer b; 597 luaL_buffinit(L, &b); 598 luaV_addlstring(&b, s, l, 1); 599 luaL_pushresult(&b); 600 return (char_u *) lua_tostring(L, -1); 601 } 602 603 /* pops a string s from the top of the stack and calls mf(t) for pieces t of 604 * s separated by newlines */ 605 static void 606 luaV_msgfunc(lua_State *L, msgfunc_T mf) 607 { 608 luaL_Buffer b; 609 size_t l; 610 const char *p, *s = lua_tolstring(L, -1, &l); 611 luaL_buffinit(L, &b); 612 luaV_addlstring(&b, s, l, 0); 613 luaL_pushresult(&b); 614 /* break string */ 615 p = s = lua_tolstring(L, -1, &l); 616 while (l--) 617 { 618 if (*p++ == '\0') /* break? */ 619 { 620 mf((char_u *) s); 621 s = p; 622 } 623 } 624 mf((char_u *) s); 625 lua_pop(L, 2); /* original and modified strings */ 626 } 627 628 #define luaV_newtype(typ,tname,luatyp,luatname) \ 629 static luatyp * \ 630 luaV_new##tname (lua_State *L, typ *obj) \ 631 { \ 632 luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \ 633 *o = obj; \ 634 luaV_setudata(L, obj); /* cache[obj] = udata */ \ 635 luaV_getfield(L, luatname); \ 636 lua_setmetatable(L, -2); \ 637 return o; \ 638 } 639 640 #define luaV_pushtype(typ,tname,luatyp) \ 641 static luatyp * \ 642 luaV_push##tname (lua_State *L, typ *obj) \ 643 { \ 644 luatyp *o = NULL; \ 645 if (obj == NULL) \ 646 lua_pushnil(L); \ 647 else { \ 648 luaV_getudata(L, obj); \ 649 if (lua_isnil(L, -1)) /* not interned? */ \ 650 { \ 651 lua_pop(L, 1); \ 652 o = luaV_new##tname(L, obj); \ 653 } \ 654 else \ 655 o = (luatyp *) lua_touserdata(L, -1); \ 656 } \ 657 return o; \ 658 } 659 660 #define luaV_type_tostring(tname,luatname) \ 661 static int \ 662 luaV_##tname##_tostring (lua_State *L) \ 663 { \ 664 lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \ 665 return 1; \ 666 } 667 668 /* ======= List type ======= */ 669 670 static luaV_List * 671 luaV_newlist (lua_State *L, list_T *lis) 672 { 673 luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List)); 674 *l = lis; 675 lis->lv_refcount++; /* reference in Lua */ 676 luaV_setudata(L, lis); /* cache[lis] = udata */ 677 luaV_getfield(L, LUAVIM_LIST); 678 lua_setmetatable(L, -2); 679 return l; 680 } 681 682 luaV_pushtype(list_T, list, luaV_List) 683 luaV_type_tostring(list, LUAVIM_LIST) 684 685 static int 686 luaV_list_len (lua_State *L) 687 { 688 list_T *l = luaV_unbox(L, luaV_List, 1); 689 lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len); 690 return 1; 691 } 692 693 static int 694 luaV_list_iter (lua_State *L) 695 { 696 listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2)); 697 if (li == NULL) return 0; 698 luaV_pushtypval(L, &li->li_tv); 699 lua_pushlightuserdata(L, (void *) li->li_next); 700 lua_replace(L, lua_upvalueindex(2)); 701 return 1; 702 } 703 704 static int 705 luaV_list_call (lua_State *L) 706 { 707 list_T *l = luaV_unbox(L, luaV_List, 1); 708 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ 709 lua_pushlightuserdata(L, (void *) l->lv_first); 710 lua_pushcclosure(L, luaV_list_iter, 2); 711 return 1; 712 } 713 714 static int 715 luaV_list_index (lua_State *L) 716 { 717 list_T *l = luaV_unbox(L, luaV_List, 1); 718 if (lua_isnumber(L, 2)) /* list item? */ 719 { 720 listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2)); 721 if (li == NULL) 722 lua_pushnil(L); 723 else 724 luaV_pushtypval(L, &li->li_tv); 725 } 726 else if (lua_isstring(L, 2)) /* method? */ 727 { 728 const char *s = lua_tostring(L, 2); 729 if (strncmp(s, "add", 3) == 0 730 || strncmp(s, "insert", 6) == 0) 731 { 732 lua_getmetatable(L, 1); 733 lua_getfield(L, -1, s); 734 } 735 else 736 lua_pushnil(L); 737 } 738 else 739 lua_pushnil(L); 740 return 1; 741 } 742 743 static int 744 luaV_list_newindex (lua_State *L) 745 { 746 list_T *l = luaV_unbox(L, luaV_List, 1); 747 long n = (long) luaL_checkinteger(L, 2); 748 listitem_T *li; 749 if (l->lv_lock) 750 luaL_error(L, "list is locked"); 751 li = list_find(l, n); 752 if (li == NULL) return 0; 753 if (lua_isnil(L, 3)) /* remove? */ 754 { 755 vimlist_remove(l, li, li); 756 clear_tv(&li->li_tv); 757 vim_free(li); 758 } 759 else 760 { 761 typval_T v; 762 luaV_totypval(L, 3, &v); 763 clear_tv(&li->li_tv); 764 copy_tv(&v, &li->li_tv); 765 clear_tv(&v); 766 } 767 return 0; 768 } 769 770 static int 771 luaV_list_add (lua_State *L) 772 { 773 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); 774 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); 775 typval_T v; 776 if (l->lv_lock) 777 luaL_error(L, "list is locked"); 778 lua_settop(L, 2); 779 luaV_totypval(L, 2, &v); 780 if (list_append_tv(l, &v) == FAIL) 781 { 782 clear_tv(&v); 783 luaL_error(L, "Failed to add item to list"); 784 } 785 clear_tv(&v); 786 lua_settop(L, 1); 787 return 1; 788 } 789 790 static int 791 luaV_list_insert (lua_State *L) 792 { 793 luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); 794 list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); 795 long pos = (long) luaL_optinteger(L, 3, 0); 796 listitem_T *li = NULL; 797 typval_T v; 798 if (l->lv_lock) 799 luaL_error(L, "list is locked"); 800 if (pos < l->lv_len) 801 { 802 li = list_find(l, pos); 803 if (li == NULL) 804 luaL_error(L, "invalid position"); 805 } 806 lua_settop(L, 2); 807 luaV_totypval(L, 2, &v); 808 if (list_insert_tv(l, &v, li) == FAIL) 809 { 810 clear_tv(&v); 811 luaL_error(L, "Failed to add item to list"); 812 } 813 clear_tv(&v); 814 lua_settop(L, 1); 815 return 1; 816 } 817 818 static const luaL_Reg luaV_List_mt[] = { 819 {"__tostring", luaV_list_tostring}, 820 {"__len", luaV_list_len}, 821 {"__call", luaV_list_call}, 822 {"__index", luaV_list_index}, 823 {"__newindex", luaV_list_newindex}, 824 {"add", luaV_list_add}, 825 {"insert", luaV_list_insert}, 826 {NULL, NULL} 827 }; 828 829 830 /* ======= Dict type ======= */ 831 832 static luaV_Dict * 833 luaV_newdict (lua_State *L, dict_T *dic) 834 { 835 luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict)); 836 *d = dic; 837 dic->dv_refcount++; /* reference in Lua */ 838 luaV_setudata(L, dic); /* cache[dic] = udata */ 839 luaV_getfield(L, LUAVIM_DICT); 840 lua_setmetatable(L, -2); 841 return d; 842 } 843 844 luaV_pushtype(dict_T, dict, luaV_Dict) 845 luaV_type_tostring(dict, LUAVIM_DICT) 846 847 static int 848 luaV_dict_len (lua_State *L) 849 { 850 dict_T *d = luaV_unbox(L, luaV_Dict, 1); 851 lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used); 852 return 1; 853 } 854 855 static int 856 luaV_dict_iter (lua_State *L UNUSED) 857 { 858 #ifdef FEAT_EVAL 859 hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2)); 860 int n = lua_tointeger(L, lua_upvalueindex(3)); 861 dictitem_T *di; 862 if (n <= 0) return 0; 863 while (HASHITEM_EMPTY(hi)) hi++; 864 di = dict_lookup(hi); 865 lua_pushstring(L, (char *) hi->hi_key); 866 luaV_pushtypval(L, &di->di_tv); 867 lua_pushlightuserdata(L, (void *) (hi + 1)); 868 lua_replace(L, lua_upvalueindex(2)); 869 lua_pushinteger(L, n - 1); 870 lua_replace(L, lua_upvalueindex(3)); 871 return 2; 872 #else 873 return 0; 874 #endif 875 } 876 877 static int 878 luaV_dict_call (lua_State *L) 879 { 880 dict_T *d = luaV_unbox(L, luaV_Dict, 1); 881 hashtab_T *ht = &d->dv_hashtab; 882 lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ 883 lua_pushlightuserdata(L, (void *) ht->ht_array); 884 lua_pushinteger(L, ht->ht_used); /* # remaining items */ 885 lua_pushcclosure(L, luaV_dict_iter, 3); 886 return 1; 887 } 888 889 static int 890 luaV_dict_index (lua_State *L) 891 { 892 dict_T *d = luaV_unbox(L, luaV_Dict, 1); 893 char_u *key = (char_u *) luaL_checkstring(L, 2); 894 dictitem_T *di = dict_find(d, key, -1); 895 if (di == NULL) 896 lua_pushnil(L); 897 else 898 luaV_pushtypval(L, &di->di_tv); 899 return 1; 900 } 901 902 static int 903 luaV_dict_newindex (lua_State *L) 904 { 905 dict_T *d = luaV_unbox(L, luaV_Dict, 1); 906 char_u *key = (char_u *) luaL_checkstring(L, 2); 907 dictitem_T *di; 908 if (d->dv_lock) 909 luaL_error(L, "dict is locked"); 910 di = dict_find(d, key, -1); 911 if (di == NULL) /* non-existing key? */ 912 { 913 if (lua_isnil(L, 3)) return 0; 914 di = dictitem_alloc(key); 915 if (di == NULL) return 0; 916 if (dict_add(d, di) == FAIL) 917 { 918 vim_free(di); 919 return 0; 920 } 921 } 922 else 923 clear_tv(&di->di_tv); 924 if (lua_isnil(L, 3)) /* remove? */ 925 { 926 hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key); 927 hash_remove(&d->dv_hashtab, hi); 928 dictitem_free(di); 929 } 930 else { 931 typval_T v; 932 luaV_totypval(L, 3, &v); 933 copy_tv(&v, &di->di_tv); 934 clear_tv(&v); 935 } 936 return 0; 937 } 938 939 static const luaL_Reg luaV_Dict_mt[] = { 940 {"__tostring", luaV_dict_tostring}, 941 {"__len", luaV_dict_len}, 942 {"__call", luaV_dict_call}, 943 {"__index", luaV_dict_index}, 944 {"__newindex", luaV_dict_newindex}, 945 {NULL, NULL} 946 }; 947 948 949 /* ======= Buffer type ======= */ 950 951 luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER) 952 luaV_pushtype(buf_T, buffer, luaV_Buffer) 953 luaV_type_tostring(buffer, LUAVIM_BUFFER) 954 955 static int 956 luaV_buffer_len(lua_State *L) 957 { 958 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 959 lua_pushinteger(L, b->b_ml.ml_line_count); 960 return 1; 961 } 962 963 static int 964 luaV_buffer_call(lua_State *L) 965 { 966 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 967 lua_settop(L, 1); 968 set_curbuf(b, DOBUF_SPLIT); 969 return 1; 970 } 971 972 static int 973 luaV_buffer_index(lua_State *L) 974 { 975 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 976 linenr_T n = (linenr_T) lua_tointeger(L, 2); 977 if (n > 0 && n <= b->b_ml.ml_line_count) 978 luaV_pushline(L, b, n); 979 else if (lua_isstring(L, 2)) 980 { 981 const char *s = lua_tostring(L, 2); 982 if (strncmp(s, "name", 4) == 0) 983 lua_pushstring(L, (char *) b->b_sfname); 984 else if (strncmp(s, "fname", 5) == 0) 985 lua_pushstring(L, (char *) b->b_ffname); 986 else if (strncmp(s, "number", 6) == 0) 987 lua_pushinteger(L, b->b_fnum); 988 /* methods */ 989 else if (strncmp(s, "insert", 6) == 0 990 || strncmp(s, "next", 4) == 0 991 || strncmp(s, "previous", 8) == 0 992 || strncmp(s, "isvalid", 7) == 0) 993 { 994 lua_getmetatable(L, 1); 995 lua_getfield(L, -1, s); 996 } 997 else 998 lua_pushnil(L); 999 } 1000 else 1001 lua_pushnil(L); 1002 return 1; 1003 } 1004 1005 static int 1006 luaV_buffer_newindex(lua_State *L) 1007 { 1008 buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); 1009 linenr_T n = (linenr_T) luaL_checkinteger(L, 2); 1010 #ifdef HAVE_SANDBOX 1011 luaV_checksandbox(L); 1012 #endif 1013 if (n < 1 || n > b->b_ml.ml_line_count) 1014 luaL_error(L, "invalid line number"); 1015 if (lua_isnil(L, 3)) /* delete line */ 1016 { 1017 buf_T *buf = curbuf; 1018 curbuf = b; 1019 if (u_savedel(n, 1L) == FAIL) 1020 { 1021 curbuf = buf; 1022 luaL_error(L, "cannot save undo information"); 1023 } 1024 else if (ml_delete(n, FALSE) == FAIL) 1025 { 1026 curbuf = buf; 1027 luaL_error(L, "cannot delete line"); 1028 } 1029 else { 1030 deleted_lines_mark(n, 1L); 1031 if (b == curwin->w_buffer) /* fix cursor in current window? */ 1032 { 1033 if (curwin->w_cursor.lnum >= n) 1034 { 1035 if (curwin->w_cursor.lnum > n) 1036 { 1037 curwin->w_cursor.lnum -= 1; 1038 check_cursor_col(); 1039 } 1040 else check_cursor(); 1041 changed_cline_bef_curs(); 1042 } 1043 invalidate_botline(); 1044 } 1045 } 1046 curbuf = buf; 1047 } 1048 else if (lua_isstring(L, 3)) /* update line */ 1049 { 1050 buf_T *buf = curbuf; 1051 curbuf = b; 1052 if (u_savesub(n) == FAIL) 1053 { 1054 curbuf = buf; 1055 luaL_error(L, "cannot save undo information"); 1056 } 1057 else if (ml_replace(n, luaV_toline(L, 3), TRUE) == FAIL) 1058 { 1059 curbuf = buf; 1060 luaL_error(L, "cannot replace line"); 1061 } 1062 else changed_bytes(n, 0); 1063 curbuf = buf; 1064 if (b == curwin->w_buffer) 1065 check_cursor_col(); 1066 } 1067 else 1068 luaL_error(L, "wrong argument to change line"); 1069 return 0; 1070 } 1071 1072 static int 1073 luaV_buffer_insert(lua_State *L) 1074 { 1075 luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER); 1076 buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb); 1077 linenr_T last = b->b_ml.ml_line_count; 1078 linenr_T n = (linenr_T) luaL_optinteger(L, 3, last); 1079 buf_T *buf; 1080 luaL_checktype(L, 2, LUA_TSTRING); 1081 #ifdef HAVE_SANDBOX 1082 luaV_checksandbox(L); 1083 #endif 1084 /* fix insertion line */ 1085 if (n < 0) n = 0; 1086 if (n > last) n = last; 1087 /* insert */ 1088 buf = curbuf; 1089 curbuf = b; 1090 if (u_save(n, n + 1) == FAIL) 1091 { 1092 curbuf = buf; 1093 luaL_error(L, "cannot save undo information"); 1094 } 1095 else if (ml_append(n, luaV_toline(L, 2), 0, FALSE) == FAIL) 1096 { 1097 curbuf = buf; 1098 luaL_error(L, "cannot insert line"); 1099 } 1100 else 1101 appended_lines_mark(n, 1L); 1102 curbuf = buf; 1103 update_screen(VALID); 1104 return 0; 1105 } 1106 1107 static int 1108 luaV_buffer_next(lua_State *L) 1109 { 1110 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 1111 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); 1112 luaV_pushbuffer(L, buf->b_next); 1113 return 1; 1114 } 1115 1116 static int 1117 luaV_buffer_previous(lua_State *L) 1118 { 1119 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 1120 buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); 1121 luaV_pushbuffer(L, buf->b_prev); 1122 return 1; 1123 } 1124 1125 static int 1126 luaV_buffer_isvalid(lua_State *L) 1127 { 1128 luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); 1129 luaV_getudata(L, *b); 1130 lua_pushboolean(L, !lua_isnil(L, -1)); 1131 return 1; 1132 } 1133 1134 static const luaL_Reg luaV_Buffer_mt[] = { 1135 {"__tostring", luaV_buffer_tostring}, 1136 {"__len", luaV_buffer_len}, 1137 {"__call", luaV_buffer_call}, 1138 {"__index", luaV_buffer_index}, 1139 {"__newindex", luaV_buffer_newindex}, 1140 {"insert", luaV_buffer_insert}, 1141 {"next", luaV_buffer_next}, 1142 {"previous", luaV_buffer_previous}, 1143 {"isvalid", luaV_buffer_isvalid}, 1144 {NULL, NULL} 1145 }; 1146 1147 1148 /* ======= Window type ======= */ 1149 1150 luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW) 1151 luaV_pushtype(win_T, window, luaV_Window) 1152 luaV_type_tostring(window, LUAVIM_WINDOW) 1153 1154 static int 1155 luaV_window_call(lua_State *L) 1156 { 1157 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 1158 lua_settop(L, 1); 1159 win_goto(w); 1160 return 1; 1161 } 1162 1163 static int 1164 luaV_window_index(lua_State *L) 1165 { 1166 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 1167 const char *s = luaL_checkstring(L, 2); 1168 if (strncmp(s, "buffer", 6) == 0) 1169 luaV_pushbuffer(L, w->w_buffer); 1170 else if (strncmp(s, "line", 4) == 0) 1171 lua_pushinteger(L, w->w_cursor.lnum); 1172 else if (strncmp(s, "col", 3) == 0) 1173 lua_pushinteger(L, w->w_cursor.col + 1); 1174 #ifdef FEAT_VERTSPLIT 1175 else if (strncmp(s, "width", 5) == 0) 1176 lua_pushinteger(L, W_WIDTH(w)); 1177 #endif 1178 else if (strncmp(s, "height", 6) == 0) 1179 lua_pushinteger(L, w->w_height); 1180 /* methods */ 1181 else if (strncmp(s, "next", 4) == 0 1182 || strncmp(s, "previous", 8) == 0 1183 || strncmp(s, "isvalid", 7) == 0) 1184 { 1185 lua_getmetatable(L, 1); 1186 lua_getfield(L, -1, s); 1187 } 1188 else 1189 lua_pushnil(L); 1190 return 1; 1191 } 1192 1193 static int 1194 luaV_window_newindex (lua_State *L) 1195 { 1196 win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); 1197 const char *s = luaL_checkstring(L, 2); 1198 int v = luaL_checkinteger(L, 3); 1199 if (strncmp(s, "line", 4) == 0) 1200 { 1201 #ifdef HAVE_SANDBOX 1202 luaV_checksandbox(L); 1203 #endif 1204 if (v < 1 || v > w->w_buffer->b_ml.ml_line_count) 1205 luaL_error(L, "line out of range"); 1206 w->w_cursor.lnum = v; 1207 update_screen(VALID); 1208 } 1209 else if (strncmp(s, "col", 3) == 0) 1210 { 1211 #ifdef HAVE_SANDBOX 1212 luaV_checksandbox(L); 1213 #endif 1214 w->w_cursor.col = v - 1; 1215 update_screen(VALID); 1216 } 1217 #ifdef FEAT_VERTSPLIT 1218 else if (strncmp(s, "width", 5) == 0) 1219 { 1220 win_T *win = curwin; 1221 #ifdef FEAT_GUI 1222 need_mouse_correct = TRUE; 1223 #endif 1224 curwin = w; 1225 win_setwidth(v); 1226 curwin = win; 1227 } 1228 #endif 1229 else if (strncmp(s, "height", 6) == 0) 1230 { 1231 win_T *win = curwin; 1232 #ifdef FEAT_GUI 1233 need_mouse_correct = TRUE; 1234 #endif 1235 curwin = w; 1236 win_setheight(v); 1237 curwin = win; 1238 } 1239 else 1240 luaL_error(L, "invalid window property: `%s'", s); 1241 return 0; 1242 } 1243 1244 static int 1245 luaV_window_next(lua_State *L) 1246 { 1247 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1248 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); 1249 luaV_pushwindow(L, win->w_next); 1250 return 1; 1251 } 1252 1253 static int 1254 luaV_window_previous(lua_State *L) 1255 { 1256 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1257 win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); 1258 luaV_pushwindow(L, win->w_prev); 1259 return 1; 1260 } 1261 1262 static int 1263 luaV_window_isvalid(lua_State *L) 1264 { 1265 luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); 1266 luaV_getudata(L, *w); 1267 lua_pushboolean(L, !lua_isnil(L, -1)); 1268 return 1; 1269 } 1270 1271 static const luaL_Reg luaV_Window_mt[] = { 1272 {"__tostring", luaV_window_tostring}, 1273 {"__call", luaV_window_call}, 1274 {"__index", luaV_window_index}, 1275 {"__newindex", luaV_window_newindex}, 1276 {"next", luaV_window_next}, 1277 {"previous", luaV_window_previous}, 1278 {"isvalid", luaV_window_isvalid}, 1279 {NULL, NULL} 1280 }; 1281 1282 1283 /* ======= Vim module ======= */ 1284 1285 static int 1286 luaV_print(lua_State *L) 1287 { 1288 int i, n = lua_gettop(L); /* nargs */ 1289 const char *s; 1290 size_t l; 1291 luaL_Buffer b; 1292 luaL_buffinit(L, &b); 1293 lua_getglobal(L, "tostring"); 1294 for (i = 1; i <= n; i++) 1295 { 1296 lua_pushvalue(L, -1); /* tostring */ 1297 lua_pushvalue(L, i); /* arg */ 1298 lua_call(L, 1, 1); 1299 s = lua_tolstring(L, -1, &l); 1300 if (s == NULL) 1301 return luaL_error(L, "cannot convert to string"); 1302 if (i > 1) luaL_addchar(&b, ' '); /* use space instead of tab */ 1303 luaV_addlstring(&b, s, l, 0); 1304 lua_pop(L, 1); 1305 } 1306 luaL_pushresult(&b); 1307 luaV_msg(L); 1308 return 0; 1309 } 1310 1311 static int 1312 luaV_debug(lua_State *L) 1313 { 1314 lua_settop(L, 0); 1315 lua_getglobal(L, "vim"); 1316 lua_getfield(L, -1, "eval"); 1317 lua_remove(L, -2); /* vim.eval at position 1 */ 1318 for (;;) 1319 { 1320 const char *input; 1321 size_t l; 1322 lua_pushvalue(L, 1); /* vim.eval */ 1323 lua_pushliteral(L, "input('lua_debug> ')"); 1324 lua_call(L, 1, 1); /* return string */ 1325 input = lua_tolstring(L, -1, &l); 1326 if (l == 0 || strcmp(input, "cont") == 0) 1327 return 0; 1328 msg_putchar('\n'); /* avoid outputting on input line */ 1329 if (luaL_loadbuffer(L, input, l, "=(debug command)") 1330 || lua_pcall(L, 0, 0, 0)) 1331 luaV_emsg(L); 1332 lua_settop(L, 1); /* remove eventual returns, but keep vim.eval */ 1333 } 1334 } 1335 1336 static int 1337 luaV_command(lua_State *L) 1338 { 1339 do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); 1340 update_screen(VALID); 1341 return 0; 1342 } 1343 1344 static int 1345 luaV_eval(lua_State *L) 1346 { 1347 typval_T *tv = eval_expr((char_u *) luaL_checkstring(L, 1), NULL); 1348 if (tv == NULL) luaL_error(L, "invalid expression"); 1349 luaV_pushtypval(L, tv); 1350 free_tv(tv); 1351 return 1; 1352 } 1353 1354 static int 1355 luaV_beep(lua_State *L UNUSED) 1356 { 1357 vim_beep(BO_LANG); 1358 return 0; 1359 } 1360 1361 static int 1362 luaV_line(lua_State *L) 1363 { 1364 luaV_pushline(L, curbuf, curwin->w_cursor.lnum); 1365 return 1; 1366 } 1367 1368 static int 1369 luaV_list(lua_State *L) 1370 { 1371 list_T *l = list_alloc(); 1372 if (l == NULL) 1373 lua_pushnil(L); 1374 else 1375 luaV_newlist(L, l); 1376 return 1; 1377 } 1378 1379 static int 1380 luaV_dict(lua_State *L) 1381 { 1382 dict_T *d = dict_alloc(); 1383 if (d == NULL) 1384 lua_pushnil(L); 1385 else 1386 luaV_newdict(L, d); 1387 return 1; 1388 } 1389 1390 static int 1391 luaV_buffer(lua_State *L) 1392 { 1393 buf_T *buf; 1394 if (lua_isstring(L, 1)) /* get by number or name? */ 1395 { 1396 if (lua_isnumber(L, 1)) /* by number? */ 1397 { 1398 int n = lua_tointeger(L, 1); 1399 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 1400 if (buf->b_fnum == n) break; 1401 } 1402 else { /* by name */ 1403 size_t l; 1404 const char *s = lua_tolstring(L, 1, &l); 1405 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 1406 { 1407 if (buf->b_ffname == NULL || buf->b_sfname == NULL) 1408 { 1409 if (l == 0) break; 1410 } 1411 else if (strncmp(s, (char *)buf->b_ffname, l) == 0 1412 || strncmp(s, (char *)buf->b_sfname, l) == 0) 1413 break; 1414 } 1415 } 1416 } 1417 else 1418 buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ 1419 luaV_pushbuffer(L, buf); 1420 return 1; 1421 } 1422 1423 static int 1424 luaV_window(lua_State *L) 1425 { 1426 win_T *win; 1427 if (lua_isnumber(L, 1)) /* get by number? */ 1428 { 1429 int n = lua_tointeger(L, 1); 1430 for (win = firstwin; win != NULL; win = win->w_next, n--) 1431 if (n == 1) break; 1432 } 1433 else 1434 win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ 1435 luaV_pushwindow(L, win); 1436 return 1; 1437 } 1438 1439 static int 1440 luaV_open(lua_State *L) 1441 { 1442 char_u *s = NULL; 1443 #ifdef HAVE_SANDBOX 1444 luaV_checksandbox(L); 1445 #endif 1446 if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1); 1447 luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED)); 1448 return 1; 1449 } 1450 1451 static int 1452 luaV_type(lua_State *L) 1453 { 1454 luaL_checkany(L, 1); 1455 if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */ 1456 { 1457 lua_settop(L, 1); 1458 if (lua_getmetatable(L, 1)) 1459 { 1460 luaV_getfield(L, LUAVIM_LIST); 1461 if (lua_rawequal(L, -1, 2)) 1462 { 1463 lua_pushstring(L, "list"); 1464 return 1; 1465 } 1466 luaV_getfield(L, LUAVIM_DICT); 1467 if (lua_rawequal(L, -1, 2)) 1468 { 1469 lua_pushstring(L, "dict"); 1470 return 1; 1471 } 1472 luaV_getfield(L, LUAVIM_BUFFER); 1473 if (lua_rawequal(L, -1, 2)) 1474 { 1475 lua_pushstring(L, "buffer"); 1476 return 1; 1477 } 1478 luaV_getfield(L, LUAVIM_WINDOW); 1479 if (lua_rawequal(L, -1, 2)) 1480 { 1481 lua_pushstring(L, "window"); 1482 return 1; 1483 } 1484 } 1485 } 1486 lua_pushstring(L, luaL_typename(L, 1)); /* fallback */ 1487 return 1; 1488 } 1489 1490 static const luaL_Reg luaV_module[] = { 1491 {"command", luaV_command}, 1492 {"eval", luaV_eval}, 1493 {"beep", luaV_beep}, 1494 {"line", luaV_line}, 1495 {"list", luaV_list}, 1496 {"dict", luaV_dict}, 1497 {"buffer", luaV_buffer}, 1498 {"window", luaV_window}, 1499 {"open", luaV_open}, 1500 {"type", luaV_type}, 1501 {NULL, NULL} 1502 }; 1503 1504 /* for freeing list, dict, buffer and window objects; lightuserdata as arg */ 1505 static int 1506 luaV_free(lua_State *L) 1507 { 1508 lua_pushnil(L); 1509 luaV_setudata(L, lua_touserdata(L, 1)); 1510 return 0; 1511 } 1512 1513 static int 1514 luaV_luaeval (lua_State *L) 1515 { 1516 luaL_Buffer b; 1517 size_t l; 1518 const char *str = lua_tolstring(L, 1, &l); 1519 typval_T *arg = (typval_T *) lua_touserdata(L, 2); 1520 typval_T *rettv = (typval_T *) lua_touserdata(L, 3); 1521 luaL_buffinit(L, &b); 1522 luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1); 1523 luaL_addlstring(&b, str, l); 1524 luaL_pushresult(&b); 1525 str = lua_tolstring(L, -1, &l); 1526 if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */ 1527 { 1528 luaV_emsg(L); 1529 return 0; 1530 } 1531 luaV_pushtypval(L, arg); 1532 if (lua_pcall(L, 1, 1, 0)) /* running error? */ 1533 { 1534 luaV_emsg(L); 1535 return 0; 1536 } 1537 luaV_totypval(L, -1, rettv); 1538 return 0; 1539 } 1540 1541 static int 1542 luaV_setref (lua_State *L) 1543 { 1544 int copyID = lua_tointeger(L, 1); 1545 int abort = FALSE; 1546 typval_T tv; 1547 1548 luaV_getfield(L, LUAVIM_LIST); 1549 luaV_getfield(L, LUAVIM_DICT); 1550 lua_pushnil(L); 1551 /* traverse cache table */ 1552 while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) 1553 { 1554 lua_getmetatable(L, -1); 1555 if (lua_rawequal(L, -1, 2)) /* list? */ 1556 { 1557 tv.v_type = VAR_LIST; 1558 tv.vval.v_list = (list_T *) lua_touserdata(L, 4); /* key */ 1559 abort = set_ref_in_item(&tv, copyID, NULL, NULL); 1560 } 1561 else if (lua_rawequal(L, -1, 3)) /* dict? */ 1562 { 1563 tv.v_type = VAR_DICT; 1564 tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */ 1565 abort = set_ref_in_item(&tv, copyID, NULL, NULL); 1566 } 1567 lua_pop(L, 2); /* metatable and value */ 1568 } 1569 lua_pushinteger(L, abort); 1570 return 1; 1571 } 1572 1573 static int 1574 luaopen_vim(lua_State *L) 1575 { 1576 /* set cache table */ 1577 lua_newtable(L); 1578 lua_newtable(L); 1579 lua_pushstring(L, "v"); 1580 lua_setfield(L, -2, "__mode"); 1581 lua_setmetatable(L, -2); /* cache is weak-valued */ 1582 /* print */ 1583 lua_pushcfunction(L, luaV_print); 1584 lua_setglobal(L, "print"); 1585 /* debug.debug */ 1586 lua_getglobal(L, "debug"); 1587 lua_pushcfunction(L, luaV_debug); 1588 lua_setfield(L, -2, "debug"); 1589 lua_pop(L, 1); 1590 /* free */ 1591 lua_pushlightuserdata(L, (void *) LUAVIM_FREE); 1592 lua_pushvalue(L, 1); /* cache table */ 1593 lua_pushcclosure(L, luaV_free, 1); 1594 lua_rawset(L, LUA_REGISTRYINDEX); 1595 /* luaeval */ 1596 lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL); 1597 lua_pushvalue(L, 1); /* cache table */ 1598 lua_pushcclosure(L, luaV_luaeval, 1); 1599 lua_rawset(L, LUA_REGISTRYINDEX); 1600 /* setref */ 1601 lua_pushlightuserdata(L, (void *) LUAVIM_SETREF); 1602 lua_pushvalue(L, 1); /* cache table */ 1603 lua_pushcclosure(L, luaV_setref, 1); 1604 lua_rawset(L, LUA_REGISTRYINDEX); 1605 /* register */ 1606 luaV_newmetatable(L, LUAVIM_LIST); 1607 lua_pushvalue(L, 1); 1608 luaV_openlib(L, luaV_List_mt, 1); 1609 luaV_newmetatable(L, LUAVIM_DICT); 1610 lua_pushvalue(L, 1); 1611 luaV_openlib(L, luaV_Dict_mt, 1); 1612 luaV_newmetatable(L, LUAVIM_BUFFER); 1613 lua_pushvalue(L, 1); /* cache table */ 1614 luaV_openlib(L, luaV_Buffer_mt, 1); 1615 luaV_newmetatable(L, LUAVIM_WINDOW); 1616 lua_pushvalue(L, 1); /* cache table */ 1617 luaV_openlib(L, luaV_Window_mt, 1); 1618 lua_newtable(L); /* vim table */ 1619 lua_pushvalue(L, 1); /* cache table */ 1620 luaV_openlib(L, luaV_module, 1); 1621 lua_setglobal(L, LUAVIM_NAME); 1622 return 0; 1623 } 1624 1625 static lua_State * 1626 luaV_newstate(void) 1627 { 1628 lua_State *L = luaL_newstate(); 1629 luaL_openlibs(L); /* core libs */ 1630 lua_pushcfunction(L, luaopen_vim); /* vim */ 1631 lua_call(L, 0, 0); 1632 return L; 1633 } 1634 1635 static void 1636 luaV_setrange(lua_State *L, int line1, int line2) 1637 { 1638 lua_getglobal(L, LUAVIM_NAME); 1639 lua_pushinteger(L, line1); 1640 lua_setfield(L, -2, "firstline"); 1641 lua_pushinteger(L, line2); 1642 lua_setfield(L, -2, "lastline"); 1643 lua_pop(L, 1); /* vim table */ 1644 } 1645 1646 1647 /* ======= Interface ======= */ 1648 1649 static lua_State *L = NULL; 1650 1651 static int 1652 lua_isopen(void) 1653 { 1654 return L != NULL; 1655 } 1656 1657 static int 1658 lua_init(void) 1659 { 1660 if (!lua_isopen()) 1661 { 1662 #ifdef DYNAMIC_LUA 1663 if (!lua_enabled(TRUE)) 1664 { 1665 EMSG(_("Lua library cannot be loaded.")); 1666 return FAIL; 1667 } 1668 #endif 1669 L = luaV_newstate(); 1670 } 1671 return OK; 1672 } 1673 1674 void 1675 lua_end(void) 1676 { 1677 if (lua_isopen()) 1678 { 1679 lua_close(L); 1680 L = NULL; 1681 #ifdef DYNAMIC_LUA 1682 end_dynamic_lua(); 1683 #endif 1684 } 1685 } 1686 1687 /* ex commands */ 1688 void 1689 ex_lua(exarg_T *eap) 1690 { 1691 char *script; 1692 if (lua_init() == FAIL) return; 1693 script = (char *) script_get(eap, eap->arg); 1694 if (!eap->skip) 1695 { 1696 char *s = (script) ? script : (char *) eap->arg; 1697 luaV_setrange(L, eap->line1, eap->line2); 1698 if (luaL_loadbuffer(L, s, strlen(s), LUAVIM_CHUNKNAME) 1699 || lua_pcall(L, 0, 0, 0)) 1700 luaV_emsg(L); 1701 } 1702 if (script != NULL) vim_free(script); 1703 } 1704 1705 void 1706 ex_luado(exarg_T *eap) 1707 { 1708 linenr_T l; 1709 const char *s = (const char *) eap->arg; 1710 luaL_Buffer b; 1711 size_t len; 1712 if (lua_init() == FAIL) return; 1713 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) 1714 { 1715 EMSG(_("cannot save undo information")); 1716 return; 1717 } 1718 luaV_setrange(L, eap->line1, eap->line2); 1719 luaL_buffinit(L, &b); 1720 luaL_addlstring(&b, "return function(line, linenr) ", 30); /* header */ 1721 luaL_addlstring(&b, s, strlen(s)); 1722 luaL_addlstring(&b, " end", 4); /* footer */ 1723 luaL_pushresult(&b); 1724 s = lua_tolstring(L, -1, &len); 1725 if (luaL_loadbuffer(L, s, len, LUAVIM_CHUNKNAME)) 1726 { 1727 luaV_emsg(L); 1728 lua_pop(L, 1); /* function body */ 1729 return; 1730 } 1731 lua_call(L, 0, 1); 1732 lua_replace(L, -2); /* function -> body */ 1733 for (l = eap->line1; l <= eap->line2; l++) 1734 { 1735 lua_pushvalue(L, -1); /* function */ 1736 luaV_pushline(L, curbuf, l); /* current line as arg */ 1737 lua_pushinteger(L, l); /* current line number as arg */ 1738 if (lua_pcall(L, 2, 1, 0)) 1739 { 1740 luaV_emsg(L); 1741 break; 1742 } 1743 if (lua_isstring(L, -1)) /* update line? */ 1744 { 1745 #ifdef HAVE_SANDBOX 1746 luaV_checksandbox(L); 1747 #endif 1748 ml_replace(l, luaV_toline(L, -1), TRUE); 1749 changed_bytes(l, 0); 1750 lua_pop(L, 1); /* result from luaV_toline */ 1751 } 1752 lua_pop(L, 1); /* line */ 1753 } 1754 lua_pop(L, 1); /* function */ 1755 check_cursor(); 1756 update_screen(NOT_VALID); 1757 } 1758 1759 void 1760 ex_luafile(exarg_T *eap) 1761 { 1762 if (lua_init() == FAIL) 1763 return; 1764 if (!eap->skip) 1765 { 1766 luaV_setrange(L, eap->line1, eap->line2); 1767 if (luaL_loadfile(L, (char *) eap->arg) || lua_pcall(L, 0, 0, 0)) 1768 luaV_emsg(L); 1769 } 1770 } 1771 1772 #define luaV_freetype(typ,tname) \ 1773 void \ 1774 lua_##tname##_free(typ *o) \ 1775 { \ 1776 if (!lua_isopen()) return; \ 1777 luaV_getfield(L, LUAVIM_FREE); \ 1778 lua_pushlightuserdata(L, (void *) o); \ 1779 lua_call(L, 1, 0); \ 1780 } 1781 1782 luaV_freetype(buf_T, buffer) 1783 luaV_freetype(win_T, window) 1784 1785 void 1786 do_luaeval (char_u *str, typval_T *arg, typval_T *rettv) 1787 { 1788 lua_init(); 1789 luaV_getfield(L, LUAVIM_LUAEVAL); 1790 lua_pushstring(L, (char *) str); 1791 lua_pushlightuserdata(L, (void *) arg); 1792 lua_pushlightuserdata(L, (void *) rettv); 1793 lua_call(L, 3, 0); 1794 } 1795 1796 int 1797 set_ref_in_lua (int copyID) 1798 { 1799 int aborted = 0; 1800 1801 if (lua_isopen()) 1802 { 1803 luaV_getfield(L, LUAVIM_SETREF); 1804 /* call the function with 1 arg, getting 1 result back */ 1805 lua_pushinteger(L, copyID); 1806 lua_call(L, 1, 1); 1807 /* get the result */ 1808 aborted = lua_tointeger(L, -1); 1809 /* pop result off the stack */ 1810 lua_pop(L, 1); 1811 } 1812 return aborted; 1813 } 1814 1815 #endif 1816