diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lauxlib.h | 2 | ||||
| -rw-r--r-- | src/lib_base.c | 2 | ||||
| -rw-r--r-- | src/lib_debug.c | 50 | ||||
| -rw-r--r-- | src/lj_debug.c | 51 | ||||
| -rw-r--r-- | src/luajit.c | 14 |
5 files changed, 59 insertions, 60 deletions
diff --git a/src/lauxlib.h b/src/lauxlib.h index b0f66d68..fed1491b 100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h | |||
| @@ -82,6 +82,8 @@ LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, | |||
| 82 | const char *mode); | 82 | const char *mode); |
| 83 | LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, | 83 | LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, |
| 84 | const char *name, const char *mode); | 84 | const char *name, const char *mode); |
| 85 | LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, | ||
| 86 | int level); | ||
| 85 | 87 | ||
| 86 | 88 | ||
| 87 | /* | 89 | /* |
diff --git a/src/lib_base.c b/src/lib_base.c index 6f664eb6..568216e1 100644 --- a/src/lib_base.c +++ b/src/lib_base.c | |||
| @@ -320,7 +320,7 @@ LJLIB_ASM(tostring) LJLIB_REC(.) | |||
| 320 | s = strV(lj_lib_upvalue(L, -(int32_t)itype(o))); | 320 | s = strV(lj_lib_upvalue(L, -(int32_t)itype(o))); |
| 321 | } else { | 321 | } else { |
| 322 | if (tvisfunc(o) && isffunc(funcV(o))) | 322 | if (tvisfunc(o) && isffunc(funcV(o))) |
| 323 | lua_pushfstring(L, "function: fast#%d", funcV(o)->c.ffid); | 323 | lua_pushfstring(L, "function: builtin#%d", funcV(o)->c.ffid); |
| 324 | else | 324 | else |
| 325 | lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1)); | 325 | lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1)); |
| 326 | /* Note: lua_pushfstring calls the GC which may invalidate o. */ | 326 | /* Note: lua_pushfstring calls the GC which may invalidate o. */ |
diff --git a/src/lib_debug.c b/src/lib_debug.c index 07b025af..06750266 100644 --- a/src/lib_debug.c +++ b/src/lib_debug.c | |||
| @@ -383,55 +383,13 @@ LJLIB_CF(debug_debug) | |||
| 383 | 383 | ||
| 384 | LJLIB_CF(debug_traceback) | 384 | LJLIB_CF(debug_traceback) |
| 385 | { | 385 | { |
| 386 | int level; | ||
| 387 | int firstpart = 1; /* still before eventual `...' */ | ||
| 388 | int arg; | 386 | int arg; |
| 389 | lua_State *L1 = getthread(L, &arg); | 387 | lua_State *L1 = getthread(L, &arg); |
| 390 | lua_Debug ar; | 388 | const char *msg = lua_tostring(L, arg+1); |
| 391 | if (lua_isnumber(L, arg+2)) { | 389 | if (msg == NULL && L->top > L->base+arg) |
| 392 | level = (int)lua_tointeger(L, arg+2); | 390 | L->top = L->base+arg+1; |
| 393 | lua_pop(L, 1); | ||
| 394 | } | ||
| 395 | else | 391 | else |
| 396 | level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ | 392 | luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1))); |
| 397 | if (lua_gettop(L) == arg) | ||
| 398 | lua_pushliteral(L, ""); | ||
| 399 | else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ | ||
| 400 | else lua_pushliteral(L, "\n"); | ||
| 401 | lua_pushliteral(L, "stack traceback:"); | ||
| 402 | while (lua_getstack(L1, level++, &ar)) { | ||
| 403 | if (level > LEVELS1 && firstpart) { | ||
| 404 | /* no more than `LEVELS2' more levels? */ | ||
| 405 | if (!lua_getstack(L1, level+LEVELS2, &ar)) { | ||
| 406 | level--; /* keep going */ | ||
| 407 | } else { | ||
| 408 | lua_pushliteral(L, "\n\t..."); /* too many levels */ | ||
| 409 | /* This only works with LuaJIT 2.x. Avoids O(n^2) behaviour. */ | ||
| 410 | lua_getstack(L1, -10, &ar); | ||
| 411 | level = ar.i_ci - LEVELS2; | ||
| 412 | } | ||
| 413 | firstpart = 0; | ||
| 414 | continue; | ||
| 415 | } | ||
| 416 | lua_pushliteral(L, "\n\t"); | ||
| 417 | lua_getinfo(L1, "Snl", &ar); | ||
| 418 | lua_pushfstring(L, "%s:", ar.short_src); | ||
| 419 | if (ar.currentline > 0) | ||
| 420 | lua_pushfstring(L, "%d:", ar.currentline); | ||
| 421 | if (*ar.namewhat != '\0') { /* is there a name? */ | ||
| 422 | lua_pushfstring(L, " in function " LUA_QS, ar.name); | ||
| 423 | } else { | ||
| 424 | if (*ar.what == 'm') /* main? */ | ||
| 425 | lua_pushfstring(L, " in main chunk"); | ||
| 426 | else if (*ar.what == 'C' || *ar.what == 't') | ||
| 427 | lua_pushliteral(L, " ?"); /* C function or tail call */ | ||
| 428 | else | ||
| 429 | lua_pushfstring(L, " in function <%s:%d>", | ||
| 430 | ar.short_src, ar.linedefined); | ||
| 431 | } | ||
| 432 | lua_concat(L, lua_gettop(L) - arg); | ||
| 433 | } | ||
| 434 | lua_concat(L, lua_gettop(L) - arg); | ||
| 435 | return 1; | 393 | return 1; |
| 436 | } | 394 | } |
| 437 | 395 | ||
diff --git a/src/lj_debug.c b/src/lj_debug.c index 0e26cd7c..4f4c4bb1 100644 --- a/src/lj_debug.c +++ b/src/lj_debug.c | |||
| @@ -543,3 +543,54 @@ LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar) | |||
| 543 | } | 543 | } |
| 544 | } | 544 | } |
| 545 | 545 | ||
| 546 | /* Number of frames for the leading and trailing part of a traceback. */ | ||
| 547 | #define TRACEBACK_LEVELS1 12 | ||
| 548 | #define TRACEBACK_LEVELS2 10 | ||
| 549 | |||
| 550 | LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, | ||
| 551 | int level) | ||
| 552 | { | ||
| 553 | int top = (int)(L->top - L->base); | ||
| 554 | int lim = TRACEBACK_LEVELS1; | ||
| 555 | lua_Debug ar; | ||
| 556 | if (msg) lua_pushfstring(L, "%s\n", msg); | ||
| 557 | lua_pushliteral(L, "stack traceback:"); | ||
| 558 | while (lua_getstack(L1, level++, &ar)) { | ||
| 559 | GCfunc *fn; | ||
| 560 | if (level > lim) { | ||
| 561 | if (!lua_getstack(L1, level + TRACEBACK_LEVELS2, &ar)) { | ||
| 562 | level--; | ||
| 563 | } else { | ||
| 564 | lua_pushliteral(L, "\n\t..."); | ||
| 565 | lua_getstack(L1, -10, &ar); | ||
| 566 | level = ar.i_ci - TRACEBACK_LEVELS2; | ||
| 567 | } | ||
| 568 | lim = 2147483647; | ||
| 569 | continue; | ||
| 570 | } | ||
| 571 | lua_getinfo(L1, "Snlf", &ar); | ||
| 572 | fn = funcV(L1->top-1); L1->top--; | ||
| 573 | if (isffunc(fn) && !*ar.namewhat) | ||
| 574 | lua_pushfstring(L, "\n\t[builtin#%d]:", fn->c.ffid); | ||
| 575 | else | ||
| 576 | lua_pushfstring(L, "\n\t%s:", ar.short_src); | ||
| 577 | if (ar.currentline > 0) | ||
| 578 | lua_pushfstring(L, "%d:", ar.currentline); | ||
| 579 | if (*ar.namewhat) { | ||
| 580 | lua_pushfstring(L, " in function " LUA_QS, ar.name); | ||
| 581 | } else { | ||
| 582 | if (*ar.what == 'm') { | ||
| 583 | lua_pushliteral(L, " in main chunk"); | ||
| 584 | } else if (*ar.what == 'C') { | ||
| 585 | lua_pushfstring(L, " at %p", fn->c.f); | ||
| 586 | } else { | ||
| 587 | lua_pushfstring(L, " in function <%s:%d>", | ||
| 588 | ar.short_src, ar.linedefined); | ||
| 589 | } | ||
| 590 | } | ||
| 591 | if ((int)(L->top - L->base) - top >= 15) | ||
| 592 | lua_concat(L, (int)(L->top - L->base) - top); | ||
| 593 | } | ||
| 594 | lua_concat(L, (int)(L->top - L->base) - top); | ||
| 595 | } | ||
| 596 | |||
diff --git a/src/luajit.c b/src/luajit.c index 22628aaf..a9476372 100644 --- a/src/luajit.c +++ b/src/luajit.c | |||
| @@ -106,19 +106,7 @@ static int traceback(lua_State *L) | |||
| 106 | return 1; /* Return non-string error object. */ | 106 | return 1; /* Return non-string error object. */ |
| 107 | lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */ | 107 | lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */ |
| 108 | } | 108 | } |
| 109 | lua_getfield(L, LUA_GLOBALSINDEX, "debug"); | 109 | luaL_traceback(L, L, lua_tostring(L, 1), 1); |
| 110 | if (!lua_istable(L, -1)) { | ||
| 111 | lua_pop(L, 1); | ||
| 112 | return 1; | ||
| 113 | } | ||
| 114 | lua_getfield(L, -1, "traceback"); | ||
| 115 | if (!lua_isfunction(L, -1)) { | ||
| 116 | lua_pop(L, 2); | ||
| 117 | return 1; | ||
| 118 | } | ||
| 119 | lua_pushvalue(L, 1); /* Push error message. */ | ||
| 120 | lua_pushinteger(L, 2); /* Skip this function and debug.traceback(). */ | ||
| 121 | lua_call(L, 2, 1); /* Call debug.traceback(). */ | ||
| 122 | return 1; | 110 | return 1; |
| 123 | } | 111 | } |
| 124 | 112 | ||
