?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  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.  
  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.  
  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.  
  399.