aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-02-27 15:18:19 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-02-27 15:18:19 -0300
commitb4033173253a0ce443a27d95dcb6c575f1bc272e (patch)
treed696139b3e5e7b76c20d83163da8643430503939
parent9bf05e7364295cc6322f2ebb413994a2f42c4a80 (diff)
downloadlua-b4033173253a0ce443a27d95dcb6c575f1bc272e.tar.gz
lua-b4033173253a0ce443a27d95dcb6c575f1bc272e.tar.bz2
lua-b4033173253a0ce443a27d95dcb6c575f1bc272e.zip
error functions search global space for a name for a function when
no other name is available
-rw-r--r--lauxlib.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/lauxlib.c b/lauxlib.c
index 532ce052..cb7698e2 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -40,13 +40,65 @@
40#define LEVELS2 10 /* size of the second part of the stack */ 40#define LEVELS2 10 /* size of the second part of the stack */
41 41
42 42
43
44/*
45** search for 'objidx' in table at index -1.
46** return 1 + string at top if find a good name.
47*/
48static int findfield (lua_State *L, int objidx, int level) {
49 int found = 0;
50 if (level == 0 || !lua_istable(L, -1))
51 return 0; /* not found */
52 lua_pushnil(L); /* start 'next' loop */
53 while (!found && lua_next(L, -2)) { /* for each pair in table */
54 if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */
55 if (lua_rawequal(L, objidx, -1)) { /* found object? */
56 lua_pop(L, 1); /* remove value (but keep name) */
57 return 1;
58 }
59 else if (findfield(L, objidx, level - 1)) { /* try recursively */
60 lua_remove(L, -2); /* remove table (but keep name) */
61 lua_pushliteral(L, ".");
62 lua_insert(L, -2); /* place '.' between the two names */
63 lua_concat(L, 3);
64 return 1;
65 }
66 }
67 lua_pop(L, 1); /* remove value */
68 }
69 return 0; /* not found */
70}
71
72
73static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
74 int top = lua_gettop(L);
75 lua_getinfo(L, "f", ar); /* push function */
76 lua_pushvalue(L, LUA_GLOBALSINDEX); /* push global table */
77 if (findfield(L, top + 1, 2)) {
78 lua_replace(L, top + 1); /* move name to proper place */
79 lua_pop(L, 1); /* remove other pushed value */
80 return 1;
81 }
82 else {
83 lua_settop(L, top); /* remove function and global table */
84 return 0;
85 }
86}
87
88
43static void pushfuncname (lua_State *L, lua_Debug *ar) { 89static void pushfuncname (lua_State *L, lua_Debug *ar) {
44 if (*ar->namewhat != '\0') /* is there a name? */ 90 if (*ar->namewhat != '\0') /* is there a name? */
45 lua_pushfstring(L, "function " LUA_QS, ar->name); 91 lua_pushfstring(L, "function " LUA_QS, ar->name);
46 else if (*ar->what == 'm') /* main? */ 92 else if (*ar->what == 'm') /* main? */
47 lua_pushfstring(L, "main chunk"); 93 lua_pushfstring(L, "main chunk");
48 else if (*ar->what == 'C' || *ar->what == 't') 94 else if (*ar->what == 'C' || *ar->what == 't') {
49 lua_pushliteral(L, "?"); /* C function or tail call */ 95 if (pushglobalfuncname(L, ar)) {
96 lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
97 lua_remove(L, -2); /* remove name */
98 }
99 else
100 lua_pushliteral(L, "?"); /* C function or tail call */
101 }
50 else 102 else
51 lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); 103 lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
52} 104}
@@ -106,7 +158,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
106 return luaL_error(L, "calling " LUA_QS " on bad self", ar.name); 158 return luaL_error(L, "calling " LUA_QS " on bad self", ar.name);
107 } 159 }
108 if (ar.name == NULL) 160 if (ar.name == NULL)
109 ar.name = "?"; 161 ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
110 return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", 162 return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
111 narg, ar.name, extramsg); 163 narg, ar.name, extramsg);
112} 164}