summaryrefslogtreecommitdiff
path: root/lib/lua/src/LuaLib/ldblib.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lua/src/LuaLib/ldblib.c')
-rw-r--r--lib/lua/src/LuaLib/ldblib.c324
1 files changed, 211 insertions, 113 deletions
diff --git a/lib/lua/src/LuaLib/ldblib.c b/lib/lua/src/LuaLib/ldblib.c
index 2449b90..076ddac 100644
--- a/lib/lua/src/LuaLib/ldblib.c
+++ b/lib/lua/src/LuaLib/ldblib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldblib.c,v 1.4 2004-11-27 21:46:10 pixel Exp $
+** $Id: ldblib.c,v 1.5 2007-07-27 10:05:55 pixel Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,7 @@
#include <string.h>
#define ldblib_c
+#define LUA_LIB
#include "lua.h"
@@ -18,75 +19,137 @@
+static int db_getregistry (lua_State *L) {
+ lua_pushvalue(L, LUA_REGISTRYINDEX);
+ return 1;
+}
+
+
+static int db_getmetatable (lua_State *L) {
+ luaL_checkany(L, 1);
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L); /* no metatable */
+ }
+ return 1;
+}
+
+
+static int db_setmetatable (lua_State *L) {
+ int t = lua_type(L, 2);
+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+ "nil or table expected");
+ lua_settop(L, 2);
+ lua_pushboolean(L, lua_setmetatable(L, 1));
+ return 1;
+}
+
+
+static int db_getfenv (lua_State *L) {
+ lua_getfenv(L, 1);
+ return 1;
+}
+
+
+static int db_setfenv (lua_State *L) {
+ luaL_checktype(L, 2, LUA_TTABLE);
+ lua_settop(L, 2);
+ if (lua_setfenv(L, 1) == 0)
+ luaL_error(L, LUA_QL("setfenv")
+ " cannot change environment of given object");
+ return 1;
+}
+
+
static void settabss (lua_State *L, const char *i, const char *v) {
- lua_pushstring(L, i);
lua_pushstring(L, v);
- lua_rawset(L, -3);
+ lua_setfield(L, -2, i);
}
static void settabsi (lua_State *L, const char *i, int v) {
- lua_pushstring(L, i);
- lua_pushnumber(L, (lua_Number)v);
- lua_rawset(L, -3);
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, i);
}
-static int getinfo (lua_State *L) {
+static lua_State *getthread (lua_State *L, int *arg) {
+ if (lua_isthread(L, 1)) {
+ *arg = 1;
+ return lua_tothread(L, 1);
+ }
+ else {
+ *arg = 0;
+ return L;
+ }
+}
+
+
+static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
+ if (L == L1) {
+ lua_pushvalue(L, -2);
+ lua_remove(L, -3);
+ }
+ else
+ lua_xmove(L1, L, 1);
+ lua_setfield(L, -2, fname);
+}
+
+
+static int db_getinfo (lua_State *L) {
lua_Debug ar;
- const char *options = luaL_optstring(L, 2, "flnSu");
- if (lua_isnumber(L, 1)) {
- if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ const char *options = luaL_optstring(L, arg+2, "flnSu");
+ if (lua_isnumber(L, arg+1)) {
+ if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
lua_pushnil(L); /* level out of range */
return 1;
}
}
- else if (lua_isfunction(L, 1)) {
+ else if (lua_isfunction(L, arg+1)) {
lua_pushfstring(L, ">%s", options);
options = lua_tostring(L, -1);
- lua_pushvalue(L, 1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
}
else
- return luaL_argerror(L, 1, "function or level expected");
- if (!lua_getinfo(L, options, &ar))
- return luaL_argerror(L, 2, "invalid option");
- lua_newtable(L);
- for (; *options; options++) {
- switch (*options) {
- case 'S':
- settabss(L, "source", ar.source);
- settabss(L, "short_src", ar.short_src);
- settabsi(L, "linedefined", ar.linedefined);
- settabss(L, "what", ar.what);
- break;
- case 'l':
- settabsi(L, "currentline", ar.currentline);
- break;
- case 'u':
- settabsi(L, "nups", ar.nups);
- break;
- case 'n':
- settabss(L, "name", ar.name);
- settabss(L, "namewhat", ar.namewhat);
- break;
- case 'f':
- lua_pushliteral(L, "func");
- lua_pushvalue(L, -3);
- lua_rawset(L, -3);
- break;
- }
+ return luaL_argerror(L, arg+1, "function or level expected");
+ if (!lua_getinfo(L1, options, &ar))
+ return luaL_argerror(L, arg+2, "invalid option");
+ lua_createtable(L, 0, 2);
+ if (strchr(options, 'S')) {
+ settabss(L, "source", ar.source);
+ settabss(L, "short_src", ar.short_src);
+ settabsi(L, "linedefined", ar.linedefined);
+ settabsi(L, "lastlinedefined", ar.lastlinedefined);
+ settabss(L, "what", ar.what);
+ }
+ if (strchr(options, 'l'))
+ settabsi(L, "currentline", ar.currentline);
+ if (strchr(options, 'u'))
+ settabsi(L, "nups", ar.nups);
+ if (strchr(options, 'n')) {
+ settabss(L, "name", ar.name);
+ settabss(L, "namewhat", ar.namewhat);
}
+ if (strchr(options, 'L'))
+ treatstackoption(L, L1, "activelines");
+ if (strchr(options, 'f'))
+ treatstackoption(L, L1, "func");
return 1; /* return table */
}
-static int getlocal (lua_State *L) {
+static int db_getlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
const char *name;
- if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
- return luaL_argerror(L, 1, "level out of range");
- name = lua_getlocal(L, &ar, luaL_checkint(L, 2));
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
if (name) {
+ lua_xmove(L1, L, 1);
lua_pushstring(L, name);
lua_pushvalue(L, -2);
return 2;
@@ -98,12 +161,16 @@ static int getlocal (lua_State *L) {
}
-static int setlocal (lua_State *L) {
+static int db_setlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
- if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
- return luaL_argerror(L, 1, "level out of range");
- luaL_checkany(L, 3);
- lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2)));
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ luaL_checkany(L, arg+3);
+ lua_settop(L, arg+3);
+ lua_xmove(L, L1, 1);
+ lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
return 1;
}
@@ -121,12 +188,12 @@ static int auxupvalue (lua_State *L, int get) {
}
-static int getupvalue (lua_State *L) {
+static int db_getupvalue (lua_State *L) {
return auxupvalue(L, 1);
}
-static int setupvalue (lua_State *L) {
+static int db_setupvalue (lua_State *L) {
luaL_checkany(L, 3);
return auxupvalue(L, 0);
}
@@ -141,16 +208,16 @@ static void hookf (lua_State *L, lua_Debug *ar) {
{"call", "return", "line", "count", "tail return"};
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, L);
+ lua_rawget(L, -2);
if (lua_isfunction(L, -1)) {
lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0)
- lua_pushnumber(L, (lua_Number)ar->currentline);
+ lua_pushinteger(L, ar->currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
}
- else
- lua_pop(L, 1); /* pop result from gettable */
}
@@ -174,48 +241,75 @@ static char *unmakemask (int mask, char *smask) {
}
-static int sethook (lua_State *L) {
- if (lua_isnoneornil(L, 1)) {
- lua_settop(L, 1);
- lua_sethook(L, NULL, 0, 0); /* turn off hooks */
+static void gethooktable (lua_State *L) {
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ lua_createtable(L, 0, 1);
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ }
+}
+
+
+static int db_sethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ if (lua_isnoneornil(L, arg+1)) {
+ lua_settop(L, arg+1);
+ lua_sethook(L1, NULL, 0, 0); /* turn off hooks */
}
else {
- const char *smask = luaL_checkstring(L, 2);
- int count = luaL_optint(L, 3, 0);
- luaL_checktype(L, 1, LUA_TFUNCTION);
- lua_sethook(L, hookf, makemask(smask, count), count);
+ const char *smask = luaL_checkstring(L, arg+2);
+ int count = luaL_optint(L, arg+3, 0);
+ luaL_checktype(L, arg+1, LUA_TFUNCTION);
+ lua_sethook(L1, hookf, makemask(smask, count), count);
}
- lua_pushlightuserdata(L, (void *)&KEY_HOOK);
- lua_pushvalue(L, 1);
- lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */
+ gethooktable(L1);
+ lua_pushlightuserdata(L1, L1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
+ lua_rawset(L1, -3); /* set new hook */
+ lua_pop(L1, 1); /* remove hook table */
return 0;
}
-static int gethook (lua_State *L) {
+static int db_gethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
char buff[5];
- int mask = lua_gethookmask(L);
- lua_Hook hook = lua_gethook(L);
+ int mask = lua_gethookmask(L1);
+ lua_Hook hook = lua_gethook(L1);
if (hook != NULL && hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else {
- lua_pushlightuserdata(L, (void *)&KEY_HOOK);
- lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
+ gethooktable(L1);
+ lua_pushlightuserdata(L1, L1);
+ lua_rawget(L1, -2); /* get hook */
+ lua_remove(L1, -2); /* remove hook table */
+ lua_xmove(L1, L, 1);
}
lua_pushstring(L, unmakemask(mask, buff));
- lua_pushnumber(L, (lua_Number)lua_gethookcount(L));
+ lua_pushinteger(L, lua_gethookcount(L1));
return 3;
}
-static int debug (lua_State *L) {
+static int db_debug (lua_State *L) {
for (;;) {
char buffer[250];
fputs("lua_debug> ", stderr);
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0)
return 0;
- lua_dostring(L, buffer);
+ if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
+ lua_pcall(L, 0, 0, 0)) {
+ fputs(lua_tostring(L, -1), stderr);
+ fputs("\n", stderr);
+ }
lua_settop(L, 0); /* remove eventual returns */
}
}
@@ -224,76 +318,80 @@ static int debug (lua_State *L) {
#define LEVELS1 12 /* size of the first part of the stack */
#define LEVELS2 10 /* size of the second part of the stack */
-static int errorfb (lua_State *L) {
- int level = 1; /* skip level 0 (it's this function) */
+static int db_errorfb (lua_State *L) {
+ int level;
int firstpart = 1; /* still before eventual `...' */
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
- if (lua_gettop(L) == 0)
+ if (lua_isnumber(L, arg+2)) {
+ level = (int)lua_tointeger(L, arg+2);
+ lua_pop(L, 1);
+ }
+ else
+ level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
+ if (lua_gettop(L) == arg)
lua_pushliteral(L, "");
- else if (!lua_isstring(L, 1)) return 1; /* no string message */
+ else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
- while (lua_getstack(L, level++, &ar)) {
+ while (lua_getstack(L1, level++, &ar)) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
- if (!lua_getstack(L, level+LEVELS2, &ar))
+ if (!lua_getstack(L1, level+LEVELS2, &ar))
level--; /* keep going */
else {
lua_pushliteral(L, "\n\t..."); /* too many levels */
- while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */
+ while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\n\t");
- lua_getinfo(L, "Snl", &ar);
+ lua_getinfo(L1, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
- switch (*ar.namewhat) {
- case 'g': /* global */
- case 'l': /* local */
- case 'f': /* field */
- case 'm': /* method */
- lua_pushfstring(L, " in function `%s'", ar.name);
- break;
- default: {
- if (*ar.what == 'm') /* main? */
- lua_pushfstring(L, " in main chunk");
- else if (*ar.what == 'C' || *ar.what == 't')
- lua_pushliteral(L, " ?"); /* C function or tail call */
- else
- lua_pushfstring(L, " in function <%s:%d>",
- ar.short_src, ar.linedefined);
- }
+ if (*ar.namewhat != '\0') /* is there a name? */
+ lua_pushfstring(L, " in function " LUA_QS, ar.name);
+ else {
+ if (*ar.what == 'm') /* main? */
+ lua_pushfstring(L, " in main chunk");
+ else if (*ar.what == 'C' || *ar.what == 't')
+ lua_pushliteral(L, " ?"); /* C function or tail call */
+ else
+ lua_pushfstring(L, " in function <%s:%d>",
+ ar.short_src, ar.linedefined);
}
- lua_concat(L, lua_gettop(L));
+ lua_concat(L, lua_gettop(L) - arg);
}
- lua_concat(L, lua_gettop(L));
+ lua_concat(L, lua_gettop(L) - arg);
return 1;
}
-static const luaL_reg dblib[] = {
- {"getlocal", getlocal},
- {"getinfo", getinfo},
- {"gethook", gethook},
- {"getupvalue", getupvalue},
- {"sethook", sethook},
- {"setlocal", setlocal},
- {"setupvalue", setupvalue},
- {"debug", debug},
- {"traceback", errorfb},
+static const luaL_Reg dblib[] = {
+ {"debug", db_debug},
+ {"getfenv", db_getfenv},
+ {"gethook", db_gethook},
+ {"getinfo", db_getinfo},
+ {"getlocal", db_getlocal},
+ {"getregistry", db_getregistry},
+ {"getmetatable", db_getmetatable},
+ {"getupvalue", db_getupvalue},
+ {"setfenv", db_setfenv},
+ {"sethook", db_sethook},
+ {"setlocal", db_setlocal},
+ {"setmetatable", db_setmetatable},
+ {"setupvalue", db_setupvalue},
+ {"traceback", db_errorfb},
{NULL, NULL}
};
LUALIB_API int luaopen_debug (lua_State *L) {
- luaL_openlib(L, LUA_DBLIBNAME, dblib, 0);
- lua_pushliteral(L, "_TRACEBACK");
- lua_pushcfunction(L, errorfb);
- lua_settable(L, LUA_GLOBALSINDEX);
+ luaL_register(L, LUA_DBLIBNAME, dblib);
return 1;
}