diff --git a/lauxlib.c b/lauxlib.c index 532ce052..cb7698e2 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -40,13 +40,65 @@ #define LEVELS2 10 /* size of the second part of the stack */ + +/* +** search for 'objidx' in table at index -1. +** return 1 + string at top if find a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + int found = 0; + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (!found && lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushvalue(L, LUA_GLOBALSINDEX); /* push global table */ + if (findfield(L, top + 1, 2)) { + lua_replace(L, top + 1); /* move name to proper place */ + lua_pop(L, 1); /* remove other pushed value */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + + static void pushfuncname (lua_State *L, lua_Debug *ar) { if (*ar->namewhat != '\0') /* is there a name? */ lua_pushfstring(L, "function " LUA_QS, ar->name); else if (*ar->what == 'm') /* main? */ lua_pushfstring(L, "main chunk"); - else if (*ar->what == 'C' || *ar->what == 't') - lua_pushliteral(L, "?"); /* C function or tail call */ + else if (*ar->what == 'C' || *ar->what == 't') { + if (pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); /* C function or tail call */ + } else lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); } @@ -106,7 +158,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { return luaL_error(L, "calling " LUA_QS " on bad self", ar.name); } if (ar.name == NULL) - ar.name = "?"; + ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", narg, ar.name, extramsg); }