?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. /*
  2. ** $Id: ldblib.c,v 1.151.1.1 2017/04/19 17:20:42 roberto Exp $
  3. ** Interface from Lua to its debug API
  4. ** See Copyright Notice in lua.h
  5. */
  6.  
  7. #define ldblib_c
  8. #define LUA_LIB
  9.  
  10. #include "lprefix.h"
  11.  
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17. #include "lua.h"
  18.  
  19. #include "lauxlib.h"
  20. #include "lualib.h"
  21.  
  22.  
  23. /*
  24. ** The hook table at registry[&HOOKKEY] maps threads to their current
  25. ** hook function. (We only need the unique address of 'HOOKKEY'.)
  26. */
  27. static const int HOOKKEY = 0;
  28.  
  29.  
  30. /*
  31. ** If L1 != L, L1 can be in any state, and therefore there are no
  32. ** guarantees about its stack space; any push in L1 must be
  33. ** checked.
  34. */
  35. static void checkstack (lua_State *L, lua_State *L1, int n) {
  36.   if (L != L1 && !lua_checkstack(L1, n))
  37.     luaL_error(L, "stack overflow");
  38. }
  39.  
  40.  
  41. static int db_getregistry (lua_State *L) {
  42.   lua_pushvalue(L, LUA_REGISTRYINDEX);
  43.   return 1;
  44. }
  45.  
  46.  
  47. static int db_getmetatable (lua_State *L) {
  48.   luaL_checkany(L, 1);
  49.   if (!lua_getmetatable(L, 1)) {
  50.     lua_pushnil(L);  /* no metatable */
  51.   }
  52.   return 1;
  53. }
  54.  
  55.  
  56. static int db_setmetatable (lua_State *L) {
  57.   int t = lua_type(L, 2);
  58.   luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
  59.                     "nil or table expected");
  60.   lua_settop(L, 2);
  61.   lua_setmetatable(L, 1);
  62.   return 1;  /* return 1st argument */
  63. }
  64.  
  65.  
  66. static int db_getuservalue (lua_State *L) {
  67.   if (lua_type(L, 1) != LUA_TUSERDATA)
  68.     lua_pushnil(L);
  69.   else
  70.     lua_getuservalue(L, 1);
  71.   return 1;
  72. }
  73.  
  74.  
  75. static int db_setuservalue (lua_State *L) {
  76.   luaL_checktype(L, 1, LUA_TUSERDATA);
  77.   luaL_checkany(L, 2);
  78.   lua_settop(L, 2);
  79.   lua_setuservalue(L, 1);
  80.   return 1;
  81. }
  82.  
  83.  
  84. /*
  85. ** Auxiliary function used by several library functions: check for
  86. ** an optional thread as function's first argument and set 'arg' with
  87. ** 1 if this argument is present (so that functions can skip it to
  88. ** access their other arguments)
  89. */
  90. static lua_State *getthread (lua_State *L, int *arg) {
  91.   if (lua_isthread(L, 1)) {
  92.     *arg = 1;
  93.     return lua_tothread(L, 1);
  94.   }
  95.   else {
  96.     *arg = 0;
  97.     return L;  /* function will operate over current thread */
  98.   }
  99. }
  100.  
  101.  
  102. /*
  103. ** Variations of 'lua_settable', used by 'db_getinfo' to put results
  104. ** from 'lua_getinfo' into result table. Key is always a string;
  105. ** value can be a string, an int, or a boolean.
  106. */
  107. static void settabss (lua_State *L, const char *k, const char *v) {
  108.   lua_pushstring(L, v);
  109.   lua_setfield(L, -2, k);
  110. }
  111.  
  112. static void settabsi (lua_State *L, const char *k, int v) {
  113.   lua_pushinteger(L, v);
  114.   lua_setfield(L, -2, k);
  115. }
  116.  
  117. static void settabsb (lua_State *L, const char *k, int v) {
  118.   lua_pushboolean(L, v);
  119.   lua_setfield(L, -2, k);
  120. }
  121.  
  122.  
  123. /*
  124. ** In function 'db_getinfo', the call to 'lua_getinfo' may push
  125. ** results on the stack; later it creates the result table to put
  126. ** these objects. Function 'treatstackoption' puts the result from
  127. ** 'lua_getinfo' on top of the result table so that it can call
  128. ** 'lua_setfield'.
  129. */
  130. static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
  131.   if (L == L1)
  132.     lua_rotate(L, -2, 1);  /* exchange object and table */
  133.   else
  134.     lua_xmove(L1, L, 1);  /* move object to the "main" stack */
  135.   lua_setfield(L, -2, fname);  /* put object into table */
  136. }
  137.  
  138.  
  139. /*
  140. ** Calls 'lua_getinfo' and collects all results in a new table.
  141. ** L1 needs stack space for an optional input (function) plus
  142. ** two optional outputs (function and line table) from function
  143. ** 'lua_getinfo'.
  144. */
  145. static int db_getinfo (lua_State *L) {
  146.   lua_Debug ar;
  147.   int arg;
  148.   lua_State *L1 = getthread(L, &arg);
  149.   const char *options = luaL_optstring(L, arg+2, "flnStu");
  150.   checkstack(L, L1, 3);
  151.   if (lua_isfunction(L, arg + 1)) {  /* info about a function? */
  152.     options = lua_pushfstring(L, ">%s", options);  /* add '>' to 'options' */
  153.     lua_pushvalue(L, arg + 1);  /* move function to 'L1' stack */
  154.     lua_xmove(L, L1, 1);
  155.   }
  156.   else {  /* stack level */
  157.     if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
  158.       lua_pushnil(L);  /* level out of range */
  159.       return 1;
  160.     }
  161.   }
  162.   if (!lua_getinfo(L1, options, &ar))
  163.     return luaL_argerror(L, arg+2, "invalid option");
  164.   lua_newtable(L);  /* table to collect results */
  165.   if (strchr(options, 'S')) {
  166.     settabss(L, "source", ar.source);
  167.     settabss(L, "short_src", ar.short_src);
  168.     settabsi(L, "linedefined", ar.linedefined);
  169.     settabsi(L, "lastlinedefined", ar.lastlinedefined);
  170.     settabss(L, "what", ar.what);
  171.   }
  172.   if (strchr(options, 'l'))
  173.     settabsi(L, "currentline", ar.currentline);
  174.   if (strchr(options, 'u')) {
  175.     settabsi(L, "nups", ar.nups);
  176.     settabsi(L, "nparams", ar.nparams);
  177.     settabsb(L, "isvararg", ar.isvararg);
  178.   }
  179.   if (strchr(options, 'n')) {
  180.     settabss(L, "name", ar.name);
  181.     settabss(L, "namewhat", ar.namewhat);
  182.   }
  183.   if (strchr(options, 't'))
  184.     settabsb(L, "istailcall", ar.istailcall);
  185.   if (strchr(options, 'L'))
  186.     treatstackoption(L, L1, "activelines");
  187.   if (strchr(options, 'f'))
  188.     treatstackoption(L, L1, "func");
  189.   return 1;  /* return table */
  190. }
  191.  
  192.  
  193. static int db_getlocal (lua_State *L) {
  194.   int arg;
  195.   lua_State *L1 = getthread(L, &arg);
  196.   lua_Debug ar;
  197.   const char *name;
  198.   int nvar = (int)luaL_checkinteger(L, arg + 2);  /* local-variable index */
  199.   if (lua_isfunction(L, arg + 1)) {  /* function argument? */
  200.     lua_pushvalue(L, arg + 1);  /* push function */
  201.     lua_pushstring(L, lua_getlocal(L, NULL, nvar));  /* push local name */
  202.     return 1;  /* return only name (there is no value) */
  203.   }
  204.   else {  /* stack-level argument */
  205.     int level = (int)luaL_checkinteger(L, arg + 1);
  206.     if (!lua_getstack(L1, level, &ar))  /* out of range? */
  207.       return luaL_argerror(L, arg+1, "level out of range");
  208.     checkstack(L, L1, 1);
  209.     name = lua_getlocal(L1, &ar, nvar);
  210.     if (name) {
  211.       lua_xmove(L1, L, 1);  /* move local value */
  212.       lua_pushstring(L, name);  /* push name */
  213.       lua_rotate(L, -2, 1);  /* re-order */
  214.       return 2;
  215.     }
  216.     else {
  217.       lua_pushnil(L);  /* no name (nor value) */
  218.       return 1;
  219.     }
  220.   }
  221. }
  222.  
  223.  
  224. static int db_setlocal (lua_State *L) {
  225.   int arg;
  226.   const char *name;
  227.   lua_State *L1 = getthread(L, &arg);
  228.   lua_Debug ar;
  229.   int level = (int)luaL_checkinteger(L, arg + 1);
  230.   int nvar = (int)luaL_checkinteger(L, arg + 2);
  231.   if (!lua_getstack(L1, level, &ar))  /* out of range? */
  232.     return luaL_argerror(L, arg+1, "level out of range");
  233.   luaL_checkany(L, arg+3);
  234.   lua_settop(L, arg+3);
  235.   checkstack(L, L1, 1);
  236.   lua_xmove(L, L1, 1);
  237.   name = lua_setlocal(L1, &ar, nvar);
  238.   if (name == NULL)
  239.     lua_pop(L1, 1);  /* pop value (if not popped by 'lua_setlocal') */
  240.   lua_pushstring(L, name);
  241.   return 1;
  242. }
  243.  
  244.  
  245. /*
  246. ** get (if 'get' is true) or set an upvalue from a closure
  247. */
  248. static int auxupvalue (lua_State *L, int get) {
  249.   const char *name;
  250.   int n = (int)luaL_checkinteger(L, 2);  /* upvalue index */
  251.   luaL_checktype(L, 1, LUA_TFUNCTION);  /* closure */
  252.   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
  253.   if (name == NULL) return 0;
  254.   lua_pushstring(L, name);
  255.   lua_insert(L, -(get+1));  /* no-op if get is false */
  256.   return get + 1;
  257. }
  258.  
  259.  
  260. static int db_getupvalue (lua_State *L) {
  261.   return auxupvalue(L, 1);
  262. }
  263.  
  264.  
  265. static int db_setupvalue (lua_State *L) {
  266.   luaL_checkany(L, 3);
  267.   return auxupvalue(L, 0);
  268. }
  269.  
  270.  
  271. /*
  272. ** Check whether a given upvalue from a given closure exists and
  273. ** returns its index
  274. */
  275. static int checkupval (lua_State *L, int argf, int argnup) {
  276.   int nup = (int)luaL_checkinteger(L, argnup);  /* upvalue index */
  277.   luaL_checktype(L, argf, LUA_TFUNCTION);  /* closure */
  278.   luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
  279.                    "invalid upvalue index");
  280.   return nup;
  281. }
  282.  
  283.  
  284. static int db_upvalueid (lua_State *L) {
  285.   int n = checkupval(L, 1, 2);
  286.   lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
  287.   return 1;
  288. }
  289.  
  290.  
  291. static int db_upvaluejoin (lua_State *L) {
  292.   int n1 = checkupval(L, 1, 2);
  293.   int n2 = checkupval(L, 3, 4);
  294.   luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
  295.   luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
  296.   lua_upvaluejoin(L, 1, n1, 3, n2);
  297.   return 0;
  298. }
  299.  
  300.  
  301. /*
  302. ** Call hook function registered at hook table for the current
  303. ** thread (if there is one)
  304. */
  305. static void hookf (lua_State *L, lua_Debug *ar) {
  306.   static const char *const hooknames[] =
  307.     {"call", "return", "line", "count", "tail call"};
  308.   lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
  309.   lua_pushthread(L);
  310.   if (lua_rawget(L, -2) == LUA_TFUNCTION) {  /* is there a hook function? */
  311.     lua_pushstring(L, hooknames[(int)ar->event]);  /* push event name */
  312.     if (ar->currentline >= 0)
  313.       lua_pushinteger(L, ar->currentline);  /* push current line */
  314.     else lua_pushnil(L);
  315.     lua_assert(lua_getinfo(L, "lS", ar));
  316.     lua_call(L, 2, 0);  /* call hook function */
  317.   }
  318. }
  319.  
  320.  
  321. /*
  322. ** Convert a string mask (for 'sethook') into a bit mask
  323. */
  324. static int makemask (const char *smask, int count) {
  325.   int mask = 0;
  326.   if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
  327.   if (strchr(smask, 'r')) mask |= LUA_MASKRET;
  328.   if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
  329.   if (count > 0) mask |= LUA_MASKCOUNT;
  330.   return mask;
  331. }
  332.  
  333.  
  334. /*
  335. ** Convert a bit mask (for 'gethook') into a string mask
  336. */
  337. static char *unmakemask (int mask, char *smask) {
  338.   int i = 0;
  339.   if (mask & LUA_MASKCALL) smask[i++] = 'c';
  340.   if (mask & LUA_MASKRET) smask[i++] = 'r';
  341.   if (mask & LUA_MASKLINE) smask[i++] = 'l';
  342.   smask[i] = '\0';
  343.   return smask;
  344. }
  345.  
  346.  
  347. static int db_sethook (lua_State *L) {
  348.   int arg, mask, count;
  349.   lua_Hook func;
  350.   lua_State *L1 = getthread(L, &arg);
  351.   if (lua_isnoneornil(L, arg+1)) {  /* no hook? */
  352.     lua_settop(L, arg+1);
  353.     func = NULL; mask = 0; count = 0;  /* turn off hooks */
  354.   }
  355.   else {
  356.     const char *smask = luaL_checkstring(L, arg+2);
  357.     luaL_checktype(L, arg+1, LUA_TFUNCTION);
  358.     count = (int)luaL_optinteger(L, arg + 3, 0);
  359.     func = hookf; mask = makemask(smask, count);
  360.   }
  361.   if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) {
  362.     lua_createtable(L, 0, 2);  /* create a hook table */
  363.     lua_pushvalue(L, -1);
  364.     lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY);  /* set it in position */
  365.     lua_pushstring(L, "k");
  366.     lua_setfield(L, -2, "__mode");  /** hooktable.__mode = "k" */
  367.     lua_pushvalue(L, -1);
  368.     lua_setmetatable(L, -2);  /* setmetatable(hooktable) = hooktable */
  369.   }
  370.   checkstack(L, L1, 1);
  371.   lua_pushthread(L1); lua_xmove(L1, L, 1);  /* key (thread) */
  372.   lua_pushvalue(L, arg + 1);  /* value (hook function) */
  373.   lua_rawset(L, -3);  /* hooktable[L1] = new Lua hook */
  374.   lua_sethook(L1, func, mask, count);
  375.   return 0;
  376. }
  377.  
  378.  
  379. static int db_gethook (lua_State *L) {
  380.   int arg;
  381.   lua_State *L1 = getthread(L, &arg);
  382.   char buff[5];
  383.   int mask = lua_gethookmask(L1);
  384.   lua_Hook hook = lua_gethook(L1);
  385.   if (hook == NULL)  /* no hook? */
  386.     lua_pushnil(L);
  387.   else if (hook != hookf)  /* external hook? */
  388.     lua_pushliteral(L, "external hook");
  389.   else {  /* hook table must exist */
  390.     lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
  391.     checkstack(L, L1, 1);
  392.     lua_pushthread(L1); lua_xmove(L1, L, 1);
  393.     lua_rawget(L, -2);   /* 1st result = hooktable[L1] */
  394.     lua_remove(L, -2);  /* remove hook table */
  395.   }
  396.   lua_pushstring(L, unmakemask(mask, buff));  /* 2nd result = mask */
  397.   lua_pushinteger(L, lua_gethookcount(L1));  /* 3rd result = count */
  398.   return 3;
  399. }
  400.  
  401.  
  402. static int db_debug (lua_State *L) {
  403.   for (;;) {
  404.     char buffer[250];
  405.     lua_writestringerror("%s", "lua_debug> ");
  406.     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
  407.         strcmp(buffer, "cont\n") == 0)
  408.       return 0;
  409.     if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
  410.         lua_pcall(L, 0, 0, 0))
  411.       lua_writestringerror("%s\n", lua_tostring(L, -1));
  412.     lua_settop(L, 0);  /* remove eventual returns */
  413.   }
  414. }
  415.  
  416.  
  417. static int db_traceback (lua_State *L) {
  418.   int arg;
  419.   lua_State *L1 = getthread(L, &arg);
  420.   const char *msg = lua_tostring(L, arg + 1);
  421.   if (msg == NULL && !lua_isnoneornil(L, arg + 1))  /* non-string 'msg'? */
  422.     lua_pushvalue(L, arg + 1);  /* return it untouched */
  423.   else {
  424.     int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0);
  425.     luaL_traceback(L, L1, msg, level);
  426.   }
  427.   return 1;
  428. }
  429.  
  430.  
  431. static const luaL_Reg dblib[] = {
  432.   {"debug", db_debug},
  433.   {"getuservalue", db_getuservalue},
  434.   {"gethook", db_gethook},
  435.   {"getinfo", db_getinfo},
  436.   {"getlocal", db_getlocal},
  437.   {"getregistry", db_getregistry},
  438.   {"getmetatable", db_getmetatable},
  439.   {"getupvalue", db_getupvalue},
  440.   {"upvaluejoin", db_upvaluejoin},
  441.   {"upvalueid", db_upvalueid},
  442.   {"setuservalue", db_setuservalue},
  443.   {"sethook", db_sethook},
  444.   {"setlocal", db_setlocal},
  445.   {"setmetatable", db_setmetatable},
  446.   {"setupvalue", db_setupvalue},
  447.   {"traceback", db_traceback},
  448.   {NULL, NULL}
  449. };
  450.  
  451.  
  452. LUAMOD_API int luaopen_debug (lua_State *L) {
  453.   luaL_newlib(L, dblib);
  454.   return 1;
  455. }
  456.  
  457.