diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-07-07 10:37:08 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-07-07 10:37:08 -0300 |
commit | 79fee990241bc29c9306d7cee655653ff88b3d0c (patch) | |
tree | 9679215722d4b70f51be8593b3dd488d591fb813 /ldblib.c | |
parent | a73ded21535c79a081cae16b12482e3e70441e6c (diff) | |
download | lua-79fee990241bc29c9306d7cee655653ff88b3d0c.tar.gz lua-79fee990241bc29c9306d7cee655653ff88b3d0c.tar.bz2 lua-79fee990241bc29c9306d7cee655653ff88b3d0c.zip |
`debug' library can operate over other threads
Diffstat (limited to 'ldblib.c')
-rw-r--r-- | ldblib.c | 134 |
1 files changed, 92 insertions, 42 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldblib.c,v 1.79 2003/03/11 12:24:34 roberto Exp roberto $ | 2 | ** $Id: ldblib.c,v 1.80 2003/04/03 13:35:34 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 | */ |
@@ -32,24 +32,39 @@ static void settabsi (lua_State *L, const char *i, int v) { | |||
32 | } | 32 | } |
33 | 33 | ||
34 | 34 | ||
35 | static lua_State *getthread (lua_State *L, int *arg) { | ||
36 | if (lua_isthread(L, 1)) { | ||
37 | *arg = 1; | ||
38 | return lua_tothread(L, 1); | ||
39 | } | ||
40 | else { | ||
41 | *arg = 0; | ||
42 | return L; | ||
43 | } | ||
44 | } | ||
45 | |||
46 | |||
35 | static int getinfo (lua_State *L) { | 47 | static int getinfo (lua_State *L) { |
36 | lua_Debug ar; | 48 | lua_Debug ar; |
37 | const char *options = luaL_optstring(L, 2, "flnSu"); | 49 | int arg; |
38 | if (lua_isnumber(L, 1)) { | 50 | lua_State *L1 = getthread(L, &arg); |
39 | if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) { | 51 | const char *options = luaL_optstring(L, arg+2, "flnSu"); |
52 | if (lua_isnumber(L, arg+1)) { | ||
53 | if (!lua_getstack(L1, (int)(lua_tonumber(L, arg+1)), &ar)) { | ||
40 | lua_pushnil(L); /* level out of range */ | 54 | lua_pushnil(L); /* level out of range */ |
41 | return 1; | 55 | return 1; |
42 | } | 56 | } |
43 | } | 57 | } |
44 | else if (lua_isfunction(L, 1)) { | 58 | else if (lua_isfunction(L, arg+1)) { |
45 | lua_pushfstring(L, ">%s", options); | 59 | lua_pushfstring(L, ">%s", options); |
46 | options = lua_tostring(L, -1); | 60 | options = lua_tostring(L, -1); |
47 | lua_pushvalue(L, 1); | 61 | lua_pushvalue(L, arg+1); |
62 | lua_xmove(L, L1, 1); | ||
48 | } | 63 | } |
49 | else | 64 | else |
50 | return luaL_argerror(L, 1, "function or level expected"); | 65 | return luaL_argerror(L, arg+1, "function or level expected"); |
51 | if (!lua_getinfo(L, options, &ar)) | 66 | if (!lua_getinfo(L1, options, &ar)) |
52 | return luaL_argerror(L, 2, "invalid option"); | 67 | return luaL_argerror(L, arg+2, "invalid option"); |
53 | lua_newtable(L); | 68 | lua_newtable(L); |
54 | for (; *options; options++) { | 69 | for (; *options; options++) { |
55 | switch (*options) { | 70 | switch (*options) { |
@@ -71,7 +86,10 @@ static int getinfo (lua_State *L) { | |||
71 | break; | 86 | break; |
72 | case 'f': | 87 | case 'f': |
73 | lua_pushliteral(L, "func"); | 88 | lua_pushliteral(L, "func"); |
74 | lua_pushvalue(L, -3); | 89 | if (L == L1) |
90 | lua_pushvalue(L, -3); | ||
91 | else | ||
92 | lua_xmove(L1, L, 1); | ||
75 | lua_rawset(L, -3); | 93 | lua_rawset(L, -3); |
76 | break; | 94 | break; |
77 | } | 95 | } |
@@ -81,12 +99,15 @@ static int getinfo (lua_State *L) { | |||
81 | 99 | ||
82 | 100 | ||
83 | static int getlocal (lua_State *L) { | 101 | static int getlocal (lua_State *L) { |
102 | int arg; | ||
103 | lua_State *L1 = getthread(L, &arg); | ||
84 | lua_Debug ar; | 104 | lua_Debug ar; |
85 | const char *name; | 105 | const char *name; |
86 | if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ | 106 | if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ |
87 | return luaL_argerror(L, 1, "level out of range"); | 107 | return luaL_argerror(L, arg+1, "level out of range"); |
88 | name = lua_getlocal(L, &ar, luaL_checkint(L, 2)); | 108 | name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); |
89 | if (name) { | 109 | if (name) { |
110 | lua_xmove(L1, L, 1); | ||
90 | lua_pushstring(L, name); | 111 | lua_pushstring(L, name); |
91 | lua_pushvalue(L, -2); | 112 | lua_pushvalue(L, -2); |
92 | return 2; | 113 | return 2; |
@@ -99,11 +120,15 @@ static int getlocal (lua_State *L) { | |||
99 | 120 | ||
100 | 121 | ||
101 | static int setlocal (lua_State *L) { | 122 | static int setlocal (lua_State *L) { |
123 | int arg; | ||
124 | lua_State *L1 = getthread(L, &arg); | ||
102 | lua_Debug ar; | 125 | lua_Debug ar; |
103 | if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */ | 126 | if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ |
104 | return luaL_argerror(L, 1, "level out of range"); | 127 | return luaL_argerror(L, arg+1, "level out of range"); |
105 | luaL_checkany(L, 3); | 128 | luaL_checkany(L, arg+3); |
106 | lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2))); | 129 | lua_settop(L, arg+3); |
130 | lua_xmove(L, L1, 1); | ||
131 | lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); | ||
107 | return 1; | 132 | return 1; |
108 | } | 133 | } |
109 | 134 | ||
@@ -141,6 +166,8 @@ static void hookf (lua_State *L, lua_Debug *ar) { | |||
141 | {"call", "return", "line", "count", "tail return"}; | 166 | {"call", "return", "line", "count", "tail return"}; |
142 | lua_pushlightuserdata(L, (void *)&KEY_HOOK); | 167 | lua_pushlightuserdata(L, (void *)&KEY_HOOK); |
143 | lua_rawget(L, LUA_REGISTRYINDEX); | 168 | lua_rawget(L, LUA_REGISTRYINDEX); |
169 | lua_pushlightuserdata(L, L); | ||
170 | lua_rawget(L, -2); | ||
144 | if (lua_isfunction(L, -1)) { | 171 | if (lua_isfunction(L, -1)) { |
145 | lua_pushstring(L, hooknames[(int)ar->event]); | 172 | lua_pushstring(L, hooknames[(int)ar->event]); |
146 | if (ar->currentline >= 0) | 173 | if (ar->currentline >= 0) |
@@ -149,8 +176,6 @@ static void hookf (lua_State *L, lua_Debug *ar) { | |||
149 | lua_assert(lua_getinfo(L, "lS", ar)); | 176 | lua_assert(lua_getinfo(L, "lS", ar)); |
150 | lua_call(L, 2, 0); | 177 | lua_call(L, 2, 0); |
151 | } | 178 | } |
152 | else | ||
153 | lua_pop(L, 1); /* pop result from gettable */ | ||
154 | } | 179 | } |
155 | 180 | ||
156 | 181 | ||
@@ -174,36 +199,59 @@ static char *unmakemask (int mask, char *smask) { | |||
174 | } | 199 | } |
175 | 200 | ||
176 | 201 | ||
202 | static void gethooktable (lua_State *L) { | ||
203 | lua_pushlightuserdata(L, (void *)&KEY_HOOK); | ||
204 | lua_rawget(L, LUA_REGISTRYINDEX); | ||
205 | if (!lua_istable(L, -1)) { | ||
206 | lua_pop(L, 1); | ||
207 | lua_newtable(L); | ||
208 | lua_pushlightuserdata(L, (void *)&KEY_HOOK); | ||
209 | lua_pushvalue(L, -2); | ||
210 | lua_rawset(L, LUA_REGISTRYINDEX); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | |||
177 | static int sethook (lua_State *L) { | 215 | static int sethook (lua_State *L) { |
178 | if (lua_isnoneornil(L, 1)) { | 216 | int arg; |
179 | lua_settop(L, 1); | 217 | lua_State *L1 = getthread(L, &arg); |
180 | lua_sethook(L, NULL, 0, 0); /* turn off hooks */ | 218 | if (lua_isnoneornil(L, arg+1)) { |
219 | lua_settop(L, arg+1); | ||
220 | lua_sethook(L1, NULL, 0, 0); /* turn off hooks */ | ||
181 | } | 221 | } |
182 | else { | 222 | else { |
183 | const char *smask = luaL_checkstring(L, 2); | 223 | const char *smask = luaL_checkstring(L, arg+2); |
184 | int count = luaL_optint(L, 3, 0); | 224 | int count = luaL_optint(L, arg+3, 0); |
185 | luaL_checktype(L, 1, LUA_TFUNCTION); | 225 | luaL_checktype(L, arg+1, LUA_TFUNCTION); |
186 | lua_sethook(L, hookf, makemask(smask, count), count); | 226 | lua_sethook(L1, hookf, makemask(smask, count), count); |
187 | } | 227 | } |
188 | lua_pushlightuserdata(L, (void *)&KEY_HOOK); | 228 | gethooktable(L1); |
189 | lua_pushvalue(L, 1); | 229 | lua_pushlightuserdata(L1, L1); |
190 | lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */ | 230 | lua_pushvalue(L, arg+1); |
231 | lua_xmove(L, L1, 1); | ||
232 | lua_rawset(L1, -3); /* set new hook */ | ||
233 | lua_pop(L1, 1); /* remove hook table */ | ||
191 | return 0; | 234 | return 0; |
192 | } | 235 | } |
193 | 236 | ||
194 | 237 | ||
195 | static int gethook (lua_State *L) { | 238 | static int gethook (lua_State *L) { |
239 | int arg; | ||
240 | lua_State *L1 = getthread(L, &arg); | ||
196 | char buff[5]; | 241 | char buff[5]; |
197 | int mask = lua_gethookmask(L); | 242 | int mask = lua_gethookmask(L1); |
198 | lua_Hook hook = lua_gethook(L); | 243 | lua_Hook hook = lua_gethook(L1); |
199 | if (hook != NULL && hook != hookf) /* external hook? */ | 244 | if (hook != NULL && hook != hookf) /* external hook? */ |
200 | lua_pushliteral(L, "external hook"); | 245 | lua_pushliteral(L, "external hook"); |
201 | else { | 246 | else { |
202 | lua_pushlightuserdata(L, (void *)&KEY_HOOK); | 247 | gethooktable(L1); |
203 | lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ | 248 | lua_pushlightuserdata(L1, L1); |
249 | lua_rawget(L1, -2); /* get hook */ | ||
250 | lua_remove(L1, -2); /* remove hook table */ | ||
251 | lua_xmove(L1, L, 1); | ||
204 | } | 252 | } |
205 | lua_pushstring(L, unmakemask(mask, buff)); | 253 | lua_pushstring(L, unmakemask(mask, buff)); |
206 | lua_pushnumber(L, (lua_Number)lua_gethookcount(L)); | 254 | lua_pushnumber(L, (lua_Number)lua_gethookcount(L1)); |
207 | return 3; | 255 | return 3; |
208 | } | 256 | } |
209 | 257 | ||
@@ -227,27 +275,29 @@ static int debug (lua_State *L) { | |||
227 | static int errorfb (lua_State *L) { | 275 | static int errorfb (lua_State *L) { |
228 | int level = 1; /* skip level 0 (it's this function) */ | 276 | int level = 1; /* skip level 0 (it's this function) */ |
229 | int firstpart = 1; /* still before eventual `...' */ | 277 | int firstpart = 1; /* still before eventual `...' */ |
278 | int arg; | ||
279 | lua_State *L1 = getthread(L, &arg); | ||
230 | lua_Debug ar; | 280 | lua_Debug ar; |
231 | if (lua_gettop(L) == 0) | 281 | if (lua_gettop(L) == arg) |
232 | lua_pushliteral(L, ""); | 282 | lua_pushliteral(L, ""); |
233 | else if (!lua_isstring(L, 1)) return 1; /* no string message */ | 283 | else if (!lua_isstring(L, arg+1)) return 1; /* no string message */ |
234 | else lua_pushliteral(L, "\n"); | 284 | else lua_pushliteral(L, "\n"); |
235 | lua_pushliteral(L, "stack traceback:"); | 285 | lua_pushliteral(L, "stack traceback:"); |
236 | while (lua_getstack(L, level++, &ar)) { | 286 | while (lua_getstack(L1, level++, &ar)) { |
237 | if (level > LEVELS1 && firstpart) { | 287 | if (level > LEVELS1 && firstpart) { |
238 | /* no more than `LEVELS2' more levels? */ | 288 | /* no more than `LEVELS2' more levels? */ |
239 | if (!lua_getstack(L, level+LEVELS2, &ar)) | 289 | if (!lua_getstack(L1, level+LEVELS2, &ar)) |
240 | level--; /* keep going */ | 290 | level--; /* keep going */ |
241 | else { | 291 | else { |
242 | lua_pushliteral(L, "\n\t..."); /* too many levels */ | 292 | lua_pushliteral(L, "\n\t..."); /* too many levels */ |
243 | while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ | 293 | while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ |
244 | level++; | 294 | level++; |
245 | } | 295 | } |
246 | firstpart = 0; | 296 | firstpart = 0; |
247 | continue; | 297 | continue; |
248 | } | 298 | } |
249 | lua_pushliteral(L, "\n\t"); | 299 | lua_pushliteral(L, "\n\t"); |
250 | lua_getinfo(L, "Snl", &ar); | 300 | lua_getinfo(L1, "Snl", &ar); |
251 | lua_pushfstring(L, "%s:", ar.short_src); | 301 | lua_pushfstring(L, "%s:", ar.short_src); |
252 | if (ar.currentline > 0) | 302 | if (ar.currentline > 0) |
253 | lua_pushfstring(L, "%d:", ar.currentline); | 303 | lua_pushfstring(L, "%d:", ar.currentline); |
@@ -268,9 +318,9 @@ static int errorfb (lua_State *L) { | |||
268 | ar.short_src, ar.linedefined); | 318 | ar.short_src, ar.linedefined); |
269 | } | 319 | } |
270 | } | 320 | } |
271 | lua_concat(L, lua_gettop(L)); | 321 | lua_concat(L, lua_gettop(L) - arg); |
272 | } | 322 | } |
273 | lua_concat(L, lua_gettop(L)); | 323 | lua_concat(L, lua_gettop(L) - arg); |
274 | return 1; | 324 | return 1; |
275 | } | 325 | } |
276 | 326 | ||