?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. /*
  2. ** $Id: ldblib.c,v 1.132.1.2 2015/02/19 17:16:55 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. #define HOOKKEY         "_HKEY"
  22.  
  23.  
  24. static void checkstack (lua_State *L, lua_State *L1, int n) {
  25.   if (L != L1 && !lua_checkstack(L1, n))
  26.     luaL_error(L, "stack overflow");
  27. }
  28.  
  29.  
  30. static int db_getregistry (lua_State *L) {
  31.   lua_pushvalue(L, LUA_REGISTRYINDEX);
  32.   return 1;
  33. }
  34.  
  35.  
  36. static int db_getmetatable (lua_State *L) {
  37.   luaL_checkany(L, 1);
  38.   if (!lua_getmetatable(L, 1)) {
  39.     lua_pushnil(L);  /* no metatable */
  40.   }
  41.   return 1;
  42. }
  43.  
  44.  
  45. static int db_setmetatable (lua_State *L) {
  46.   int t = lua_type(L, 2);
  47.   luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
  48.                     "nil or table expected");
  49.   lua_settop(L, 2);
  50.   lua_setmetatable(L, 1);
  51.   return 1;  /* return 1st argument */
  52. }
  53.  
  54.  
  55. static int db_getuservalue (lua_State *L) {
  56.   if (lua_type(L, 1) != LUA_TUSERDATA)
  57.     lua_pushnil(L);
  58.   else
  59.     lua_getuservalue(L, 1);
  60.   return 1;
  61. }
  62.  
  63.  
  64. static int db_setuservalue (lua_State *L) {
  65.   if (lua_type(L, 1) == LUA_TLIGHTUSERDATA)
  66.     luaL_argerror(L, 1, "full userdata expected, got light userdata");
  67.   luaL_checktype(L, 1, LUA_TUSERDATA);
  68.   if (!lua_isnoneornil(L, 2))
  69.     luaL_checktype(L, 2, LUA_TTABLE);
  70.   lua_settop(L, 2);
  71.   lua_setuservalue(L, 1);
  72.   return 1;
  73. }
  74.  
  75.  
  76. static void settabss (lua_State *L, const char *i, const char *v) {
  77.   lua_pushstring(L, v);
  78.   lua_setfield(L, -2, i);
  79. }
  80.  
  81.  
  82. static void settabsi (lua_State *L, const char *i, int v) {
  83.   lua_pushinteger(L, v);
  84.   lua_setfield(L, -2, i);
  85. }
  86.  
  87.  
  88. static void settabsb (lua_State *L, const char *i, int v) {
  89.   lua_pushboolean(L, v);
  90.   lua_setfield(L, -2, i);
  91. }
  92.  
  93.  
  94. static lua_State *getthread (lua_State *L, int *arg) {
  95.   if (lua_isthread(L, 1)) {
  96.     *arg = 1;
  97.     return lua_tothread(L, 1);
  98.   }
  99.   else {
  100.     *arg = 0;
  101.     return L;
  102.   }
  103. }
  104.  
  105.  
  106. static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
  107.   if (L == L1) {
  108.     lua_pushvalue(L, -2);
  109.     lua_remove(L, -3);
  110.   }
  111.   else
  112.     lua_xmove(L1, L, 1);
  113.   lua_setfield(L, -2, fname);
  114. }
  115.  
  116.  
  117. static int db_getinfo (lua_State *L) {
  118.   lua_Debug ar;
  119.   int arg;
  120.   lua_State *L1 = getthread(L, &arg);
  121.   const char *options = luaL_optstring(L, arg+2, "flnStu");
  122.   checkstack(L, L1, 3);
  123.   if (lua_isnumber(L, arg+1)) {
  124.     if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
  125.       lua_pushnil(L);  /* level out of range */
  126.       return 1;
  127.     }
  128.   }
  129.   else if (lua_isfunction(L, arg+1)) {
  130.     lua_pushfstring(L, ">%s", options);
  131.     options = lua_tostring(L, -1);
  132.     lua_pushvalue(L, arg+1);
  133.     lua_xmove(L, L1, 1);
  134.   }
  135.   else
  136.     return luaL_argerror(L, arg+1, "function or level expected");
  137.   if (!lua_getinfo(L1, options, &ar))
  138.     return luaL_argerror(L, arg+2, "invalid option");
  139.   lua_createtable(L, 0, 2);
  140.   if (strchr(options, 'S')) {
  141.     settabss(L, "source", ar.source);
  142.     settabss(L, "short_src", ar.short_src);
  143.     settabsi(L, "linedefined", ar.linedefined);
  144.     settabsi(L, "lastlinedefined", ar.lastlinedefined);
  145.     settabss(L, "what", ar.what);
  146.   }
  147.   if (strchr(options, 'l'))
  148.     settabsi(L, "currentline", ar.currentline);
  149.   if (strchr(options, 'u')) {
  150.     settabsi(L, "nups", ar.nups);
  151.     settabsi(L, "nparams", ar.nparams);
  152.     settabsb(L, "isvararg", ar.isvararg);
  153.   }
  154.   if (strchr(options, 'n')) {
  155.     settabss(L, "name", ar.name);
  156.     settabss(L, "namewhat", ar.namewhat);
  157.   }
  158.   if (strchr(options, 't'))
  159.     settabsb(L, "istailcall", ar.istailcall);
  160.   if (strchr(options, 'L'))
  161.     treatstackoption(L, L1, "activelines");
  162.   if (strchr(options, 'f'))
  163.     treatstackoption(L, L1, "func");
  164.   return 1;  /* return table */
  165. }
  166.  
  167.  
  168. static int db_getlocal (lua_State *L) {
  169.   int arg;
  170.   lua_State *L1 = getthread(L, &arg);
  171.   lua_Debug ar;
  172.   const char *name;
  173.   int nvar = luaL_checkint(L, arg+2);  /* local-variable index */
  174.   if (lua_isfunction(L, arg + 1)) {  /* function argument? */
  175.     lua_pushvalue(L, arg + 1);  /* push function */
  176.     lua_pushstring(L, lua_getlocal(L, NULL, nvar));  /* push local name */
  177.     return 1;
  178.   }
  179.   else {  /* stack-level argument */
  180.     if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
  181.       return luaL_argerror(L, arg+1, "level out of range");
  182.     checkstack(L, L1, 1);
  183.     name = lua_getlocal(L1, &ar, nvar);
  184.     if (name) {
  185.       lua_xmove(L1, L, 1);  /* push local value */
  186.       lua_pushstring(L, name);  /* push name */
  187.       lua_pushvalue(L, -2);  /* re-order */
  188.       return 2;
  189.     }
  190.     else {
  191.       lua_pushnil(L);  /* no name (nor value) */
  192.       return 1;
  193.     }
  194.   }
  195. }
  196.  
  197.  
  198. static int db_setlocal (lua_State *L) {
  199.   int arg;
  200.   lua_State *L1 = getthread(L, &arg);
  201.   lua_Debug ar;
  202.   if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
  203.     return luaL_argerror(L, arg+1, "level out of range");
  204.   luaL_checkany(L, arg+3);
  205.   lua_settop(L, arg+3);
  206.   checkstack(L, L1, 1);
  207.   lua_xmove(L, L1, 1);
  208.   lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
  209.   return 1;
  210. }
  211.  
  212.  
  213. static int auxupvalue (lua_State *L, int get) {
  214.   const char *name;
  215.   int n = luaL_checkint(L, 2);
  216.   luaL_checktype(L, 1, LUA_TFUNCTION);
  217.   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
  218.   if (name == NULL) return 0;
  219.   lua_pushstring(L, name);
  220.   lua_insert(L, -(get+1));
  221.   return get + 1;
  222. }
  223.  
  224.  
  225. static int db_getupvalue (lua_State *L) {
  226.   return auxupvalue(L, 1);
  227. }
  228.  
  229.  
  230. static int db_setupvalue (lua_State *L) {
  231.   luaL_checkany(L, 3);
  232.   return auxupvalue(L, 0);
  233. }
  234.  
  235.  
  236. static int checkupval (lua_State *L, int argf, int argnup) {
  237.   lua_Debug ar;
  238.   int nup = luaL_checkint(L, argnup);
  239.   luaL_checktype(L, argf, LUA_TFUNCTION);
  240.   lua_pushvalue(L, argf);
  241.   lua_getinfo(L, ">u", &ar);
  242.   luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");
  243.   return nup;
  244. }
  245.  
  246.  
  247. static int db_upvalueid (lua_State *L) {
  248.   int n = checkupval(L, 1, 2);
  249.   lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
  250.   return 1;
  251. }
  252.  
  253.  
  254. static int db_upvaluejoin (lua_State *L) {
  255.   int n1 = checkupval(L, 1, 2);
  256.   int n2 = checkupval(L, 3, 4);
  257.   luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
  258.   luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
  259.   lua_upvaluejoin(L, 1, n1, 3, n2);
  260.   return 0;
  261. }
  262.  
  263.  
  264. #define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
  265.  
  266.  
  267. static void hookf (lua_State *L, lua_Debug *ar) {
  268.   static const char *const hooknames[] =
  269.     {"call", "return", "line", "count", "tail call"};
  270.   gethooktable(L);
  271.   lua_pushthread(L);
  272.   lua_rawget(L, -2);
  273.   if (lua_isfunction(L, -1)) {
  274.     lua_pushstring(L, hooknames[(int)ar->event]);
  275.     if (ar->currentline >= 0)
  276.       lua_pushinteger(L, ar->currentline);
  277.     else lua_pushnil(L);
  278.     lua_assert(lua_getinfo(L, "lS", ar));
  279.     lua_call(L, 2, 0);
  280.   }
  281. }
  282.  
  283.  
  284. static int makemask (const char *smask, int count) {
  285.   int mask = 0;
  286.   if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
  287.   if (strchr(smask, 'r')) mask |= LUA_MASKRET;
  288.   if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
  289.   if (count > 0) mask |= LUA_MASKCOUNT;
  290.   return mask;
  291. }
  292.  
  293.  
  294. static char *unmakemask (int mask, char *smask) {
  295.   int i = 0;
  296.   if (mask & LUA_MASKCALL) smask[i++] = 'c';
  297.   if (mask & LUA_MASKRET) smask[i++] = 'r';
  298.   if (mask & LUA_MASKLINE) smask[i++] = 'l';
  299.   smask[i] = '\0';
  300.   return smask;
  301. }
  302.  
  303.  
  304. static int db_sethook (lua_State *L) {
  305.   int arg, mask, count;
  306.   lua_Hook func;
  307.   lua_State *L1 = getthread(L, &arg);
  308.   if (lua_isnoneornil(L, arg+1)) {
  309.     lua_settop(L, arg+1);
  310.     func = NULL; mask = 0; count = 0;  /* turn off hooks */
  311.   }
  312.   else {
  313.     const char *smask = luaL_checkstring(L, arg+2);
  314.     luaL_checktype(L, arg+1, LUA_TFUNCTION);
  315.     count = luaL_optint(L, arg+3, 0);
  316.     func = hookf; mask = makemask(smask, count);
  317.   }
  318.   if (gethooktable(L) == 0) {  /* creating hook table? */
  319.     lua_pushstring(L, "k");
  320.     lua_setfield(L, -2, "__mode");  /** hooktable.__mode = "k" */
  321.     lua_pushvalue(L, -1);
  322.     lua_setmetatable(L, -2);  /* setmetatable(hooktable) = hooktable */
  323.   }
  324.   checkstack(L, L1, 1);
  325.   lua_pushthread(L1); lua_xmove(L1, L, 1);
  326.   lua_pushvalue(L, arg+1);
  327.   lua_rawset(L, -3);  /* set new hook */
  328.   lua_sethook(L1, func, mask, count);  /* set hooks */
  329.   return 0;
  330. }
  331.  
  332.  
  333. static int db_gethook (lua_State *L) {
  334.   int arg;
  335.   lua_State *L1 = getthread(L, &arg);
  336.   char buff[5];
  337.   int mask = lua_gethookmask(L1);
  338.   lua_Hook hook = lua_gethook(L1);
  339.   if (hook != NULL && hook != hookf)  /* external hook? */
  340.     lua_pushliteral(L, "external hook");
  341.   else {
  342.     gethooktable(L);
  343.     checkstack(L, L1, 1);
  344.     lua_pushthread(L1); lua_xmove(L1, L, 1);
  345.     lua_rawget(L, -2);   /* get hook */
  346.     lua_remove(L, -2);  /* remove hook table */
  347.   }
  348.   lua_pushstring(L, unmakemask(mask, buff));
  349.   lua_pushinteger(L, lua_gethookcount(L1));
  350.   return 3;
  351. }
  352.  
  353.  
  354. static int db_debug (lua_State *L) {
  355.   for (;;) {
  356.     char buffer[250];
  357.     luai_writestringerror("%s", "lua_debug> ");
  358.     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
  359.         strcmp(buffer, "cont\n") == 0)
  360.       return 0;
  361.     if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
  362.         lua_pcall(L, 0, 0, 0))
  363.       luai_writestringerror("%s\n", lua_tostring(L, -1));
  364.     lua_settop(L, 0);  /* remove eventual returns */
  365.   }
  366. }
  367.  
  368.  
  369. static int db_traceback (lua_State *L) {
  370.   int arg;
  371.   lua_State *L1 = getthread(L, &arg);
  372.   const char *msg = lua_tostring(L, arg + 1);
  373.   if (msg == NULL && !lua_isnoneornil(L, arg + 1))  /* non-string 'msg'? */
  374.     lua_pushvalue(L, arg + 1);  /* return it untouched */
  375.   else {
  376.     int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0);
  377.     luaL_traceback(L, L1, msg, level);
  378.   }
  379.   return 1;
  380. }
  381.  
  382.  
  383. static const luaL_Reg dblib[] = {
  384.   {"debug", db_debug},
  385.   {"getuservalue", db_getuservalue},
  386.   {"gethook", db_gethook},
  387.   {"getinfo", db_getinfo},
  388.   {"getlocal", db_getlocal},
  389.   {"getregistry", db_getregistry},
  390.   {"getmetatable", db_getmetatable},
  391.   {"getupvalue", db_getupvalue},
  392.   {"upvaluejoin", db_upvaluejoin},
  393.   {"upvalueid", db_upvalueid},
  394.   {"setuservalue", db_setuservalue},
  395.   {"sethook", db_sethook},
  396.   {"setlocal", db_setlocal},
  397.   {"setmetatable", db_setmetatable},
  398.   {"setupvalue", db_setupvalue},
  399.   {"traceback", db_traceback},
  400.   {NULL, NULL}
  401. };
  402.  
  403.  
  404. LUAMOD_API int luaopen_debug (lua_State *L) {
  405.   luaL_newlib(L, dblib);
  406.   return 1;
  407. }
  408.  
  409.