diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-05-28 15:50:40 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-05-28 15:50:40 -0300 |
| commit | 2b8b53864c6b8655aa7198699884075b3e2f15fa (patch) | |
| tree | c21e66f343f32ecd5db8df63e31980f4f9b2a3de | |
| parent | b293ae0577bebaca7169cb4f041b800641d5e2c4 (diff) | |
| download | lua-2b8b53864c6b8655aa7198699884075b3e2f15fa.tar.gz lua-2b8b53864c6b8655aa7198699884075b3e2f15fa.tar.bz2 lua-2b8b53864c6b8655aa7198699884075b3e2f15fa.zip | |
Improvements in 'luaL_traceback'
'luaL_traceback' changed to use an aux buffer instead of concats.
This should reduce the quantity of garbage it generates (in the
form of intermediate strings) while producing a trackback.
It also added information about the number of levels skipped when
skipping levels in a trace.
| -rw-r--r-- | lauxlib.c | 53 |
1 files changed, 29 insertions, 24 deletions
| @@ -46,8 +46,8 @@ | |||
| 46 | 46 | ||
| 47 | 47 | ||
| 48 | /* | 48 | /* |
| 49 | ** search for 'objidx' in table at index -1. | 49 | ** Search for 'objidx' in table at index -1. ('objidx' must be an |
| 50 | ** return 1 + string at top if find a good name. | 50 | ** absolute index.) Return 1 + string at top if it found a good name. |
| 51 | */ | 51 | */ |
| 52 | static int findfield (lua_State *L, int objidx, int level) { | 52 | static int findfield (lua_State *L, int objidx, int level) { |
| 53 | if (level == 0 || !lua_istable(L, -1)) | 53 | if (level == 0 || !lua_istable(L, -1)) |
| @@ -60,10 +60,10 @@ static int findfield (lua_State *L, int objidx, int level) { | |||
| 60 | return 1; | 60 | return 1; |
| 61 | } | 61 | } |
| 62 | else if (findfield(L, objidx, level - 1)) { /* try recursively */ | 62 | else if (findfield(L, objidx, level - 1)) { /* try recursively */ |
| 63 | lua_remove(L, -2); /* remove table (but keep name) */ | 63 | /* stack: lib_name, lib_table, field_name (top) */ |
| 64 | lua_pushliteral(L, "."); | 64 | lua_pushliteral(L, "."); /* place '.' between the two names */ |
| 65 | lua_insert(L, -2); /* place '.' between the two names */ | 65 | lua_replace(L, -3); /* (in the slot ocupied by table) */ |
| 66 | lua_concat(L, 3); | 66 | lua_concat(L, 3); /* lib_name.field_name */ |
| 67 | return 1; | 67 | return 1; |
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| @@ -86,8 +86,8 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { | |||
| 86 | lua_pushstring(L, name + 3); /* push name without prefix */ | 86 | lua_pushstring(L, name + 3); /* push name without prefix */ |
| 87 | lua_remove(L, -2); /* remove original name */ | 87 | lua_remove(L, -2); /* remove original name */ |
| 88 | } | 88 | } |
| 89 | lua_copy(L, -1, top + 1); /* move name to proper place */ | 89 | lua_copy(L, -1, top + 1); /* copy name to proper place */ |
| 90 | lua_pop(L, 2); /* remove pushed values */ | 90 | lua_settop(L, top + 1); /* remove table "loaded" an name copy */ |
| 91 | return 1; | 91 | return 1; |
| 92 | } | 92 | } |
| 93 | else { | 93 | else { |
| @@ -130,32 +130,37 @@ static int lastlevel (lua_State *L) { | |||
| 130 | 130 | ||
| 131 | LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, | 131 | LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, |
| 132 | const char *msg, int level) { | 132 | const char *msg, int level) { |
| 133 | luaL_Buffer b; | ||
| 133 | lua_Debug ar; | 134 | lua_Debug ar; |
| 134 | int top = lua_gettop(L); | ||
| 135 | int last = lastlevel(L1); | 135 | int last = lastlevel(L1); |
| 136 | int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; | 136 | int limit2show = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; |
| 137 | if (msg) | 137 | luaL_buffinit(L, &b); |
| 138 | lua_pushfstring(L, "%s\n", msg); | 138 | if (msg) { |
| 139 | luaL_checkstack(L, 10, NULL); | 139 | luaL_addstring(&b, msg); |
| 140 | lua_pushliteral(L, "stack traceback:"); | 140 | luaL_addchar(&b, '\n'); |
| 141 | } | ||
| 142 | luaL_addstring(&b, "stack traceback:"); | ||
| 141 | while (lua_getstack(L1, level++, &ar)) { | 143 | while (lua_getstack(L1, level++, &ar)) { |
| 142 | if (n1-- == 0) { /* too many levels? */ | 144 | if (limit2show-- == 0) { /* too many levels? */ |
| 143 | lua_pushliteral(L, "\n\t..."); /* add a '...' */ | 145 | int n = last - level - LEVELS2 + 1; /* number of levels to skip */ |
| 144 | level = last - LEVELS2 + 1; /* and skip to last ones */ | 146 | lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n); |
| 147 | luaL_addvalue(&b); /* add warning about skip */ | ||
| 148 | level += n; /* and skip to last levels */ | ||
| 145 | } | 149 | } |
| 146 | else { | 150 | else { |
| 147 | lua_getinfo(L1, "Slnt", &ar); | 151 | lua_getinfo(L1, "Slnt", &ar); |
| 148 | lua_pushfstring(L, "\n\t%s:", ar.short_src); | 152 | if (ar.currentline <= 0) |
| 149 | if (ar.currentline > 0) | 153 | lua_pushfstring(L, "\n\t%s: in ", ar.short_src); |
| 150 | lua_pushfstring(L, "%d:", ar.currentline); | 154 | else |
| 151 | lua_pushliteral(L, " in "); | 155 | lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline); |
| 156 | luaL_addvalue(&b); | ||
| 152 | pushfuncname(L, &ar); | 157 | pushfuncname(L, &ar); |
| 158 | luaL_addvalue(&b); | ||
| 153 | if (ar.istailcall) | 159 | if (ar.istailcall) |
| 154 | lua_pushliteral(L, "\n\t(...tail calls...)"); | 160 | luaL_addstring(&b, "\n\t(...tail calls...)"); |
| 155 | lua_concat(L, lua_gettop(L) - top); | ||
| 156 | } | 161 | } |
| 157 | } | 162 | } |
| 158 | lua_concat(L, lua_gettop(L) - top); | 163 | luaL_pushresult(&b); |
| 159 | } | 164 | } |
| 160 | 165 | ||
| 161 | /* }====================================================== */ | 166 | /* }====================================================== */ |
