ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lib_debug.c (9464B)


      1 /*
      2 ** Debug library.
      3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h
      4 **
      5 ** Major portions taken verbatim or adapted from the Lua interpreter.
      6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
      7 */
      8 
      9 #define lib_debug_c
     10 #define LUA_LIB
     11 
     12 #include "lua.h"
     13 #include "lauxlib.h"
     14 #include "lualib.h"
     15 
     16 #include "lj_obj.h"
     17 #include "lj_gc.h"
     18 #include "lj_err.h"
     19 #include "lj_debug.h"
     20 #include "lj_lib.h"
     21 
     22 /* ------------------------------------------------------------------------ */
     23 
     24 #define LJLIB_MODULE_debug
     25 
     26 LJLIB_CF(debug_getregistry)
     27 {
     28   copyTV(L, L->top++, registry(L));
     29   return 1;
     30 }
     31 
     32 LJLIB_CF(debug_getmetatable)	LJLIB_REC(.)
     33 {
     34   lj_lib_checkany(L, 1);
     35   if (!lua_getmetatable(L, 1)) {
     36     setnilV(L->top-1);
     37   }
     38   return 1;
     39 }
     40 
     41 LJLIB_CF(debug_setmetatable)    LJLIB_REC(.)
     42 {
     43   lj_lib_checktabornil(L, 2);
     44   L->top = L->base+2;
     45   lua_setmetatable(L, 1);
     46 #if LJ_51
     47   setboolV(L->top-1, 1);
     48 #endif
     49   return 1;
     50 }
     51 
     52 LJLIB_CF(debug_getfenv)
     53 {
     54   lj_lib_checkany(L, 1);
     55   lua_getfenv(L, 1);
     56   return 1;
     57 }
     58 
     59 LJLIB_CF(debug_setfenv)
     60 {
     61   lj_lib_checktab(L, 2);
     62   L->top = L->base+2;
     63   if (!lua_setfenv(L, 1))
     64     lj_err_caller(L, LJ_ERR_SETFENV);
     65   return 1;
     66 }
     67 
     68 /* ------------------------------------------------------------------------ */
     69 
     70 static void settabss(lua_State *L, const char *i, const char *v)
     71 {
     72   lua_pushstring(L, v);
     73   lua_setfield(L, -2, i);
     74 }
     75 
     76 static void settabsi(lua_State *L, const char *i, int v)
     77 {
     78   lua_pushinteger(L, v);
     79   lua_setfield(L, -2, i);
     80 }
     81 
     82 static void settabsb(lua_State *L, const char *i, int v)
     83 {
     84   lua_pushboolean(L, v);
     85   lua_setfield(L, -2, i);
     86 }
     87 
     88 static lua_State *getthread(lua_State *L, int *arg)
     89 {
     90   if (L->base < L->top && tvisthread(L->base)) {
     91     *arg = 1;
     92     return threadV(L->base);
     93   } else {
     94     *arg = 0;
     95     return L;
     96   }
     97 }
     98 
     99 static void treatstackoption(lua_State *L, lua_State *L1, const char *fname)
    100 {
    101   if (L == L1) {
    102     lua_pushvalue(L, -2);
    103     lua_remove(L, -3);
    104   }
    105   else
    106     lua_xmove(L1, L, 1);
    107   lua_setfield(L, -2, fname);
    108 }
    109 
    110 LJLIB_CF(debug_getinfo)
    111 {
    112   lj_Debug ar;
    113   int arg, opt_f = 0, opt_L = 0;
    114   lua_State *L1 = getthread(L, &arg);
    115   const char *options = luaL_optstring(L, arg+2, "flnSu");
    116   if (lua_isnumber(L, arg+1)) {
    117     if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), (lua_Debug *)&ar)) {
    118       setnilV(L->top-1);
    119       return 1;
    120     }
    121   } else if (L->base+arg < L->top && tvisfunc(L->base+arg)) {
    122     options = lua_pushfstring(L, ">%s", options);
    123     setfuncV(L1, L1->top++, funcV(L->base+arg));
    124   } else {
    125     lj_err_arg(L, arg+1, LJ_ERR_NOFUNCL);
    126   }
    127   if (!lj_debug_getinfo(L1, options, &ar, 1))
    128     lj_err_arg(L, arg+2, LJ_ERR_INVOPT);
    129   lua_createtable(L, 0, 16);  /* Create result table. */
    130   for (; *options; options++) {
    131     switch (*options) {
    132     case 'S':
    133       settabss(L, "source", ar.source);
    134       settabss(L, "short_src", ar.short_src);
    135       settabsi(L, "linedefined", ar.linedefined);
    136       settabsi(L, "lastlinedefined", ar.lastlinedefined);
    137       settabss(L, "what", ar.what);
    138       break;
    139     case 'l':
    140       settabsi(L, "currentline", ar.currentline);
    141       break;
    142     case 'u':
    143       settabsi(L, "nups", ar.nups);
    144       settabsi(L, "nparams", ar.nparams);
    145       settabsb(L, "isvararg", ar.isvararg);
    146       break;
    147     case 'n':
    148       settabss(L, "name", ar.name);
    149       settabss(L, "namewhat", ar.namewhat);
    150       break;
    151     case 'f': opt_f = 1; break;
    152     case 'L': opt_L = 1; break;
    153     default: break;
    154     }
    155   }
    156   if (opt_L) treatstackoption(L, L1, "activelines");
    157   if (opt_f) treatstackoption(L, L1, "func");
    158   return 1;  /* Return result table. */
    159 }
    160 
    161 LJLIB_CF(debug_getlocal)
    162 {
    163   int arg;
    164   lua_State *L1 = getthread(L, &arg);
    165   lua_Debug ar;
    166   const char *name;
    167   int slot = lj_lib_checkint(L, arg+2);
    168   if (tvisfunc(L->base+arg)) {
    169     L->top = L->base+arg+1;
    170     lua_pushstring(L, lua_getlocal(L, NULL, slot));
    171     return 1;
    172   }
    173   if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
    174     lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
    175   name = lua_getlocal(L1, &ar, slot);
    176   if (name) {
    177     lua_xmove(L1, L, 1);
    178     lua_pushstring(L, name);
    179     lua_pushvalue(L, -2);
    180     return 2;
    181   } else {
    182     setnilV(L->top-1);
    183     return 1;
    184   }
    185 }
    186 
    187 LJLIB_CF(debug_setlocal)
    188 {
    189   int arg;
    190   lua_State *L1 = getthread(L, &arg);
    191   lua_Debug ar;
    192   TValue *tv;
    193   if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
    194     lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
    195   tv = lj_lib_checkany(L, arg+3);
    196   copyTV(L1, L1->top++, tv);
    197   lua_pushstring(L, lua_setlocal(L1, &ar, lj_lib_checkint(L, arg+2)));
    198   return 1;
    199 }
    200 
    201 static int debug_getupvalue(lua_State *L, int get)
    202 {
    203   int32_t n = lj_lib_checkint(L, 2);
    204   const char *name;
    205   lj_lib_checkfunc(L, 1);
    206   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
    207   if (name) {
    208     lua_pushstring(L, name);
    209     if (!get) return 1;
    210     copyTV(L, L->top, L->top-2);
    211     L->top++;
    212     return 2;
    213   }
    214   return 0;
    215 }
    216 
    217 LJLIB_CF(debug_getupvalue)
    218 {
    219   return debug_getupvalue(L, 1);
    220 }
    221 
    222 LJLIB_CF(debug_setupvalue)
    223 {
    224   lj_lib_checkany(L, 3);
    225   return debug_getupvalue(L, 0);
    226 }
    227 
    228 LJLIB_CF(debug_upvalueid)
    229 {
    230   GCfunc *fn = lj_lib_checkfunc(L, 1);
    231   int32_t n = lj_lib_checkint(L, 2) - 1;
    232   if ((uint32_t)n >= fn->l.nupvalues)
    233     lj_err_arg(L, 2, LJ_ERR_IDXRNG);
    234   setlightudV(L->top-1, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
    235 					(void *)&fn->c.upvalue[n]);
    236   return 1;
    237 }
    238 
    239 LJLIB_CF(debug_upvaluejoin)
    240 {
    241   GCfunc *fn[2];
    242   GCRef *p[2];
    243   int i;
    244   for (i = 0; i < 2; i++) {
    245     int32_t n;
    246     fn[i] = lj_lib_checkfunc(L, 2*i+1);
    247     if (!isluafunc(fn[i]))
    248       lj_err_arg(L, 2*i+1, LJ_ERR_NOLFUNC);
    249     n = lj_lib_checkint(L, 2*i+2) - 1;
    250     if ((uint32_t)n >= fn[i]->l.nupvalues)
    251       lj_err_arg(L, 2*i+2, LJ_ERR_IDXRNG);
    252     p[i] = &fn[i]->l.uvptr[n];
    253   }
    254   setgcrefr(*p[0], *p[1]);
    255   lj_gc_objbarrier(L, fn[0], gcref(*p[1]));
    256   return 0;
    257 }
    258 
    259 #if !LJ_51
    260 LJLIB_CF(debug_getuservalue)
    261 {
    262   if (L->base < L->top)
    263     lua_getuservalue(L, 1);
    264   return 1;
    265 }
    266 
    267 LJLIB_CF(debug_setuservalue)
    268 {
    269   TValue *o = L->base;
    270   if (!(o < L->top && (tvisudata(o)||tvistab(o))))
    271     lj_err_argt(L, 1, LUA_TUSERDATA);
    272   if (!(o+1 < L->top && tvistab(o+1)))
    273     lj_err_argt(L, 2, LUA_TTABLE);
    274   L->top = o+2;
    275   lua_setuservalue(L, 1);
    276   return 1;
    277 }
    278 #endif
    279 
    280 /* ------------------------------------------------------------------------ */
    281 
    282 static const char KEY_HOOK = 'h';
    283 
    284 static void hookf(lua_State *L, lua_Debug *ar)
    285 {
    286   static const char *const hooknames[] =
    287     {"call", "return", "line", "count", "tail return"};
    288   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
    289   lua_rawget(L, LUA_REGISTRYINDEX);
    290   if (lua_isfunction(L, -1)) {
    291     lua_pushstring(L, hooknames[(int)ar->event]);
    292     if (ar->currentline >= 0)
    293       lua_pushinteger(L, ar->currentline);
    294     else lua_pushnil(L);
    295     lua_call(L, 2, 0);
    296   }
    297 }
    298 
    299 static int makemask(const char *smask, int count)
    300 {
    301   int mask = 0;
    302   if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
    303   if (strchr(smask, 'r')) mask |= LUA_MASKRET;
    304   if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
    305   if (count > 0) mask |= LUA_MASKCOUNT;
    306   return mask;
    307 }
    308 
    309 static char *unmakemask(int mask, char *smask)
    310 {
    311   int i = 0;
    312   if (mask & LUA_MASKCALL) smask[i++] = 'c';
    313   if (mask & LUA_MASKRET) smask[i++] = 'r';
    314   if (mask & LUA_MASKLINE) smask[i++] = 'l';
    315   smask[i] = '\0';
    316   return smask;
    317 }
    318 
    319 LJLIB_CF(debug_sethook)
    320 {
    321   int arg, mask, count;
    322   lua_Hook func;
    323   (void)getthread(L, &arg);
    324   if (lua_isnoneornil(L, arg+1)) {
    325     lua_settop(L, arg+1);
    326     func = NULL; mask = 0; count = 0;  /* turn off hooks */
    327   } else {
    328     const char *smask = luaL_checkstring(L, arg+2);
    329     luaL_checktype(L, arg+1, LUA_TFUNCTION);
    330     count = luaL_optint(L, arg+3, 0);
    331     func = hookf; mask = makemask(smask, count);
    332   }
    333   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
    334   lua_pushvalue(L, arg+1);
    335   lua_rawset(L, LUA_REGISTRYINDEX);
    336   lua_sethook(L, func, mask, count);
    337   return 0;
    338 }
    339 
    340 LJLIB_CF(debug_gethook)
    341 {
    342   char buff[5];
    343   int mask = lua_gethookmask(L);
    344   lua_Hook hook = lua_gethook(L);
    345   if (hook != NULL && hook != hookf) {  /* external hook? */
    346     lua_pushliteral(L, "external hook");
    347   } else {
    348     lua_pushlightuserdata(L, (void *)&KEY_HOOK);
    349     lua_rawget(L, LUA_REGISTRYINDEX);   /* get hook */
    350   }
    351   lua_pushstring(L, unmakemask(mask, buff));
    352   lua_pushinteger(L, lua_gethookcount(L));
    353   return 3;
    354 }
    355 
    356 /* ------------------------------------------------------------------------ */
    357 
    358 LJLIB_CF(debug_debug)
    359 {
    360   for (;;) {
    361     char buffer[250];
    362     fputs("lua_debug> ", stderr);
    363     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
    364 	strcmp(buffer, "cont\n") == 0)
    365       return 0;
    366     if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
    367 	lua_pcall(L, 0, 0, 0)) {
    368       fputs(lua_tostring(L, -1), stderr);
    369       fputs("\n", stderr);
    370     }
    371     lua_settop(L, 0);  /* remove eventual returns */
    372   }
    373 }
    374 
    375 /* ------------------------------------------------------------------------ */
    376 
    377 #define LEVELS1	12	/* size of the first part of the stack */
    378 #define LEVELS2	10	/* size of the second part of the stack */
    379 
    380 LJLIB_CF(debug_traceback)
    381 {
    382   int arg;
    383   lua_State *L1 = getthread(L, &arg);
    384   const char *msg = lua_tostring(L, arg+1);
    385   if (msg == NULL && L->top > L->base+arg)
    386     L->top = L->base+arg+1;
    387   else
    388     luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1)));
    389   return 1;
    390 }
    391 
    392 /* ------------------------------------------------------------------------ */
    393 
    394 #include "lj_libdef.h"
    395 
    396 LUALIB_API int luaopen_debug(lua_State *L)
    397 {
    398   LJ_LIB_REG(L, LUA_DBLIBNAME, debug);
    399   return 1;
    400 }
    401