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