diff options
author | Mike Pall <mike> | 2012-10-01 20:45:30 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2012-10-01 20:45:30 +0200 |
commit | fcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c (patch) | |
tree | 4bce654a35af804e16eb55324aa92f9ab550a984 /src | |
parent | 3ad61689cf11ae73fef5dfe12f7ccb5fe539622e (diff) | |
download | luajit-fcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c.tar.gz luajit-fcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c.tar.bz2 luajit-fcddd5a3a0269f30df0c0da6e9ff89d3e70d0e2c.zip |
From Lua 5.2: Add luaL_traceback().
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 | ||