diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-04-26 17:39:38 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-04-26 17:39:38 -0300 |
commit | 4eb49163c662e7c1546754774acf75b893ea23df (patch) | |
tree | e7745d5283a0282af13568fc1c008d0adb8f4ce1 | |
parent | 79cb336d74697ca38d6d2f2068781086cfaa9076 (diff) | |
download | lua-4eb49163c662e7c1546754774acf75b893ea23df.tar.gz lua-4eb49163c662e7c1546754774acf75b893ea23df.tar.bz2 lua-4eb49163c662e7c1546754774acf75b893ea23df.zip |
error handler in 'lua.c' tries '__tostring' metamethod if error
message is not a string
-rw-r--r-- | ldblib.c | 23 | ||||
-rw-r--r-- | lua.c | 39 |
2 files changed, 33 insertions, 29 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldblib.c,v 1.104 2005/12/29 15:32:11 roberto Exp roberto $ | 2 | ** $Id: ldblib.c,v 1.105 2006/09/11 14:07:24 roberto Exp roberto $ |
3 | ** Interface from Lua to its debug API | 3 | ** Interface from Lua to its debug API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -319,21 +319,18 @@ static int db_debug (lua_State *L) { | |||
319 | #define LEVELS2 10 /* size of the second part of the stack */ | 319 | #define LEVELS2 10 /* size of the second part of the stack */ |
320 | 320 | ||
321 | static int db_errorfb (lua_State *L) { | 321 | static int db_errorfb (lua_State *L) { |
322 | int level; | 322 | lua_Debug ar; |
323 | int firstpart = 1; /* still before eventual `...' */ | 323 | int firstpart = 1; /* still before eventual `...' */ |
324 | int arg; | 324 | int arg; |
325 | lua_State *L1 = getthread(L, &arg); | 325 | lua_State *L1 = getthread(L, &arg); |
326 | lua_Debug ar; | 326 | const char *msg = lua_tostring(L, arg + 1); |
327 | if (lua_isnumber(L, arg+2)) { | 327 | int level = (lua_isnumber(L, arg + 2)) ? |
328 | level = (int)lua_tointeger(L, arg+2); | 328 | (int)lua_tointeger(L, arg + 2) : |
329 | lua_pop(L, 1); | 329 | (L == L1) ? 1 : 0; /* level 0 may be this own function */ |
330 | } | 330 | lua_settop(L, ++arg); |
331 | else | 331 | if (msg) lua_pushfstring(L, "%s\n", msg); |
332 | level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ | 332 | else if (!lua_isnil(L, arg)) /* is there a non-string 'msg'? */ |
333 | if (lua_gettop(L) == arg) | 333 | return 1; /* return it untouched */ |
334 | lua_pushliteral(L, ""); | ||
335 | else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ | ||
336 | else lua_pushliteral(L, "\n"); | ||
337 | lua_pushliteral(L, "stack traceback:"); | 334 | lua_pushliteral(L, "stack traceback:"); |
338 | while (lua_getstack(L1, level++, &ar)) { | 335 | while (lua_getstack(L1, level++, &ar)) { |
339 | if (level > LEVELS1 && firstpart) { | 336 | if (level > LEVELS1 && firstpart) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.c,v 1.163 2006/09/18 14:03:18 roberto Exp roberto $ | 2 | ** $Id: lua.c,v 1.164 2006/10/10 17:40:17 roberto Exp roberto $ |
3 | ** Lua stand-alone interpreter | 3 | ** Lua stand-alone interpreter |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -41,7 +41,7 @@ static void laction (int i) { | |||
41 | 41 | ||
42 | static void print_usage (void) { | 42 | static void print_usage (void) { |
43 | fprintf(stderr, | 43 | fprintf(stderr, |
44 | "usage: %s [options] [script [args]].\n" | 44 | "usage: %s [options] [script [args]]\n" |
45 | "Available options are:\n" | 45 | "Available options are:\n" |
46 | " -e stat execute string " LUA_QL("stat") "\n" | 46 | " -e stat execute string " LUA_QL("stat") "\n" |
47 | " -l name require library " LUA_QL("name") "\n" | 47 | " -l name require library " LUA_QL("name") "\n" |
@@ -73,20 +73,27 @@ static int report (lua_State *L, int status) { | |||
73 | } | 73 | } |
74 | 74 | ||
75 | 75 | ||
76 | static int traceback (lua_State *L) { | 76 | static int gettraceback (lua_State *L) { |
77 | lua_getfield(L, LUA_GLOBALSINDEX, "debug"); | 77 | lua_getfield(L, LUA_GLOBALSINDEX, "debug"); |
78 | if (!lua_istable(L, -1)) { | 78 | if (!lua_istable(L, -1)) return 0; |
79 | lua_pop(L, 1); | 79 | lua_getfield(L, -1, "traceback"); /* check 'debug.traceback' */ |
80 | return 1; | 80 | if (!lua_isfunction(L, -1)) return 0; |
81 | } | 81 | return 1; /* there is a function 'debug.traceback' */ |
82 | lua_getfield(L, -1, "traceback"); | 82 | } |
83 | if (!lua_isfunction(L, -1)) { | 83 | |
84 | lua_pop(L, 2); | 84 | |
85 | return 1; | 85 | static int traceback (lua_State *L) { |
86 | if (lua_isnoneornil(L, 1)) /* no error object? */ | ||
87 | return 1; /* keep it that way */ | ||
88 | if (!gettraceback(L)) /* no 'debug.traceback' function? */ | ||
89 | lua_pushvalue(L, 1); /* keep original message */ | ||
90 | else { | ||
91 | lua_pushvalue(L, 1); /* pass error message */ | ||
92 | lua_pushinteger(L, 2); /* skip this function and traceback */ | ||
93 | lua_call(L, 2, 1); /* call traceback */ | ||
86 | } | 94 | } |
87 | lua_pushvalue(L, 1); /* pass error message */ | 95 | if (!lua_isstring(L, -1) && !luaL_callmeta(L, 1, "__tostring")) |
88 | lua_pushinteger(L, 2); /* skip this function and traceback */ | 96 | lua_pushliteral(L, "(no error message)"); |
89 | lua_call(L, 2, 1); /* call debug.traceback */ | ||
90 | return 1; | 97 | return 1; |
91 | } | 98 | } |
92 | 99 | ||
@@ -96,6 +103,7 @@ static int docall (lua_State *L, int narg, int clear) { | |||
96 | int base = lua_gettop(L) - narg; /* function index */ | 103 | int base = lua_gettop(L) - narg; /* function index */ |
97 | lua_pushcfunction(L, traceback); /* push traceback function */ | 104 | lua_pushcfunction(L, traceback); /* push traceback function */ |
98 | lua_insert(L, base); /* put it under chunk and args */ | 105 | lua_insert(L, base); /* put it under chunk and args */ |
106 | globalL = L; /* to be available to 'laction' */ | ||
99 | signal(SIGINT, laction); | 107 | signal(SIGINT, laction); |
100 | status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); | 108 | status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); |
101 | signal(SIGINT, SIG_DFL); | 109 | signal(SIGINT, SIG_DFL); |
@@ -160,7 +168,7 @@ static const char *get_prompt (lua_State *L, int firstline) { | |||
160 | } | 168 | } |
161 | 169 | ||
162 | /* mark in error messages for incomplete statements */ | 170 | /* mark in error messages for incomplete statements */ |
163 | #define mark LUA_QL("<eof>") | 171 | #define mark "<eof>" |
164 | #define marklen (sizeof(mark) - 1) | 172 | #define marklen (sizeof(mark) - 1) |
165 | 173 | ||
166 | static int incomplete (lua_State *L, int status) { | 174 | static int incomplete (lua_State *L, int status) { |
@@ -344,7 +352,6 @@ static int pmain (lua_State *L) { | |||
344 | char **argv = s->argv; | 352 | char **argv = s->argv; |
345 | int script; | 353 | int script; |
346 | int has_i = 0, has_v = 0, has_e = 0; | 354 | int has_i = 0, has_v = 0, has_e = 0; |
347 | globalL = L; | ||
348 | if (argv[0] && argv[0][0]) progname = argv[0]; | 355 | if (argv[0] && argv[0][0]) progname = argv[0]; |
349 | lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ | 356 | lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ |
350 | luaL_openlibs(L); /* open libraries */ | 357 | luaL_openlibs(L); /* open libraries */ |