LCOV - code coverage report
Current view: directory - src - ldblib.c Found Hit Coverage
Test: Lua 5.1.4 Lines: 226 55 24.3 %
Date: 2009-09-13
Colors: not hit hit

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

Generated by: LCOV version 1.7