Lua 5.1.4: ldblib.c


L0001    /*
L0002    ** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
L0003    ** Interface from Lua to its debug API
L0004    ** See Copyright Notice in lua.h
L0005    */
L0006    
L0007    
L0008    #include <stdio.h>
L0009    #include <stdlib.h>
L0010    #include <string.h>
L0011    
L0012    #define ldblib_c
L0013    #define LUA_LIB
L0014    
L0015    #include "lua.h"
L0016    
L0017    #include "lauxlib.h"
L0018    #include "lualib.h"
L0019    
L0020    
L0021    
L0022    static int db_getregistry (lua_State *L) {
L0023      lua_pushvalue(L, LUA_REGISTRYINDEX);
L0024      return 1;
L0025    }
L0026    
L0027    
L0028    static int db_getmetatable (lua_State *L) {
L0029      luaL_checkany(L, 1);
L0030      if (!lua_getmetatable(L, 1)) {
L0031        lua_pushnil(L);  /* no metatable */
L0032      }
L0033      return 1;
L0034    }
L0035    
L0036    
L0037    static int db_setmetatable (lua_State *L) {
L0038      int t = lua_type(L, 2);
L0039      luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
L0040                        "nil or table expected");
L0041      lua_settop(L, 2);
L0042      lua_pushboolean(L, lua_setmetatable(L, 1));
L0043      return 1;
L0044    }
L0045    
L0046    
L0047    static int db_getfenv (lua_State *L) {
L0048      lua_getfenv(L, 1);
L0049      return 1;
L0050    }
L0051    
L0052    
L0053    static int db_setfenv (lua_State *L) {
L0054      luaL_checktype(L, 2, LUA_TTABLE);
L0055      lua_settop(L, 2);
L0056      if (lua_setfenv(L, 1) == 0)
L0057        luaL_error(L, LUA_QL("setfenv")
L0058                      " cannot change environment of given object");
L0059      return 1;
L0060    }
L0061    
L0062    
L0063    static void settabss (lua_State *L, const char *i, const char *v) {
L0064      lua_pushstring(L, v);
L0065      lua_setfield(L, -2, i);
L0066    }
L0067    
L0068    
L0069    static void settabsi (lua_State *L, const char *i, int v) {
L0070      lua_pushinteger(L, v);
L0071      lua_setfield(L, -2, i);
L0072    }
L0073    
L0074    
L0075    static lua_State *getthread (lua_State *L, int *arg) {
L0076      if (lua_isthread(L, 1)) {
L0077        *arg = 1;
L0078        return lua_tothread(L, 1);
L0079      }
L0080      else {
L0081        *arg = 0;
L0082        return L;
L0083      }
L0084    }
L0085    
L0086    
L0087    static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
L0088      if (L == L1) {
L0089        lua_pushvalue(L, -2);
L0090        lua_remove(L, -3);
L0091      }
L0092      else
L0093        lua_xmove(L1, L, 1);
L0094      lua_setfield(L, -2, fname);
L0095    }
L0096    
L0097    
L0098    static int db_getinfo (lua_State *L) {
L0099      lua_Debug ar;
L0100      int arg;
L0101      lua_State *L1 = getthread(L, &arg);
L0102      const char *options = luaL_optstring(L, arg+2, "flnSu");
L0103      if (lua_isnumber(L, arg+1)) {
L0104        if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
L0105          lua_pushnil(L);  /* level out of range */
L0106          return 1;
L0107        }
L0108      }
L0109      else if (lua_isfunction(L, arg+1)) {
L0110        lua_pushfstring(L, ">%s", options);
L0111        options = lua_tostring(L, -1);
L0112        lua_pushvalue(L, arg+1);
L0113        lua_xmove(L, L1, 1);
L0114      }
L0115      else
L0116        return luaL_argerror(L, arg+1, "function or level expected");
L0117      if (!lua_getinfo(L1, options, &ar))
L0118        return luaL_argerror(L, arg+2, "invalid option");
L0119      lua_createtable(L, 0, 2);
L0120      if (strchr(options, 'S')) {
L0121        settabss(L, "source", ar.source);
L0122        settabss(L, "short_src", ar.short_src);
L0123        settabsi(L, "linedefined", ar.linedefined);
L0124        settabsi(L, "lastlinedefined", ar.lastlinedefined);
L0125        settabss(L, "what", ar.what);
L0126      }
L0127      if (strchr(options, 'l'))
L0128        settabsi(L, "currentline", ar.currentline);
L0129      if (strchr(options, 'u'))
L0130        settabsi(L, "nups", ar.nups);
L0131      if (strchr(options, 'n')) {
L0132        settabss(L, "name", ar.name);
L0133        settabss(L, "namewhat", ar.namewhat);
L0134      }
L0135      if (strchr(options, 'L'))
L0136        treatstackoption(L, L1, "activelines");
L0137      if (strchr(options, 'f'))
L0138        treatstackoption(L, L1, "func");
L0139      return 1;  /* return table */
L0140    }
L0141        
L0142    
L0143    static int db_getlocal (lua_State *L) {
L0144      int arg;
L0145      lua_State *L1 = getthread(L, &arg);
L0146      lua_Debug ar;
L0147      const char *name;
L0148      if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
L0149        return luaL_argerror(L, arg+1, "level out of range");
L0150      name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
L0151      if (name) {
L0152        lua_xmove(L1, L, 1);
L0153        lua_pushstring(L, name);
L0154        lua_pushvalue(L, -2);
L0155        return 2;
L0156      }
L0157      else {
L0158        lua_pushnil(L);
L0159        return 1;
L0160      }
L0161    }
L0162    
L0163    
L0164    static int db_setlocal (lua_State *L) {
L0165      int arg;
L0166      lua_State *L1 = getthread(L, &arg);
L0167      lua_Debug ar;
L0168      if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
L0169        return luaL_argerror(L, arg+1, "level out of range");
L0170      luaL_checkany(L, arg+3);
L0171      lua_settop(L, arg+3);
L0172      lua_xmove(L, L1, 1);
L0173      lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
L0174      return 1;
L0175    }
L0176    
L0177    
L0178    static int auxupvalue (lua_State *L, int get) {
L0179      const char *name;
L0180      int n = luaL_checkint(L, 2);
L0181      luaL_checktype(L, 1, LUA_TFUNCTION);
L0182      if (lua_iscfunction(L, 1)) return 0;  /* cannot touch C upvalues from Lua */
L0183      name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
L0184      if (name == NULL) return 0;
L0185      lua_pushstring(L, name);
L0186      lua_insert(L, -(get+1));
L0187      return get + 1;
L0188    }
L0189    
L0190    
L0191    static int db_getupvalue (lua_State *L) {
L0192      return auxupvalue(L, 1);
L0193    }
L0194    
L0195    
L0196    static int db_setupvalue (lua_State *L) {
L0197      luaL_checkany(L, 3);
L0198      return auxupvalue(L, 0);
L0199    }
L0200    
L0201    
L0202    
L0203    static const char KEY_HOOK = 'h';
L0204    
L0205    
L0206    static void hookf (lua_State *L, lua_Debug *ar) {
L0207      static const char *const hooknames[] =
L0208        {"call", "return", "line", "count", "tail return"};
L0209      lua_pushlightuserdata(L, (void *)&KEY_HOOK);
L0210      lua_rawget(L, LUA_REGISTRYINDEX);
L0211      lua_pushlightuserdata(L, L);
L0212      lua_rawget(L, -2);
L0213      if (lua_isfunction(L, -1)) {
L0214        lua_pushstring(L, hooknames[(int)ar->event]);
L0215        if (ar->currentline >= 0)
L0216          lua_pushinteger(L, ar->currentline);
L0217        else lua_pushnil(L);
L0218        lua_assert(lua_getinfo(L, "lS", ar));
L0219        lua_call(L, 2, 0);
L0220      }
L0221    }
L0222    
L0223    
L0224    static int makemask (const char *smask, int count) {
L0225      int mask = 0;
L0226      if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
L0227      if (strchr(smask, 'r')) mask |= LUA_MASKRET;
L0228      if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
L0229      if (count > 0) mask |= LUA_MASKCOUNT;
L0230      return mask;
L0231    }
L0232    
L0233    
L0234    static char *unmakemask (int mask, char *smask) {
L0235      int i = 0;
L0236      if (mask & LUA_MASKCALL) smask[i++] = 'c';
L0237      if (mask & LUA_MASKRET) smask[i++] = 'r';
L0238      if (mask & LUA_MASKLINE) smask[i++] = 'l';
L0239      smask[i] = '\0';
L0240      return smask;
L0241    }
L0242    
L0243    
L0244    static void gethooktable (lua_State *L) {
L0245      lua_pushlightuserdata(L, (void *)&KEY_HOOK);
L0246      lua_rawget(L, LUA_REGISTRYINDEX);
L0247      if (!lua_istable(L, -1)) {
L0248        lua_pop(L, 1);
L0249        lua_createtable(L, 0, 1);
L0250        lua_pushlightuserdata(L, (void *)&KEY_HOOK);
L0251        lua_pushvalue(L, -2);
L0252        lua_rawset(L, LUA_REGISTRYINDEX);
L0253      }
L0254    }
L0255    
L0256    
L0257    static int db_sethook (lua_State *L) {
L0258      int arg, mask, count;
L0259      lua_Hook func;
L0260      lua_State *L1 = getthread(L, &arg);
L0261      if (lua_isnoneornil(L, arg+1)) {
L0262        lua_settop(L, arg+1);
L0263        func = NULL; mask = 0; count = 0;  /* turn off hooks */
L0264      }
L0265      else {
L0266        const char *smask = luaL_checkstring(L, arg+2);
L0267        luaL_checktype(L, arg+1, LUA_TFUNCTION);
L0268        count = luaL_optint(L, arg+3, 0);
L0269        func = hookf; mask = makemask(smask, count);
L0270      }
L0271      gethooktable(L);
L0272      lua_pushlightuserdata(L, L1);
L0273      lua_pushvalue(L, arg+1);
L0274      lua_rawset(L, -3);  /* set new hook */
L0275      lua_pop(L, 1);  /* remove hook table */
L0276      lua_sethook(L1, func, mask, count);  /* set hooks */
L0277      return 0;
L0278    }
L0279    
L0280    
L0281    static int db_gethook (lua_State *L) {
L0282      int arg;
L0283      lua_State *L1 = getthread(L, &arg);
L0284      char buff[5];
L0285      int mask = lua_gethookmask(L1);
L0286      lua_Hook hook = lua_gethook(L1);
L0287      if (hook != NULL && hook != hookf)  /* external hook? */
L0288        lua_pushliteral(L, "external hook");
L0289      else {
L0290        gethooktable(L);
L0291        lua_pushlightuserdata(L, L1);
L0292        lua_rawget(L, -2);   /* get hook */
L0293        lua_remove(L, -2);  /* remove hook table */
L0294      }
L0295      lua_pushstring(L, unmakemask(mask, buff));
L0296      lua_pushinteger(L, lua_gethookcount(L1));
L0297      return 3;
L0298    }
L0299    
L0300    
L0301    static int db_debug (lua_State *L) {
L0302      for (;;) {
L0303        char buffer[250];
L0304        fputs("lua_debug> ", stderr);
L0305        if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
L0306            strcmp(buffer, "cont\n") == 0)
L0307          return 0;
L0308        if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
L0309            lua_pcall(L, 0, 0, 0)) {
L0310          fputs(lua_tostring(L, -1), stderr);
L0311          fputs("\n", stderr);
L0312        }
L0313        lua_settop(L, 0);  /* remove eventual returns */
L0314      }
L0315    }
L0316    
L0317    
L0318    #define LEVELS1	12	/* size of the first part of the stack */
L0319    #define LEVELS2	10	/* size of the second part of the stack */
L0320    
L0321    static int db_errorfb (lua_State *L) {
L0322      int level;
L0323      int firstpart = 1;  /* still before eventual `...' */
L0324      int arg;
L0325      lua_State *L1 = getthread(L, &arg);
L0326      lua_Debug ar;
L0327      if (lua_isnumber(L, arg+2)) {
L0328        level = (int)lua_tointeger(L, arg+2);
L0329        lua_pop(L, 1);
L0330      }
L0331      else
L0332        level = (L == L1) ? 1 : 0;  /* level 0 may be this own function */
L0333      if (lua_gettop(L) == arg)
L0334        lua_pushliteral(L, "");
L0335      else if (!lua_isstring(L, arg+1)) return 1;  /* message is not a string */
L0336      else lua_pushliteral(L, "\n");
L0337      lua_pushliteral(L, "stack traceback:");
L0338      while (lua_getstack(L1, level++, &ar)) {
L0339        if (level > LEVELS1 && firstpart) {
L0340          /* no more than `LEVELS2' more levels? */
L0341          if (!lua_getstack(L1, level+LEVELS2, &ar))
L0342            level--;  /* keep going */
L0343          else {
L0344            lua_pushliteral(L, "\n\t...");  /* too many levels */
L0345            while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */
L0346              level++;
L0347          }
L0348          firstpart = 0;
L0349          continue;
L0350        }
L0351        lua_pushliteral(L, "\n\t");
L0352        lua_getinfo(L1, "Snl", &ar);
L0353        lua_pushfstring(L, "%s:", ar.short_src);
L0354        if (ar.currentline > 0)
L0355          lua_pushfstring(L, "%d:", ar.currentline);
L0356        if (*ar.namewhat != '\0')  /* is there a name? */
L0357            lua_pushfstring(L, " in function " LUA_QS, ar.name);
L0358        else {
L0359          if (*ar.what == 'm')  /* main? */
L0360            lua_pushfstring(L, " in main chunk");
L0361          else if (*ar.what == 'C' || *ar.what == 't')
L0362            lua_pushliteral(L, " ?");  /* C function or tail call */
L0363          else
L0364            lua_pushfstring(L, " in function <%s:%d>",
L0365                               ar.short_src, ar.linedefined);
L0366        }
L0367        lua_concat(L, lua_gettop(L) - arg);
L0368      }
L0369      lua_concat(L, lua_gettop(L) - arg);
L0370      return 1;
L0371    }
L0372    
L0373    
L0374    static const luaL_Reg dblib[] = {
L0375      {"debug", db_debug},
L0376      {"getfenv", db_getfenv},
L0377      {"gethook", db_gethook},
L0378      {"getinfo", db_getinfo},
L0379      {"getlocal", db_getlocal},
L0380      {"getregistry", db_getregistry},
L0381      {"getmetatable", db_getmetatable},
L0382      {"getupvalue", db_getupvalue},
L0383      {"setfenv", db_setfenv},
L0384      {"sethook", db_sethook},
L0385      {"setlocal", db_setlocal},
L0386      {"setmetatable", db_setmetatable},
L0387      {"setupvalue", db_setupvalue},
L0388      {"traceback", db_errorfb},
L0389      {NULL, NULL}
L0390    };
L0391    
L0392    
L0393    LUALIB_API int luaopen_debug (lua_State *L) {
L0394      luaL_register(L, LUA_DBLIBNAME, dblib);
L0395      return 1;
L0396    }
L0397    

Generated by pretty.lua