00001 /* 00002 ** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ 00003 ** Interface from Lua to its debug API 00004 ** See Copyright Notice in lua.h 00005 */ 00006 00007 00008 #include <stdio.h> 00009 #include <stdlib.h> 00010 #include <string.h> 00011 00012 #define ldblib_c 00013 #define LUA_LIB 00014 00015 #include "lua.h" 00016 00017 #include "lauxlib.h" 00018 #include "lualib.h" 00019 00020 00021 00022 static int db_getregistry (lua_State *L) { 00023 lua_pushvalue(L, LUA_REGISTRYINDEX); 00024 return 1; 00025 } 00026 00027 00028 static int db_getmetatable (lua_State *L) { 00029 luaL_checkany(L, 1); 00030 if (!lua_getmetatable(L, 1)) { 00031 lua_pushnil(L); /* no metatable */ 00032 } 00033 return 1; 00034 } 00035 00036 00037 static int db_setmetatable (lua_State *L) { 00038 int t = lua_type(L, 2); 00039 luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, 00040 "nil or table expected"); 00041 lua_settop(L, 2); 00042 lua_pushboolean(L, lua_setmetatable(L, 1)); 00043 return 1; 00044 } 00045 00046 00047 static int db_getfenv (lua_State *L) { 00048 lua_getfenv(L, 1); 00049 return 1; 00050 } 00051 00052 00053 static int db_setfenv (lua_State *L) { 00054 luaL_checktype(L, 2, LUA_TTABLE); 00055 lua_settop(L, 2); 00056 if (lua_setfenv(L, 1) == 0) 00057 luaL_error(L, LUA_QL("setfenv") 00058 " cannot change environment of given object"); 00059 return 1; 00060 } 00061 00062 00063 static void settabss (lua_State *L, const char *i, const char *v) { 00064 lua_pushstring(L, v); 00065 lua_setfield(L, -2, i); 00066 } 00067 00068 00069 static void settabsi (lua_State *L, const char *i, int v) { 00070 lua_pushinteger(L, v); 00071 lua_setfield(L, -2, i); 00072 } 00073 00074 00075 static lua_State *getthread (lua_State *L, int *arg) { 00076 if (lua_isthread(L, 1)) { 00077 *arg = 1; 00078 return lua_tothread(L, 1); 00079 } 00080 else { 00081 *arg = 0; 00082 return L; 00083 } 00084 } 00085 00086 00087 static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { 00088 if (L == L1) { 00089 lua_pushvalue(L, -2); 00090 lua_remove(L, -3); 00091 } 00092 else 00093 lua_xmove(L1, L, 1); 00094 lua_setfield(L, -2, fname); 00095 } 00096 00097 00098 static int db_getinfo (lua_State *L) { 00099 lua_Debug ar; 00100 int arg; 00101 lua_State *L1 = getthread(L, &arg); 00102 const char *options = luaL_optstring(L, arg+2, "flnSu"); 00103 if (lua_isnumber(L, arg+1)) { 00104 if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { 00105 lua_pushnil(L); /* level out of range */ 00106 return 1; 00107 } 00108 } 00109 else if (lua_isfunction(L, arg+1)) { 00110 lua_pushfstring(L, ">%s", options); 00111 options = lua_tostring(L, -1); 00112 lua_pushvalue(L, arg+1); 00113 lua_xmove(L, L1, 1); 00114 } 00115 else 00116 return luaL_argerror(L, arg+1, "function or level expected"); 00117 if (!lua_getinfo(L1, options, &ar)) 00118 return luaL_argerror(L, arg+2, "invalid option"); 00119 lua_createtable(L, 0, 2); 00120 if (strchr(options, 'S')) { 00121 settabss(L, "source", ar.source); 00122 settabss(L, "short_src", ar.short_src); 00123 settabsi(L, "linedefined", ar.linedefined); 00124 settabsi(L, "lastlinedefined", ar.lastlinedefined); 00125 settabss(L, "what", ar.what); 00126 } 00127 if (strchr(options, 'l')) 00128 settabsi(L, "currentline", ar.currentline); 00129 if (strchr(options, 'u')) 00130 settabsi(L, "nups", ar.nups); 00131 if (strchr(options, 'n')) { 00132 settabss(L, "name", ar.name); 00133 settabss(L, "namewhat", ar.namewhat); 00134 } 00135 if (strchr(options, 'L')) 00136 treatstackoption(L, L1, "activelines"); 00137 if (strchr(options, 'f')) 00138 treatstackoption(L, L1, "func"); 00139 return 1; /* return table */ 00140 } 00141 00142 00143 static int db_getlocal (lua_State *L) { 00144 int arg; 00145 lua_State *L1 = getthread(L, &arg); 00146 lua_Debug ar; 00147 const char *name; 00148 if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ 00149 return luaL_argerror(L, arg+1, "level out of range"); 00150 name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); 00151 if (name) { 00152 lua_xmove(L1, L, 1); 00153 lua_pushstring(L, name); 00154 lua_pushvalue(L, -2); 00155 return 2; 00156 } 00157 else { 00158 lua_pushnil(L); 00159 return 1; 00160 } 00161 } 00162 00163 00164 static int db_setlocal (lua_State *L) { 00165 int arg; 00166 lua_State *L1 = getthread(L, &arg); 00167 lua_Debug ar; 00168 if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ 00169 return luaL_argerror(L, arg+1, "level out of range"); 00170 luaL_checkany(L, arg+3); 00171 lua_settop(L, arg+3); 00172 lua_xmove(L, L1, 1); 00173 lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); 00174 return 1; 00175 } 00176 00177 00178 static int auxupvalue (lua_State *L, int get) { 00179 const char *name; 00180 int n = luaL_checkint(L, 2); 00181 luaL_checktype(L, 1, LUA_TFUNCTION); 00182 if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ 00183 name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); 00184 if (name == NULL) return 0; 00185 lua_pushstring(L, name); 00186 lua_insert(L, -(get+1)); 00187 return get + 1; 00188 } 00189 00190 00191 static int db_getupvalue (lua_State *L) { 00192 return auxupvalue(L, 1); 00193 } 00194 00195 00196 static int db_setupvalue (lua_State *L) { 00197 luaL_checkany(L, 3); 00198 return auxupvalue(L, 0); 00199 } 00200 00201 00202 00203 static const char KEY_HOOK = 'h'; 00204 00205 00206 static void hookf (lua_State *L, lua_Debug *ar) { 00207 static const char *const hooknames[] = 00208 {"call", "return", "line", "count", "tail return"}; 00209 lua_pushlightuserdata(L, (void *)&KEY_HOOK); 00210 lua_rawget(L, LUA_REGISTRYINDEX); 00211 lua_pushlightuserdata(L, L); 00212 lua_rawget(L, -2); 00213 if (lua_isfunction(L, -1)) { 00214 lua_pushstring(L, hooknames[(int)ar->event]); 00215 if (ar->currentline >= 0) 00216 lua_pushinteger(L, ar->currentline); 00217 else lua_pushnil(L); 00218 lua_assert(lua_getinfo(L, "lS", ar)); 00219 lua_call(L, 2, 0); 00220 } 00221 } 00222 00223 00224 static int makemask (const char *smask, int count) { 00225 int mask = 0; 00226 if (strchr(smask, 'c')) mask |= LUA_MASKCALL; 00227 if (strchr(smask, 'r')) mask |= LUA_MASKRET; 00228 if (strchr(smask, 'l')) mask |= LUA_MASKLINE; 00229 if (count > 0) mask |= LUA_MASKCOUNT; 00230 return mask; 00231 } 00232 00233 00234 static char *unmakemask (int mask, char *smask) { 00235 int i = 0; 00236 if (mask & LUA_MASKCALL) smask[i++] = 'c'; 00237 if (mask & LUA_MASKRET) smask[i++] = 'r'; 00238 if (mask & LUA_MASKLINE) smask[i++] = 'l'; 00239 smask[i] = '\0'; 00240 return smask; 00241 } 00242 00243 00244 static void gethooktable (lua_State *L) { 00245 lua_pushlightuserdata(L, (void *)&KEY_HOOK); 00246 lua_rawget(L, LUA_REGISTRYINDEX); 00247 if (!lua_istable(L, -1)) { 00248 lua_pop(L, 1); 00249 lua_createtable(L, 0, 1); 00250 lua_pushlightuserdata(L, (void *)&KEY_HOOK); 00251 lua_pushvalue(L, -2); 00252 lua_rawset(L, LUA_REGISTRYINDEX); 00253 } 00254 } 00255 00256 00257 static int db_sethook (lua_State *L) { 00258 int arg, mask, count; 00259 lua_Hook func; 00260 lua_State *L1 = getthread(L, &arg); 00261 if (lua_isnoneornil(L, arg+1)) { 00262 lua_settop(L, arg+1); 00263 func = NULL; mask = 0; count = 0; /* turn off hooks */ 00264 } 00265 else { 00266 const char *smask = luaL_checkstring(L, arg+2); 00267 luaL_checktype(L, arg+1, LUA_TFUNCTION); 00268 count = luaL_optint(L, arg+3, 0); 00269 func = hookf; mask = makemask(smask, count); 00270 } 00271 gethooktable(L); 00272 lua_pushlightuserdata(L, L1); 00273 lua_pushvalue(L, arg+1); 00274 lua_rawset(L, -3); /* set new hook */ 00275 lua_pop(L, 1); /* remove hook table */ 00276 lua_sethook(L1, func, mask, count); /* set hooks */ 00277 return 0; 00278 } 00279 00280 00281 static int db_gethook (lua_State *L) { 00282 int arg; 00283 lua_State *L1 = getthread(L, &arg); 00284 char buff[5]; 00285 int mask = lua_gethookmask(L1); 00286 lua_Hook hook = lua_gethook(L1); 00287 if (hook != NULL && hook != hookf) /* external hook? */ 00288 lua_pushliteral(L, "external hook"); 00289 else { 00290 gethooktable(L); 00291 lua_pushlightuserdata(L, L1); 00292 lua_rawget(L, -2); /* get hook */ 00293 lua_remove(L, -2); /* remove hook table */ 00294 } 00295 lua_pushstring(L, unmakemask(mask, buff)); 00296 lua_pushinteger(L, lua_gethookcount(L1)); 00297 return 3; 00298 } 00299 00300 00301 static int db_debug (lua_State *L) { 00302 for (;;) { 00303 char buffer[250]; 00304 fputs("lua_debug> ", stderr); 00305 if (fgets(buffer, sizeof(buffer), stdin) == 0 || 00306 strcmp(buffer, "cont\n") == 0) 00307 return 0; 00308 if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || 00309 lua_pcall(L, 0, 0, 0)) { 00310 fputs(lua_tostring(L, -1), stderr); 00311 fputs("\n", stderr); 00312 } 00313 lua_settop(L, 0); /* remove eventual returns */ 00314 } 00315 } 00316 00317 00318 #define LEVELS1 12 /* size of the first part of the stack */ 00319 #define LEVELS2 10 /* size of the second part of the stack */ 00320 00321 static int db_errorfb (lua_State *L) { 00322 int level; 00323 int firstpart = 1; /* still before eventual `...' */ 00324 int arg; 00325 lua_State *L1 = getthread(L, &arg); 00326 lua_Debug ar; 00327 if (lua_isnumber(L, arg+2)) { 00328 level = (int)lua_tointeger(L, arg+2); 00329 lua_pop(L, 1); 00330 } 00331 else 00332 level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ 00333 if (lua_gettop(L) == arg) 00334 lua_pushliteral(L, ""); 00335 else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ 00336 else lua_pushliteral(L, "\n"); 00337 lua_pushliteral(L, "stack traceback:"); 00338 while (lua_getstack(L1, level++, &ar)) { 00339 if (level > LEVELS1 && firstpart) { 00340 /* no more than `LEVELS2' more levels? */ 00341 if (!lua_getstack(L1, level+LEVELS2, &ar)) 00342 level--; /* keep going */ 00343 else { 00344 lua_pushliteral(L, "\n\t..."); /* too many levels */ 00345 while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ 00346 level++; 00347 } 00348 firstpart = 0; 00349 continue; 00350 } 00351 lua_pushliteral(L, "\n\t"); 00352 lua_getinfo(L1, "Snl", &ar); 00353 lua_pushfstring(L, "%s:", ar.short_src); 00354 if (ar.currentline > 0) 00355 lua_pushfstring(L, "%d:", ar.currentline); 00356 if (*ar.namewhat != '\0') /* is there a name? */ 00357 lua_pushfstring(L, " in function " LUA_QS, ar.name); 00358 else { 00359 if (*ar.what == 'm') /* main? */ 00360 lua_pushfstring(L, " in main chunk"); 00361 else if (*ar.what == 'C' || *ar.what == 't') 00362 lua_pushliteral(L, " ?"); /* C function or tail call */ 00363 else 00364 lua_pushfstring(L, " in function <%s:%d>", 00365 ar.short_src, ar.linedefined); 00366 } 00367 lua_concat(L, lua_gettop(L) - arg); 00368 } 00369 lua_concat(L, lua_gettop(L) - arg); 00370 return 1; 00371 } 00372 00373 00374 static const luaL_Reg dblib[] = { 00375 {"debug", db_debug}, 00376 {"getfenv", db_getfenv}, 00377 {"gethook", db_gethook}, 00378 {"getinfo", db_getinfo}, 00379 {"getlocal", db_getlocal}, 00380 {"getregistry", db_getregistry}, 00381 {"getmetatable", db_getmetatable}, 00382 {"getupvalue", db_getupvalue}, 00383 {"setfenv", db_setfenv}, 00384 {"sethook", db_sethook}, 00385 {"setlocal", db_setlocal}, 00386 {"setmetatable", db_setmetatable}, 00387 {"setupvalue", db_setupvalue}, 00388 {"traceback", db_errorfb}, 00389 {NULL, NULL} 00390 }; 00391 00392 00393 LUALIB_API int luaopen_debug (lua_State *L) { 00394 luaL_register(L, LUA_DBLIBNAME, dblib); 00395 return 1; 00396 } 00397
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1