ldblib.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:10k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /*
  2. ** $Id: ldblib.c,v 1.104 2005/12/29 15:32:11 roberto Exp $
  3. ** Interface from Lua to its debug API
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #define ldblib_c
  10. #define LUA_LIB
  11. #include "lua.h"
  12. #include "lauxlib.h"
  13. #include "lualib.h"
  14. static int db_getregistry (lua_State *L) {
  15.   lua_pushvalue(L, LUA_REGISTRYINDEX);
  16.   return 1;
  17. }
  18. static int db_getmetatable (lua_State *L) {
  19.   luaL_checkany(L, 1);
  20.   if (!lua_getmetatable(L, 1)) {
  21.     lua_pushnil(L);  /* no metatable */
  22.   }
  23.   return 1;
  24. }
  25. static int db_setmetatable (lua_State *L) {
  26.   int t = lua_type(L, 2);
  27.   luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
  28.                     "nil or table expected");
  29.   lua_settop(L, 2);
  30.   lua_pushboolean(L, lua_setmetatable(L, 1));
  31.   return 1;
  32. }
  33. static int db_getfenv (lua_State *L) {
  34.   lua_getfenv(L, 1);
  35.   return 1;
  36. }
  37. static int db_setfenv (lua_State *L) {
  38.   luaL_checktype(L, 2, LUA_TTABLE);
  39.   lua_settop(L, 2);
  40.   if (lua_setfenv(L, 1) == 0)
  41.     luaL_error(L, LUA_QL("setfenv")
  42.                   " cannot change environment of given object");
  43.   return 1;
  44. }
  45. static void settabss (lua_State *L, const char *i, const char *v) {
  46.   lua_pushstring(L, v);
  47.   lua_setfield(L, -2, i);
  48. }
  49. static void settabsi (lua_State *L, const char *i, int v) {
  50.   lua_pushinteger(L, v);
  51.   lua_setfield(L, -2, i);
  52. }
  53. static lua_State *getthread (lua_State *L, int *arg) {
  54.   if (lua_isthread(L, 1)) {
  55.     *arg = 1;
  56.     return lua_tothread(L, 1);
  57.   }
  58.   else {
  59.     *arg = 0;
  60.     return L;
  61.   }
  62. }
  63. static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
  64.   if (L == L1) {
  65.     lua_pushvalue(L, -2);
  66.     lua_remove(L, -3);
  67.   }
  68.   else
  69.     lua_xmove(L1, L, 1);
  70.   lua_setfield(L, -2, fname);
  71. }
  72. static int db_getinfo (lua_State *L) {
  73.   lua_Debug ar;
  74.   int arg;
  75.   lua_State *L1 = getthread(L, &arg);
  76.   const char *options = luaL_optstring(L, arg+2, "flnSu");
  77.   if (lua_isnumber(L, arg+1)) {
  78.     if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
  79.       lua_pushnil(L);  /* level out of range */
  80.       return 1;
  81.     }
  82.   }
  83.   else if (lua_isfunction(L, arg+1)) {
  84.     lua_pushfstring(L, ">%s", options);
  85.     options = lua_tostring(L, -1);
  86.     lua_pushvalue(L, arg+1);
  87.     lua_xmove(L, L1, 1);
  88.   }
  89.   else
  90.     return luaL_argerror(L, arg+1, "function or level expected");
  91.   if (!lua_getinfo(L1, options, &ar))
  92.     return luaL_argerror(L, arg+2, "invalid option");
  93.   lua_createtable(L, 0, 2);
  94.   if (strchr(options, 'S')) {
  95.     settabss(L, "source", ar.source);
  96.     settabss(L, "short_src", ar.short_src);
  97.     settabsi(L, "linedefined", ar.linedefined);
  98.     settabsi(L, "lastlinedefined", ar.lastlinedefined);
  99.     settabss(L, "what", ar.what);
  100.   }
  101.   if (strchr(options, 'l'))
  102.     settabsi(L, "currentline", ar.currentline);
  103.   if (strchr(options, 'u'))
  104.     settabsi(L, "nups", ar.nups);
  105.   if (strchr(options, 'n')) {
  106.     settabss(L, "name", ar.name);
  107.     settabss(L, "namewhat", ar.namewhat);
  108.   }
  109.   if (strchr(options, 'L'))
  110.     treatstackoption(L, L1, "activelines");
  111.   if (strchr(options, 'f'))
  112.     treatstackoption(L, L1, "func");
  113.   return 1;  /* return table */
  114. }
  115.     
  116. static int db_getlocal (lua_State *L) {
  117.   int arg;
  118.   lua_State *L1 = getthread(L, &arg);
  119.   lua_Debug ar;
  120.   const char *name;
  121.   if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
  122.     return luaL_argerror(L, arg+1, "level out of range");
  123.   name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
  124.   if (name) {
  125.     lua_xmove(L1, L, 1);
  126.     lua_pushstring(L, name);
  127.     lua_pushvalue(L, -2);
  128.     return 2;
  129.   }
  130.   else {
  131.     lua_pushnil(L);
  132.     return 1;
  133.   }
  134. }
  135. static int db_setlocal (lua_State *L) {
  136.   int arg;
  137.   lua_State *L1 = getthread(L, &arg);
  138.   lua_Debug ar;
  139.   if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
  140.     return luaL_argerror(L, arg+1, "level out of range");
  141.   luaL_checkany(L, arg+3);
  142.   lua_settop(L, arg+3);
  143.   lua_xmove(L, L1, 1);
  144.   lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
  145.   return 1;
  146. }
  147. static int auxupvalue (lua_State *L, int get) {
  148.   const char *name;
  149.   int n = luaL_checkint(L, 2);
  150.   luaL_checktype(L, 1, LUA_TFUNCTION);
  151.   if (lua_iscfunction(L, 1)) return 0;  /* cannot touch C upvalues from Lua */
  152.   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
  153.   if (name == NULL) return 0;
  154.   lua_pushstring(L, name);
  155.   lua_insert(L, -(get+1));
  156.   return get + 1;
  157. }
  158. static int db_getupvalue (lua_State *L) {
  159.   return auxupvalue(L, 1);
  160. }
  161. static int db_setupvalue (lua_State *L) {
  162.   luaL_checkany(L, 3);
  163.   return auxupvalue(L, 0);
  164. }
  165. static const char KEY_HOOK = 'h';
  166. static void hookf (lua_State *L, lua_Debug *ar) {
  167.   static const char *const hooknames[] =
  168.     {"call", "return", "line", "count", "tail return"};
  169.   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
  170.   lua_rawget(L, LUA_REGISTRYINDEX);
  171.   lua_pushlightuserdata(L, L);
  172.   lua_rawget(L, -2);
  173.   if (lua_isfunction(L, -1)) {
  174.     lua_pushstring(L, hooknames[(int)ar->event]);
  175.     if (ar->currentline >= 0)
  176.       lua_pushinteger(L, ar->currentline);
  177.     else lua_pushnil(L);
  178.     lua_assert(lua_getinfo(L, "lS", ar));
  179.     lua_call(L, 2, 0);
  180.   }
  181. }
  182. static int makemask (const char *smask, int count) {
  183.   int mask = 0;
  184.   if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
  185.   if (strchr(smask, 'r')) mask |= LUA_MASKRET;
  186.   if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
  187.   if (count > 0) mask |= LUA_MASKCOUNT;
  188.   return mask;
  189. }
  190. static char *unmakemask (int mask, char *smask) {
  191.   int i = 0;
  192.   if (mask & LUA_MASKCALL) smask[i++] = 'c';
  193.   if (mask & LUA_MASKRET) smask[i++] = 'r';
  194.   if (mask & LUA_MASKLINE) smask[i++] = 'l';
  195.   smask[i] = '';
  196.   return smask;
  197. }
  198. static void gethooktable (lua_State *L) {
  199.   lua_pushlightuserdata(L, (void *)&KEY_HOOK);
  200.   lua_rawget(L, LUA_REGISTRYINDEX);
  201.   if (!lua_istable(L, -1)) {
  202.     lua_pop(L, 1);
  203.     lua_createtable(L, 0, 1);
  204.     lua_pushlightuserdata(L, (void *)&KEY_HOOK);
  205.     lua_pushvalue(L, -2);
  206.     lua_rawset(L, LUA_REGISTRYINDEX);
  207.   }
  208. }
  209. static int db_sethook (lua_State *L) {
  210.   int arg;
  211.   lua_State *L1 = getthread(L, &arg);
  212.   if (lua_isnoneornil(L, arg+1)) {
  213.     lua_settop(L, arg+1);
  214.     lua_sethook(L1, NULL, 0, 0);  /* turn off hooks */
  215.   }
  216.   else {
  217.     const char *smask = luaL_checkstring(L, arg+2);
  218.     int count = luaL_optint(L, arg+3, 0);
  219.     luaL_checktype(L, arg+1, LUA_TFUNCTION);
  220.     lua_sethook(L1, hookf, makemask(smask, count), count);
  221.   }
  222.   gethooktable(L1);
  223.   lua_pushlightuserdata(L1, L1);
  224.   lua_pushvalue(L, arg+1);
  225.   lua_xmove(L, L1, 1);
  226.   lua_rawset(L1, -3);  /* set new hook */
  227.   lua_pop(L1, 1);  /* remove hook table */
  228.   return 0;
  229. }
  230. static int db_gethook (lua_State *L) {
  231.   int arg;
  232.   lua_State *L1 = getthread(L, &arg);
  233.   char buff[5];
  234.   int mask = lua_gethookmask(L1);
  235.   lua_Hook hook = lua_gethook(L1);
  236.   if (hook != NULL && hook != hookf)  /* external hook? */
  237.     lua_pushliteral(L, "external hook");
  238.   else {
  239.     gethooktable(L1);
  240.     lua_pushlightuserdata(L1, L1);
  241.     lua_rawget(L1, -2);   /* get hook */
  242.     lua_remove(L1, -2);  /* remove hook table */
  243.     lua_xmove(L1, L, 1);
  244.   }
  245.   lua_pushstring(L, unmakemask(mask, buff));
  246.   lua_pushinteger(L, lua_gethookcount(L1));
  247.   return 3;
  248. }
  249. static int db_debug (lua_State *L) {
  250.   for (;;) {
  251.     char buffer[250];
  252.     fputs("lua_debug> ", stderr);
  253.     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
  254.         strcmp(buffer, "contn") == 0)
  255.       return 0;
  256.     if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
  257.         lua_pcall(L, 0, 0, 0)) {
  258.       fputs(lua_tostring(L, -1), stderr);
  259.       fputs("n", stderr);
  260.     }
  261.     lua_settop(L, 0);  /* remove eventual returns */
  262.   }
  263. }
  264. #define LEVELS1 12 /* size of the first part of the stack */
  265. #define LEVELS2 10 /* size of the second part of the stack */
  266. static int db_errorfb (lua_State *L) {
  267.   int level;
  268.   int firstpart = 1;  /* still before eventual `...' */
  269.   int arg;
  270.   lua_State *L1 = getthread(L, &arg);
  271.   lua_Debug ar;
  272.   if (lua_isnumber(L, arg+2)) {
  273.     level = (int)lua_tointeger(L, arg+2);
  274.     lua_pop(L, 1);
  275.   }
  276.   else
  277.     level = (L == L1) ? 1 : 0;  /* level 0 may be this own function */
  278.   if (lua_gettop(L) == arg)
  279.     lua_pushliteral(L, "");
  280.   else if (!lua_isstring(L, arg+1)) return 1;  /* message is not a string */
  281.   else lua_pushliteral(L, "n");
  282.   lua_pushliteral(L, "stack traceback:");
  283.   while (lua_getstack(L1, level++, &ar)) {
  284.     if (level > LEVELS1 && firstpart) {
  285.       /* no more than `LEVELS2' more levels? */
  286.       if (!lua_getstack(L1, level+LEVELS2, &ar))
  287.         level--;  /* keep going */
  288.       else {
  289.         lua_pushliteral(L, "nt...");  /* too many levels */
  290.         while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */
  291.           level++;
  292.       }
  293.       firstpart = 0;
  294.       continue;
  295.     }
  296.     lua_pushliteral(L, "nt");
  297.     lua_getinfo(L1, "Snl", &ar);
  298.     lua_pushfstring(L, "%s:", ar.short_src);
  299.     if (ar.currentline > 0)
  300.       lua_pushfstring(L, "%d:", ar.currentline);
  301.     if (*ar.namewhat != '')  /* is there a name? */
  302.         lua_pushfstring(L, " in function " LUA_QS, ar.name);
  303.     else {
  304.       if (*ar.what == 'm')  /* main? */
  305.         lua_pushfstring(L, " in main chunk");
  306.       else if (*ar.what == 'C' || *ar.what == 't')
  307.         lua_pushliteral(L, " ?");  /* C function or tail call */
  308.       else
  309.         lua_pushfstring(L, " in function <%s:%d>",
  310.                            ar.short_src, ar.linedefined);
  311.     }
  312.     lua_concat(L, lua_gettop(L) - arg);
  313.   }
  314.   lua_concat(L, lua_gettop(L) - arg);
  315.   return 1;
  316. }
  317. static const luaL_Reg dblib[] = {
  318.   {"debug", db_debug},
  319.   {"getfenv", db_getfenv},
  320.   {"gethook", db_gethook},
  321.   {"getinfo", db_getinfo},
  322.   {"getlocal", db_getlocal},
  323.   {"getregistry", db_getregistry},
  324.   {"getmetatable", db_getmetatable},
  325.   {"getupvalue", db_getupvalue},
  326.   {"setfenv", db_setfenv},
  327.   {"sethook", db_sethook},
  328.   {"setlocal", db_setlocal},
  329.   {"setmetatable", db_setmetatable},
  330.   {"setupvalue", db_setupvalue},
  331.   {"traceback", db_errorfb},
  332.   {NULL, NULL}
  333. };
  334. LUALIB_API int luaopen_debug (lua_State *L) {
  335.   luaL_register(L, LUA_DBLIBNAME, dblib);
  336.   return 1;
  337. }