00001
00002
00003
00004
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);
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);
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;
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))
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))
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;
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;
00259 lua_State *L1 = getthread(L, &arg);
00260 if (lua_isnoneornil(L, arg+1)) {
00261 lua_settop(L, arg+1);
00262 lua_sethook(L1, NULL, 0, 0);
00263 }
00264 else {
00265 const char *smask = luaL_checkstring(L, arg+2);
00266 int count = luaL_optint(L, arg+3, 0);
00267 luaL_checktype(L, arg+1, LUA_TFUNCTION);
00268 lua_sethook(L1, hookf, makemask(smask, count), count);
00269 }
00270 gethooktable(L1);
00271 lua_pushlightuserdata(L1, L1);
00272 lua_pushvalue(L, arg+1);
00273 lua_xmove(L, L1, 1);
00274 lua_rawset(L1, -3);
00275 lua_pop(L1, 1);
00276 return 0;
00277 }
00278
00279
00280 static int db_gethook (lua_State *L) {
00281 int arg;
00282 lua_State *L1 = getthread(L, &arg);
00283 char buff[5];
00284 int mask = lua_gethookmask(L1);
00285 lua_Hook hook = lua_gethook(L1);
00286 if (hook != NULL && hook != hookf)
00287 lua_pushliteral(L, "external hook");
00288 else {
00289 gethooktable(L1);
00290 lua_pushlightuserdata(L1, L1);
00291 lua_rawget(L1, -2);
00292 lua_remove(L1, -2);
00293 lua_xmove(L1, L, 1);
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);
00314 }
00315 }
00316
00317
00318 #define LEVELS1 12
00319 #define LEVELS2 10
00320
00321 static int db_errorfb (lua_State *L) {
00322 int level;
00323 int firstpart = 1;
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;
00333 if (lua_gettop(L) == arg)
00334 lua_pushliteral(L, "");
00335 else if (!lua_isstring(L, arg+1)) return 1;
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
00341 if (!lua_getstack(L1, level+LEVELS2, &ar))
00342 level--;
00343 else {
00344 lua_pushliteral(L, "\n\t...");
00345 while (lua_getstack(L1, level+LEVELS2, &ar))
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')
00357 lua_pushfstring(L, " in function " LUA_QS, ar.name);
00358 else {
00359 if (*ar.what == 'm')
00360 lua_pushfstring(L, " in main chunk");
00361 else if (*ar.what == 'C' || *ar.what == 't')
00362 lua_pushliteral(L, " ?");
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