Sorry, previous patch has problems on system which without dynamic lua. Attached new patch have fixed it. Please check it.
-- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php
# HG changeset patch # Parent 2e546d787ee8d12f7ea1b22172b9d491652c1ed7 Fix confused references related with an environment table diff -r 2e546d787ee8 src/if_lua.c --- a/src/if_lua.c Thu Jan 05 09:14:30 2012 +0900 +++ b/src/if_lua.c Sun Jan 08 19:19:42 2012 +0900 @@ -73,6 +73,7 @@ #define lua_gettop dll_lua_gettop #define lua_settop dll_lua_settop #define lua_pushvalue dll_lua_pushvalue +#define lua_insert dll_lua_insert #define lua_replace dll_lua_replace #define lua_isnumber dll_lua_isnumber #define lua_isstring dll_lua_isstring @@ -135,6 +136,7 @@ int (*dll_lua_gettop) (lua_State *L); void (*dll_lua_settop) (lua_State *L, int idx); void (*dll_lua_pushvalue) (lua_State *L, int idx); +void (*dll_lua_insert) (lua_State *L, int idx); void (*dll_lua_replace) (lua_State *L, int idx); int (*dll_lua_isnumber) (lua_State *L, int idx); int (*dll_lua_isstring) (lua_State *L, int idx); @@ -204,6 +206,7 @@ {"lua_gettop", (luaV_function) &dll_lua_gettop}, {"lua_settop", (luaV_function) &dll_lua_settop}, {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue}, + {"lua_insert", (luaV_function) &dll_lua_insert}, {"lua_replace", (luaV_function) &dll_lua_replace}, {"lua_isnumber", (luaV_function) &dll_lua_isnumber}, {"lua_isstring", (luaV_function) &dll_lua_isstring}, @@ -297,6 +300,143 @@ /* ======= Internal ======= */ +/** + * Push a lua object which associated to the pointer to the stack, and return + * 1. If no objects associated, nil is pushed to the stack, and return 0. + * + * [+1, 0, -] + */ + static int +luaV_get_associated_luavalue(lua_State *L, void *rawptr) +{ + lua_pushlightuserdata(L, rawptr); + lua_rawget(L, LUA_REGISTRYINDEX); + return lua_isnil(L, -1) ? 0 : 1; +} + +/** + * A lua object is associated with a C native pointer return 1, otherwise 0. + * + * [0, 0, -] + */ + static int +luaV_is_associated_luavalue(lua_State *L, void *rawptr) +{ + int retval = luaV_get_associated_luavalue(L, rawptr); + lua_pop(L, 1); /* obj */ + return retval; +} + +/** + * Associate a lua object which specified by index with a C native pointer. + * + * [0, 0, -] + */ + static void +luaV_set_associated_luavalue(lua_State *L, void *rawptr, int idx) +{ + lua_pushvalue(L, idx); + lua_pushlightuserdata(L, rawptr); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + lua_pop(L, 1); +} + +/** + * Reset any associated values to associated with a C native pointer. + * + * [0, 0, -] + */ + static void +luaV_reset_associated_luavalue(lua_State *L, void *rawptr) +{ + lua_pushnil(L); + luaV_set_associated_luavalue(L, rawptr, -1); + lua_pop(L, 1); +} + +/** + * Setup a cache table be identified by cacheKey. + * + * [0, 0, -] + */ + static void +luaV_open_cachetable(lua_State *L, void *cacheKey) +{ + lua_pushlightuserdata(L, cacheKey); + lua_newtable(L); + lua_rawset(L, LUA_REGISTRYINDEX); +} + +/** + * Dispose a cache table be identified by cacheKey. + * + * [0, 0, -] + */ + static void +luaV_close_cachetable(lua_State *L, void *cacheKey) +{ + lua_pushlightuserdata(L, cacheKey); + lua_pushnil(L); + lua_rawset(L, LUA_REGISTRYINDEX); +} + +/** + * Push a lua object associated with a pointer in the cachetable which + * associated with cacheKey to the stack, and return 1. If no objects + * associated, nil is pushed to the stack, and return 0. + * + * [+1, 0, -] + */ + static int +luaV_get_cachetable(lua_State *L, void *cacheKey, void *rawptr) +{ + lua_pushlightuserdata(L, cacheKey); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) + { + /* + * FIXME: This will causes if luaV_open_cachetable() isn't called. It + * may be failed by assertion or so. + */ + lua_pop(L, 1); /* {not table} */ + lua_pushnil(L); + return 0; + } + else + { + lua_pushlightuserdata(L, rawptr); + lua_rawget(L, -2); + lua_insert(L, -2); /* (table, object) -> (object, table) */ + lua_pop(L, 1); /* table */ + return lua_isnil(L, -1) ? 0 : 1; + } +} + +/** + * [0, 0, -] + */ + static void +luaV_set_cachetable(lua_State *L, void *cacheKey, void *rawptr, int idx) +{ + lua_pushvalue(L, idx); + + /* Push a cacheable for cacheKey. */ + lua_pushlightuserdata(L, cacheKey); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) + { + lua_pop(L, 2); /* idx, {not table} */ + } + else + { + lua_pushlightuserdata(L, rawptr); + lua_pushvalue(L, -3); + lua_rawset(L, -3); + lua_pop(L, 2); /* idx, table */ + } +} + static void luaV_newmetatable(lua_State *L, const char *tname) { @@ -335,7 +475,7 @@ } static void -luaV_pushtypval(lua_State *L, typval_T *tv) +luaV_pushtypval2(lua_State *L, void *cacheKey, typval_T *tv) { if (tv == NULL) luaL_error(L, "null type"); switch (tv->v_type) @@ -357,20 +497,17 @@ if (l != NULL) { /* check cache */ - lua_pushlightuserdata(L, (void *) l); - lua_rawget(L, LUA_ENVIRONINDEX); - if (lua_isnil(L, -1)) /* not interned? */ - { + if (!luaV_get_cachetable(L, cacheKey, (void *)l)) + { + /* Push a new table (array) to the stack. */ listitem_T *li; int n = 0; lua_pop(L, 1); /* nil */ lua_newtable(L); - lua_pushlightuserdata(L, (void *) l); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_ENVIRONINDEX); + luaV_set_cachetable(L, cacheKey, (void *)l, -1); for (li = l->lv_first; li != NULL; li = li->li_next) { - luaV_pushtypval(L, &li->li_tv); + luaV_pushtypval2(L, cacheKey, &li->li_tv); lua_rawseti(L, -2, ++n); } } @@ -384,24 +521,21 @@ if (d != NULL) { /* check cache */ - lua_pushlightuserdata(L, (void *) d); - lua_rawget(L, LUA_ENVIRONINDEX); - if (lua_isnil(L, -1)) /* not interned? */ - { + if (!luaV_get_cachetable(L, cacheKey, (void *)d)) + { + /* Push a new table (dict) to the stack. */ hashtab_T *ht = &d->dv_hashtab; hashitem_T *hi; int n = ht->ht_used; /* remaining items */ lua_pop(L, 1); /* nil */ lua_newtable(L); - lua_pushlightuserdata(L, (void *) d); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_ENVIRONINDEX); + luaV_set_cachetable(L, cacheKey, (void *)d, -1); for (hi = ht->ht_array; n > 0; hi++) { if (!HASHITEM_EMPTY(hi)) { dictitem_T *di = dict_lookup(hi); - luaV_pushtypval(L, &di->di_tv); + luaV_pushtypval2(L, cacheKey, &di->di_tv); lua_setfield(L, -2, (char *) hi->hi_key); n--; } @@ -416,6 +550,19 @@ } } +/** + * [+1, 0, -] + */ + static void +luaV_pushtypval(lua_State *L, typval_T *tv) +{ + void *cacheKey = (void *)tv; + + luaV_open_cachetable(L, cacheKey); + luaV_pushtypval2(L, cacheKey, tv); + luaV_close_cachetable(L, cacheKey); +} + /* similar to luaL_addlstring, but replaces \0 with \n if toline and * \n with \0 otherwise */ static void @@ -489,13 +636,9 @@ { luaV_Buffer *b = (luaV_Buffer *) lua_newuserdata(L, sizeof(luaV_Buffer)); *b = buf; - lua_pushlightuserdata(L, (void *) buf); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[buf] = udata */ - /* to avoid GC, store as key in env */ - lua_pushvalue(L, -1); - lua_pushboolean(L, 1); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ + + luaV_set_associated_luavalue(L, (void *)buf, -1); + /* set metatable */ luaV_getfield(L, LUAVIM_BUFFER); lua_setmetatable(L, -2); @@ -508,12 +651,11 @@ luaV_Buffer *b = NULL; if (buf == NULL) lua_pushnil(L); - else { - lua_pushlightuserdata(L, (void *) buf); - lua_rawget(L, LUA_ENVIRONINDEX); - if (lua_isnil(L, -1)) /* not interned? */ - { - lua_pop(L, 1); + else + { + if (!luaV_get_associated_luavalue(L, (void *)buf)) + { + lua_pop(L, 1); /* nil */ b = luaV_newbuffer(L, buf); } else @@ -553,6 +695,14 @@ { luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); linenr_T n = (linenr_T) lua_tointeger(L, 2); + + /* Check validity of a buffer. */ + if (!luaV_is_associated_luavalue(L, (void *)(*b))) + { + lua_pushnil(L); + return 1; + } + if (n > 0 && n <= (*b)->b_ml.ml_line_count) luaV_pushline(L, *b, n); else if (lua_isstring(L, 2)) @@ -702,9 +852,8 @@ luaV_buffer_isvalid(lua_State *L) { luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); - lua_pushlightuserdata(L, (void *) (*b)); - lua_rawget(L, LUA_ENVIRONINDEX); - lua_pushboolean(L, !lua_isnil(L, -1)); + lua_pushboolean(L, + luaV_get_associated_luavalue(L, (void *)(*b))); return 1; } @@ -729,13 +878,9 @@ { luaV_Window *w = (luaV_Window *) lua_newuserdata(L, sizeof(luaV_Window)); *w = win; - lua_pushlightuserdata(L, (void *) win); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[win] = udata */ - /* to avoid GC, store as key in env */ - lua_pushvalue(L, -1); - lua_pushboolean(L, 1); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ + + luaV_set_associated_luavalue(L, (void *)win, -1); + /* set metatable */ luaV_getfield(L, LUAVIM_WINDOW); lua_setmetatable(L, -2); @@ -748,15 +893,15 @@ luaV_Window *w = NULL; if (win == NULL) lua_pushnil(L); - else { - lua_pushlightuserdata(L, (void *) win); - lua_rawget(L, LUA_ENVIRONINDEX); - if (lua_isnil(L, -1)) /* not interned? */ - { - lua_pop(L, 1); + else + { + if (!luaV_get_associated_luavalue(L, (void *)win)) + { + lua_pop(L, 1); /* nil */ w = luaV_newwindow(L, win); } - else w = (luaV_Window *) lua_touserdata(L, -1); + else + w = (luaV_Window *) lua_touserdata(L, -1); } return w; } @@ -784,6 +929,14 @@ { luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); const char *s = luaL_checkstring(L, 2); + + /* Check validity of a window. */ + if (!luaV_is_associated_luavalue(L, (void *)(*w))) + { + lua_pushnil(L); + return 1; + } + if (strncmp(s, "buffer", 6) == 0) luaV_pushbuffer(L, (*w)->w_buffer); else if (strncmp(s, "line", 4) == 0) @@ -880,9 +1033,8 @@ luaV_window_isvalid(lua_State *L) { luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); - lua_pushlightuserdata(L, (void *) (*w)); - lua_rawget(L, LUA_ENVIRONINDEX); - lua_pushboolean(L, !lua_isnil(L, -1)); + lua_pushboolean(L, + luaV_get_associated_luavalue(L, (void *)(*w))); return 1; } @@ -1071,15 +1223,7 @@ static int luaV_free(lua_State *L) { - lua_pushvalue(L, 1); /* lightudata */ - lua_rawget(L, LUA_ENVIRONINDEX); - if (!lua_isnil(L, -1)) - { - lua_pushnil(L); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = nil */ - lua_pushnil(L); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[lightudata] = nil */ - } + luaV_reset_associated_luavalue(L, lua_touserdata(L, 1)); return 0; } @@ -1099,13 +1243,6 @@ static int luaopen_vim(lua_State *L) { - /* set environment */ - lua_newtable(L); - lua_newtable(L); - lua_pushliteral(L, "v"); - lua_setfield(L, -2, "__mode"); - lua_setmetatable(L, -2); - lua_replace(L, LUA_ENVIRONINDEX); /* print */ lua_pushcfunction(L, luaV_print); lua_setglobal(L, "print");