root/lib/lua/ldblib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. db_getregistry
  2. db_getmetatable
  3. db_setmetatable
  4. db_getfenv
  5. db_setfenv
  6. settabss
  7. settabsi
  8. getthread
  9. treatstackoption
  10. db_getinfo
  11. db_getlocal
  12. db_setlocal
  13. auxupvalue
  14. db_getupvalue
  15. db_setupvalue
  16. hookf
  17. makemask
  18. unmakemask
  19. gethooktable
  20. db_sethook
  21. db_gethook
  22. db_debug
  23. db_errorfb
  24. luaopen_debug

   1 /*
   2 ** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $
   3 ** Interface from Lua to its debug API
   4 ** See Copyright Notice in lua.h
   5 */
   6 
   7 
   8 #include <stdio.h>
   9 #include <stdlib.h>
  10 #include <string.h>
  11 
  12 #define ldblib_c
  13 #define LUA_LIB
  14 
  15 #include "lua.h"
  16 
  17 #include "lauxlib.h"
  18 #include "lualib.h"
  19 
  20 
  21 
  22 static int db_getregistry (lua_State *L) {
  23   lua_pushvalue(L, LUA_REGISTRYINDEX);
  24   return 1;
  25 }
  26 
  27 
  28 static int db_getmetatable (lua_State *L) {
  29   luaL_checkany(L, 1);
  30   if (!lua_getmetatable(L, 1)) {
  31     lua_pushnil(L);  /* no metatable */
  32   }
  33   return 1;
  34 }
  35 
  36 
  37 static int db_setmetatable (lua_State *L) {
  38   int t = lua_type(L, 2);
  39   luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
  40                     "nil or table expected");
  41   lua_settop(L, 2);
  42   lua_pushboolean(L, lua_setmetatable(L, 1));
  43   return 1;
  44 }
  45 
  46 
  47 static int db_getfenv (lua_State *L) {
  48   luaL_checkany(L, 1);
  49   lua_getfenv(L, 1);
  50   return 1;
  51 }
  52 
  53 
  54 static int db_setfenv (lua_State *L) {
  55   luaL_checktype(L, 2, LUA_TTABLE);
  56   lua_settop(L, 2);
  57   if (lua_setfenv(L, 1) == 0)
  58     luaL_error(L, LUA_QL("setfenv")
  59                   " cannot change environment of given object");
  60   return 1;
  61 }
  62 
  63 
  64 static void settabss (lua_State *L, const char *i, const char *v) {
  65   lua_pushstring(L, v);
  66   lua_setfield(L, -2, i);
  67 }
  68 
  69 
  70 static void settabsi (lua_State *L, const char *i, int v) {
  71   lua_pushinteger(L, v);
  72   lua_setfield(L, -2, i);
  73 }
  74 
  75 
  76 static lua_State *getthread (lua_State *L, int *arg) {
  77   if (lua_isthread(L, 1)) {
  78     *arg = 1;
  79     return lua_tothread(L, 1);
  80   }
  81   else {
  82     *arg = 0;
  83     return L;
  84   }
  85 }
  86 
  87 
  88 static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
  89   if (L == L1) {
  90     lua_pushvalue(L, -2);
  91     lua_remove(L, -3);
  92   }
  93   else
  94     lua_xmove(L1, L, 1);
  95   lua_setfield(L, -2, fname);
  96 }
  97 
  98 
  99 static int db_getinfo (lua_State *L) {
 100   lua_Debug ar;
 101   int arg;
 102   lua_State *L1 = getthread(L, &arg);
 103   const char *options = luaL_optstring(L, arg+2, "flnSu");
 104   if (lua_isnumber(L, arg+1)) {
 105     if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
 106       lua_pushnil(L);  /* level out of range */
 107       return 1;
 108     }
 109   }
 110   else if (lua_isfunction(L, arg+1)) {
 111     lua_pushfstring(L, ">%s", options);
 112     options = lua_tostring(L, -1);
 113     lua_pushvalue(L, arg+1);
 114     lua_xmove(L, L1, 1);
 115   }
 116   else
 117     return luaL_argerror(L, arg+1, "function or level expected");
 118   if (!lua_getinfo(L1, options, &ar))
 119     return luaL_argerror(L, arg+2, "invalid option");
 120   lua_createtable(L, 0, 2);
 121   if (strchr(options, 'S')) {
 122     settabss(L, "source", ar.source);
 123     settabss(L, "short_src", ar.short_src);
 124     settabsi(L, "linedefined", ar.linedefined);
 125     settabsi(L, "lastlinedefined", ar.lastlinedefined);
 126     settabss(L, "what", ar.what);
 127   }
 128   if (strchr(options, 'l'))
 129     settabsi(L, "currentline", ar.currentline);
 130   if (strchr(options, 'u'))
 131     settabsi(L, "nups", ar.nups);
 132   if (strchr(options, 'n')) {
 133     settabss(L, "name", ar.name);
 134     settabss(L, "namewhat", ar.namewhat);
 135   }
 136   if (strchr(options, 'L'))
 137     treatstackoption(L, L1, "activelines");
 138   if (strchr(options, 'f'))
 139     treatstackoption(L, L1, "func");
 140   return 1;  /* return table */
 141 }
 142     
 143 
 144 static int db_getlocal (lua_State *L) {
 145   int arg;
 146   lua_State *L1 = getthread(L, &arg);
 147   lua_Debug ar;
 148   const char *name;
 149   if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
 150     return luaL_argerror(L, arg+1, "level out of range");
 151   name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
 152   if (name) {
 153     lua_xmove(L1, L, 1);
 154     lua_pushstring(L, name);
 155     lua_pushvalue(L, -2);
 156     return 2;
 157   }
 158   else {
 159     lua_pushnil(L);
 160     return 1;
 161   }
 162 }
 163 
 164 
 165 static int db_setlocal (lua_State *L) {
 166   int arg;
 167   lua_State *L1 = getthread(L, &arg);
 168   lua_Debug ar;
 169   if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
 170     return luaL_argerror(L, arg+1, "level out of range");
 171   luaL_checkany(L, arg+3);
 172   lua_settop(L, arg+3);
 173   lua_xmove(L, L1, 1);
 174   lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
 175   return 1;
 176 }
 177 
 178 
 179 static int auxupvalue (lua_State *L, int get) {
 180   const char *name;
 181   int n = luaL_checkint(L, 2);
 182   luaL_checktype(L, 1, LUA_TFUNCTION);
 183   if (lua_iscfunction(L, 1)) return 0;  /* cannot touch C upvalues from Lua */
 184   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
 185   if (name == NULL) return 0;
 186   lua_pushstring(L, name);
 187   lua_insert(L, -(get+1));
 188   return get + 1;
 189 }
 190 
 191 
 192 static int db_getupvalue (lua_State *L) {
 193   return auxupvalue(L, 1);
 194 }
 195 
 196 
 197 static int db_setupvalue (lua_State *L) {
 198   luaL_checkany(L, 3);
 199   return auxupvalue(L, 0);
 200 }
 201 
 202 
 203 
 204 static const char KEY_HOOK = 'h';
 205 
 206 
 207 static void hookf (lua_State *L, lua_Debug *ar) {
 208   static const char *const hooknames[] =
 209     {"call", "return", "line", "count", "tail return"};
 210   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
 211   lua_rawget(L, LUA_REGISTRYINDEX);
 212   lua_pushlightuserdata(L, L);
 213   lua_rawget(L, -2);
 214   if (lua_isfunction(L, -1)) {
 215     lua_pushstring(L, hooknames[(int)ar->event]);
 216     if (ar->currentline >= 0)
 217       lua_pushinteger(L, ar->currentline);
 218     else lua_pushnil(L);
 219     lua_assert(lua_getinfo(L, "lS", ar));
 220     lua_call(L, 2, 0);
 221   }
 222 }
 223 
 224 
 225 static int makemask (const char *smask, int count) {
 226   int mask = 0;
 227   if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
 228   if (strchr(smask, 'r')) mask |= LUA_MASKRET;
 229   if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
 230   if (count > 0) mask |= LUA_MASKCOUNT;
 231   return mask;
 232 }
 233 
 234 
 235 static char *unmakemask (int mask, char *smask) {
 236   int i = 0;
 237   if (mask & LUA_MASKCALL) smask[i++] = 'c';
 238   if (mask & LUA_MASKRET) smask[i++] = 'r';
 239   if (mask & LUA_MASKLINE) smask[i++] = 'l';
 240   smask[i] = '\0';
 241   return smask;
 242 }
 243 
 244 
 245 static void gethooktable (lua_State *L) {
 246   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
 247   lua_rawget(L, LUA_REGISTRYINDEX);
 248   if (!lua_istable(L, -1)) {
 249     lua_pop(L, 1);
 250     lua_createtable(L, 0, 1);
 251     lua_pushlightuserdata(L, (void *)&KEY_HOOK);
 252     lua_pushvalue(L, -2);
 253     lua_rawset(L, LUA_REGISTRYINDEX);
 254   }
 255 }
 256 
 257 
 258 static int db_sethook (lua_State *L) {
 259   int arg, mask, count;
 260   lua_Hook func;
 261   lua_State *L1 = getthread(L, &arg);
 262   if (lua_isnoneornil(L, arg+1)) {
 263     lua_settop(L, arg+1);
 264     func = NULL; mask = 0; count = 0;  /* turn off hooks */
 265   }
 266   else {
 267     const char *smask = luaL_checkstring(L, arg+2);
 268     luaL_checktype(L, arg+1, LUA_TFUNCTION);
 269     count = luaL_optint(L, arg+3, 0);
 270     func = hookf; mask = makemask(smask, count);
 271   }
 272   gethooktable(L);
 273   lua_pushlightuserdata(L, L1);
 274   lua_pushvalue(L, arg+1);
 275   lua_rawset(L, -3);  /* set new hook */
 276   lua_pop(L, 1);  /* remove hook table */
 277   lua_sethook(L1, func, mask, count);  /* set hooks */
 278   return 0;
 279 }
 280 
 281 
 282 static int db_gethook (lua_State *L) {
 283   int arg;
 284   lua_State *L1 = getthread(L, &arg);
 285   char buff[5];
 286   int mask = lua_gethookmask(L1);
 287   lua_Hook hook = lua_gethook(L1);
 288   if (hook != NULL && hook != hookf)  /* external hook? */
 289     lua_pushliteral(L, "external hook");
 290   else {
 291     gethooktable(L);
 292     lua_pushlightuserdata(L, L1);
 293     lua_rawget(L, -2);   /* get hook */
 294     lua_remove(L, -2);  /* remove hook table */
 295   }
 296   lua_pushstring(L, unmakemask(mask, buff));
 297   lua_pushinteger(L, lua_gethookcount(L1));
 298   return 3;
 299 }
 300 
 301 #if 0
 302 static int db_debug (lua_State *L) {
 303   for (;;) {
 304     char buffer[250];
 305     fputs("lua_debug> ", stderr);
 306     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
 307         strcmp(buffer, "cont\n") == 0)
 308       return 0;
 309     if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
 310         lua_pcall(L, 0, 0, 0)) {
 311       fputs(lua_tostring(L, -1), stderr);
 312       fputs("\n", stderr);
 313     }
 314     lua_settop(L, 0);  /* remove eventual returns */
 315   }
 316 }
 317 #endif
 318 
 319 #define LEVELS1 12      /* size of the first part of the stack */
 320 #define LEVELS2 10      /* size of the second part of the stack */
 321 
 322 static int db_errorfb (lua_State *L) {
 323   int level;
 324   int firstpart = 1;  /* still before eventual `...' */
 325   int arg;
 326   lua_State *L1 = getthread(L, &arg);
 327   lua_Debug ar;
 328   if (lua_isnumber(L, arg+2)) {
 329     level = (int)lua_tointeger(L, arg+2);
 330     lua_pop(L, 1);
 331   }
 332   else
 333     level = (L == L1) ? 1 : 0;  /* level 0 may be this own function */
 334   if (lua_gettop(L) == arg)
 335     lua_pushliteral(L, "");
 336   else if (!lua_isstring(L, arg+1)) return 1;  /* message is not a string */
 337   else lua_pushliteral(L, "\n");
 338   lua_pushliteral(L, "stack traceback:");
 339   while (lua_getstack(L1, level++, &ar)) {
 340     if (level > LEVELS1 && firstpart) {
 341       /* no more than `LEVELS2' more levels? */
 342       if (!lua_getstack(L1, level+LEVELS2, &ar))
 343         level--;  /* keep going */
 344       else {
 345         lua_pushliteral(L, "\n\t...");  /* too many levels */
 346         while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */
 347           level++;
 348       }
 349       firstpart = 0;
 350       continue;
 351     }
 352     lua_pushliteral(L, "\n\t");
 353     lua_getinfo(L1, "Snl", &ar);
 354     lua_pushfstring(L, "%s:", ar.short_src);
 355     if (ar.currentline > 0)
 356       lua_pushfstring(L, "%d:", ar.currentline);
 357     if (*ar.namewhat != '\0')  /* is there a name? */
 358         lua_pushfstring(L, " in function " LUA_QS, ar.name);
 359     else {
 360       if (*ar.what == 'm')  /* main? */
 361         lua_pushfstring(L, " in main chunk");
 362       else if (*ar.what == 'C' || *ar.what == 't')
 363         lua_pushliteral(L, " ?");  /* C function or tail call */
 364       else
 365         lua_pushfstring(L, " in function <%s:%d>",
 366                            ar.short_src, ar.linedefined);
 367     }
 368     lua_concat(L, lua_gettop(L) - arg);
 369   }
 370   lua_concat(L, lua_gettop(L) - arg);
 371   return 1;
 372 }
 373 
 374 
 375 static const luaL_Reg dblib[] = {
 376   //  {"debug", db_debug},
 377   {"getfenv", db_getfenv},
 378   {"gethook", db_gethook},
 379   {"getinfo", db_getinfo},
 380   {"getlocal", db_getlocal},
 381   {"getregistry", db_getregistry},
 382   {"getmetatable", db_getmetatable},
 383   {"getupvalue", db_getupvalue},
 384   {"setfenv", db_setfenv},
 385   {"sethook", db_sethook},
 386   {"setlocal", db_setlocal},
 387   {"setmetatable", db_setmetatable},
 388   {"setupvalue", db_setupvalue},
 389   {"traceback", db_errorfb},
 390   {NULL, NULL}
 391 };
 392 
 393 
 394 LUALIB_API int luaopen_debug (lua_State *L) {
 395   luaL_register(L, LUA_DBLIBNAME, dblib);
 396   return 1;
 397 }
 398 

/* [<][>][^][v][top][bottom][index][help] */