diff options
| -rw-r--r-- | lauxlib.c | 54 | ||||
| -rw-r--r-- | lauxlib.h | 4 | ||||
| -rw-r--r-- | ldblib.c | 51 | ||||
| -rw-r--r-- | lua.c | 27 |
4 files changed, 69 insertions, 67 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lauxlib.c,v 1.168 2007/06/21 13:48:04 roberto Exp roberto $ | 2 | ** $Id: lauxlib.c,v 1.169 2007/06/21 14:09:59 roberto Exp roberto $ |
| 3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -89,6 +89,58 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { | |||
| 89 | return lua_error(L); | 89 | return lua_error(L); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | |||
| 93 | #define LEVELS1 12 /* size of the first part of the stack */ | ||
| 94 | #define LEVELS2 10 /* size of the second part of the stack */ | ||
| 95 | |||
| 96 | |||
| 97 | static void pushfuncname (lua_State *L, lua_Debug *ar) { | ||
| 98 | if (*ar->namewhat != '\0') /* is there a name? */ | ||
| 99 | lua_pushfstring(L, "function " LUA_QS, ar->name); | ||
| 100 | else if (*ar->what == 'm') /* main? */ | ||
| 101 | lua_pushfstring(L, "main chunk"); | ||
| 102 | else if (*ar->what == 'C' || *ar->what == 't') | ||
| 103 | lua_pushliteral(L, " ?"); /* C function or tail call */ | ||
| 104 | else | ||
| 105 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); | ||
| 106 | } | ||
| 107 | |||
| 108 | |||
| 109 | static int countlevels (lua_State *L) { | ||
| 110 | lua_Debug ar; | ||
| 111 | int level = 1; | ||
| 112 | while (lua_getstack(L, level, &ar)) level++; | ||
| 113 | return level; | ||
| 114 | } | ||
| 115 | |||
| 116 | |||
| 117 | LUALIB_API const char *luaL_traceback (lua_State *L, lua_State *L1, | ||
| 118 | const char *msg, int level) { | ||
| 119 | lua_Debug ar; | ||
| 120 | int top = lua_gettop(L); | ||
| 121 | int numlevels = countlevels(L1); | ||
| 122 | int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; | ||
| 123 | if (msg) lua_pushfstring(L, "%s\n", msg); | ||
| 124 | lua_pushliteral(L, "stack traceback:"); | ||
| 125 | while (lua_getstack(L1, level++, &ar)) { | ||
| 126 | if (level == mark) { /* too many levels? */ | ||
| 127 | lua_pushliteral(L, "\n\t..."); /* add a '...' */ | ||
| 128 | level = numlevels - LEVELS2; /* and skip to last ones */ | ||
| 129 | } | ||
| 130 | else { | ||
| 131 | lua_getinfo(L1, "Sln", &ar); | ||
| 132 | lua_pushfstring(L, "\n\t%s:", ar.short_src); | ||
| 133 | if (ar.currentline > 0) | ||
| 134 | lua_pushfstring(L, "%d:", ar.currentline); | ||
| 135 | lua_pushliteral(L, " in "); | ||
| 136 | pushfuncname(L, &ar); | ||
| 137 | lua_concat(L, lua_gettop(L) - top); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | lua_concat(L, lua_gettop(L) - top); | ||
| 141 | return lua_tostring(L, -1); | ||
| 142 | } | ||
| 143 | |||
| 92 | /* }====================================================== */ | 144 | /* }====================================================== */ |
| 93 | 145 | ||
| 94 | 146 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lauxlib.h,v 1.90 2007/05/15 18:46:12 roberto Exp roberto $ | 2 | ** $Id: lauxlib.h,v 1.91 2007/06/21 13:48:04 roberto Exp roberto $ |
| 3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -78,6 +78,8 @@ LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, | |||
| 78 | LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, | 78 | LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, |
| 79 | const char *fname, int szhint); | 79 | const char *fname, int szhint); |
| 80 | 80 | ||
| 81 | LUALIB_API const char *luaL_traceback (lua_State *L, lua_State *L1, | ||
| 82 | const char *msg, int level); | ||
| 81 | 83 | ||
| 82 | 84 | ||
| 83 | 85 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldblib.c,v 1.105 2006/09/11 14:07:24 roberto Exp roberto $ | 2 | ** $Id: ldblib.c,v 1.106 2007/04/26 20:39:38 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 | */ |
| @@ -315,55 +315,16 @@ static int db_debug (lua_State *L) { | |||
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | 317 | ||
| 318 | #define LEVELS1 12 /* size of the first part of the stack */ | ||
| 319 | #define LEVELS2 10 /* size of the second part of the stack */ | ||
| 320 | |||
| 321 | static int db_errorfb (lua_State *L) { | 318 | static int db_errorfb (lua_State *L) { |
| 322 | lua_Debug ar; | ||
| 323 | int firstpart = 1; /* still before eventual `...' */ | ||
| 324 | int arg; | 319 | int arg; |
| 325 | lua_State *L1 = getthread(L, &arg); | 320 | lua_State *L1 = getthread(L, &arg); |
| 326 | const char *msg = lua_tostring(L, arg + 1); | 321 | const char *msg = lua_tostring(L, arg + 1); |
| 327 | int level = (lua_isnumber(L, arg + 2)) ? | 322 | if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ |
| 328 | (int)lua_tointeger(L, arg + 2) : | 323 | lua_pushvalue(L, arg + 1); /* return it untouched */ |
| 329 | (L == L1) ? 1 : 0; /* level 0 may be this own function */ | 324 | else { |
| 330 | lua_settop(L, ++arg); | 325 | int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0); |
| 331 | if (msg) lua_pushfstring(L, "%s\n", msg); | 326 | luaL_traceback(L, L1, msg, level); |
| 332 | else if (!lua_isnil(L, arg)) /* is there a non-string 'msg'? */ | ||
| 333 | return 1; /* return it untouched */ | ||
| 334 | lua_pushliteral(L, "stack traceback:"); | ||
| 335 | while (lua_getstack(L1, level++, &ar)) { | ||
| 336 | if (level > LEVELS1 && firstpart) { | ||
| 337 | /* no more than `LEVELS2' more levels? */ | ||
| 338 | if (!lua_getstack(L1, level+LEVELS2, &ar)) | ||
| 339 | level--; /* keep going */ | ||
| 340 | else { | ||
| 341 | lua_pushliteral(L, "\n\t..."); /* too many levels */ | ||
| 342 | while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ | ||
| 343 | level++; | ||
| 344 | } | ||
| 345 | firstpart = 0; | ||
| 346 | continue; | ||
| 347 | } | ||
| 348 | lua_pushliteral(L, "\n\t"); | ||
| 349 | lua_getinfo(L1, "Snl", &ar); | ||
| 350 | lua_pushfstring(L, "%s:", ar.short_src); | ||
| 351 | if (ar.currentline > 0) | ||
| 352 | lua_pushfstring(L, "%d:", ar.currentline); | ||
| 353 | if (*ar.namewhat != '\0') /* is there a name? */ | ||
| 354 | lua_pushfstring(L, " in function " LUA_QS, ar.name); | ||
| 355 | else { | ||
| 356 | if (*ar.what == 'm') /* main? */ | ||
| 357 | lua_pushfstring(L, " in main chunk"); | ||
| 358 | else if (*ar.what == 'C' || *ar.what == 't') | ||
| 359 | lua_pushliteral(L, " ?"); /* C function or tail call */ | ||
| 360 | else | ||
| 361 | lua_pushfstring(L, " in function <%s:%d>", | ||
| 362 | ar.short_src, ar.linedefined); | ||
| 363 | } | ||
| 364 | lua_concat(L, lua_gettop(L) - arg); | ||
| 365 | } | 327 | } |
| 366 | lua_concat(L, lua_gettop(L) - arg); | ||
| 367 | return 1; | 328 | return 1; |
| 368 | } | 329 | } |
| 369 | 330 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lua.c,v 1.164 2006/10/10 17:40:17 roberto Exp roberto $ | 2 | ** $Id: lua.c,v 1.165 2007/04/26 20:39:38 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 | */ |
| @@ -73,27 +73,14 @@ static int report (lua_State *L, int status) { | |||
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | 75 | ||
| 76 | static int gettraceback (lua_State *L) { | ||
| 77 | lua_getfield(L, LUA_GLOBALSINDEX, "debug"); | ||
| 78 | if (!lua_istable(L, -1)) return 0; | ||
| 79 | lua_getfield(L, -1, "traceback"); /* check 'debug.traceback' */ | ||
| 80 | if (!lua_isfunction(L, -1)) return 0; | ||
| 81 | return 1; /* there is a function 'debug.traceback' */ | ||
| 82 | } | ||
| 83 | |||
| 84 | |||
| 85 | static int traceback (lua_State *L) { | 76 | static int traceback (lua_State *L) { |
| 86 | if (lua_isnoneornil(L, 1)) /* no error object? */ | 77 | const char *msg = lua_tostring(L, 1); |
| 87 | return 1; /* keep it that way */ | 78 | if (msg) |
| 88 | if (!gettraceback(L)) /* no 'debug.traceback' function? */ | 79 | luaL_traceback(L, L, msg, 2); |
| 89 | lua_pushvalue(L, 1); /* keep original message */ | 80 | else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ |
| 90 | else { | 81 | if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ |
| 91 | lua_pushvalue(L, 1); /* pass error message */ | 82 | lua_pushliteral(L, "(no error message)"); |
| 92 | lua_pushinteger(L, 2); /* skip this function and traceback */ | ||
| 93 | lua_call(L, 2, 1); /* call traceback */ | ||
| 94 | } | 83 | } |
| 95 | if (!lua_isstring(L, -1) && !luaL_callmeta(L, 1, "__tostring")) | ||
| 96 | lua_pushliteral(L, "(no error message)"); | ||
| 97 | return 1; | 84 | return 1; |
| 98 | } | 85 | } |
| 99 | 86 | ||
