proxmark3/client/deps/liblua/ldblib.c

397 lines
11 KiB
C
Raw Normal View History

2013-05-22 02:23:42 +08:00
/*
** $Id: ldblib.c,v 1.132 2012/01/19 20:14:44 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ldblib_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
2019-03-10 01:16:50 +08:00
#define HOOKKEY "_HKEY"
2013-05-22 02:23:42 +08:00
static int db_getregistry(lua_State *L) {
2019-03-10 07:00:59 +08:00
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
2013-05-22 02:23:42 +08:00
}
static int db_getmetatable(lua_State *L) {
2019-03-10 07:00:59 +08:00
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L); /* no metatable */
}
return 1;
2013-05-22 02:23:42 +08:00
}
static int db_setmetatable(lua_State *L) {
2019-03-10 07:00:59 +08:00
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_setmetatable(L, 1);
return 1; /* return 1st argument */
2013-05-22 02:23:42 +08:00
}
static int db_getuservalue(lua_State *L) {
2019-03-10 07:00:59 +08:00
if (lua_type(L, 1) != LUA_TUSERDATA)
lua_pushnil(L);
else
lua_getuservalue(L, 1);
return 1;
2013-05-22 02:23:42 +08:00
}
static int db_setuservalue(lua_State *L) {
2019-03-10 07:00:59 +08:00
if (lua_type(L, 1) == LUA_TLIGHTUSERDATA)
luaL_argerror(L, 1, "full userdata expected, got light userdata");
luaL_checktype(L, 1, LUA_TUSERDATA);
if (!lua_isnoneornil(L, 2))
luaL_checktype(L, 2, LUA_TTABLE);
lua_settop(L, 2);
lua_setuservalue(L, 1);
return 1;
2013-05-22 02:23:42 +08:00
}
static void settabss(lua_State *L, const char *i, const char *v) {
2019-03-10 07:00:59 +08:00
lua_pushstring(L, v);
lua_setfield(L, -2, i);
2013-05-22 02:23:42 +08:00
}
static void settabsi(lua_State *L, const char *i, int v) {
2019-03-10 07:00:59 +08:00
lua_pushinteger(L, v);
lua_setfield(L, -2, i);
2013-05-22 02:23:42 +08:00
}
static void settabsb(lua_State *L, const char *i, int v) {
2019-03-10 07:00:59 +08:00
lua_pushboolean(L, v);
lua_setfield(L, -2, i);
2013-05-22 02:23:42 +08:00
}
static lua_State *getthread(lua_State *L, int *arg) {
2019-03-10 07:00:59 +08:00
if (lua_isthread(L, 1)) {
*arg = 1;
return lua_tothread(L, 1);
} else {
*arg = 0;
return L;
}
2013-05-22 02:23:42 +08:00
}
static void treatstackoption(lua_State *L, lua_State *L1, const char *fname) {
2019-03-10 07:00:59 +08:00
if (L == L1) {
lua_pushvalue(L, -2);
lua_remove(L, -3);
} else
lua_xmove(L1, L, 1);
lua_setfield(L, -2, fname);
2013-05-22 02:23:42 +08:00
}
static int db_getinfo(lua_State *L) {
2019-03-10 07:00:59 +08:00
lua_Debug ar;
int arg;
lua_State *L1 = getthread(L, &arg);
const char *options = luaL_optstring(L, arg + 2, "flnStu");
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, arg + 1)) {
lua_pushfstring(L, ">%s", options);
options = lua_tostring(L, -1);
lua_pushvalue(L, arg + 1);
lua_xmove(L, L1, 1);
} else
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);
2013-05-22 02:23:42 +08:00
}
2019-03-10 07:00:59 +08:00
if (strchr(options, 'l'))
settabsi(L, "currentline", ar.currentline);
if (strchr(options, 'u')) {
settabsi(L, "nups", ar.nups);
settabsi(L, "nparams", ar.nparams);
settabsb(L, "isvararg", ar.isvararg);
}
if (strchr(options, 'n')) {
settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat);
}
if (strchr(options, 't'))
settabsb(L, "istailcall", ar.istailcall);
if (strchr(options, 'L'))
treatstackoption(L, L1, "activelines");
if (strchr(options, 'f'))
treatstackoption(L, L1, "func");
return 1; /* return table */
2013-05-22 02:23:42 +08:00
}
static int db_getlocal(lua_State *L) {
2019-03-10 07:00:59 +08:00
int arg;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
const char *name;
int nvar = luaL_checkint(L, arg + 2); /* local-variable index */
if (lua_isfunction(L, arg + 1)) { /* function argument? */
lua_pushvalue(L, arg + 1); /* push function */
lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
return 1;
} else { /* stack-level argument */
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, nvar);
if (name) {
lua_xmove(L1, L, 1); /* push local value */
lua_pushstring(L, name); /* push name */
lua_pushvalue(L, -2); /* re-order */
return 2;
} else {
lua_pushnil(L); /* no name (nor value) */
return 1;
}
2013-05-22 02:23:42 +08:00
}
}
static int db_setlocal(lua_State *L) {
2019-03-10 07:00:59 +08:00
int arg;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
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;
2013-05-22 02:23:42 +08:00
}
static int auxupvalue(lua_State *L, int get) {
2019-03-10 07:00:59 +08:00
const char *name;
int n = luaL_checkint(L, 2);
luaL_checktype(L, 1, LUA_TFUNCTION);
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
if (name == NULL) return 0;
lua_pushstring(L, name);
lua_insert(L, -(get + 1));
return get + 1;
2013-05-22 02:23:42 +08:00
}
static int db_getupvalue(lua_State *L) {
2019-03-10 07:00:59 +08:00
return auxupvalue(L, 1);
2013-05-22 02:23:42 +08:00
}
static int db_setupvalue(lua_State *L) {
2019-03-10 07:00:59 +08:00
luaL_checkany(L, 3);
return auxupvalue(L, 0);
2013-05-22 02:23:42 +08:00
}
static int checkupval(lua_State *L, int argf, int argnup) {
2019-03-10 07:00:59 +08:00
lua_Debug ar;
int nup = luaL_checkint(L, argnup);
luaL_checktype(L, argf, LUA_TFUNCTION);
lua_pushvalue(L, argf);
lua_getinfo(L, ">u", &ar);
luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");
return nup;
2013-05-22 02:23:42 +08:00
}
static int db_upvalueid(lua_State *L) {
2019-03-10 07:00:59 +08:00
int n = checkupval(L, 1, 2);
lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
return 1;
2013-05-22 02:23:42 +08:00
}
static int db_upvaluejoin(lua_State *L) {
2019-03-10 07:00:59 +08:00
int n1 = checkupval(L, 1, 2);
int n2 = checkupval(L, 3, 4);
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
lua_upvaluejoin(L, 1, n1, 3, n2);
return 0;
2013-05-22 02:23:42 +08:00
}
2019-03-10 01:16:50 +08:00
#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
2013-05-22 02:23:42 +08:00
static void hookf(lua_State *L, lua_Debug *ar) {
2019-03-10 07:00:59 +08:00
static const char *const hooknames[] =
2013-05-22 02:23:42 +08:00
{"call", "return", "line", "count", "tail call"};
2019-03-10 07:00:59 +08:00
gethooktable(L);
lua_pushthread(L);
lua_rawget(L, -2);
if (lua_isfunction(L, -1)) {
lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0)
lua_pushinteger(L, ar->currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
}
2013-05-22 02:23:42 +08:00
}
static int makemask(const char *smask, int count) {
2019-03-10 07:00:59 +08:00
int mask = 0;
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
if (count > 0) mask |= LUA_MASKCOUNT;
return mask;
2013-05-22 02:23:42 +08:00
}
static char *unmakemask(int mask, char *smask) {
2019-03-10 07:00:59 +08:00
int i = 0;
if (mask & LUA_MASKCALL) smask[i++] = 'c';
if (mask & LUA_MASKRET) smask[i++] = 'r';
if (mask & LUA_MASKLINE) smask[i++] = 'l';
smask[i] = '\0';
return smask;
2013-05-22 02:23:42 +08:00
}
static int db_sethook(lua_State *L) {
2019-03-10 07:00:59 +08:00
int arg, mask, count;
lua_Hook func;
lua_State *L1 = getthread(L, &arg);
if (lua_isnoneornil(L, arg + 1)) {
lua_settop(L, arg + 1);
func = NULL;
mask = 0;
count = 0; /* turn off hooks */
} else {
const char *smask = luaL_checkstring(L, arg + 2);
luaL_checktype(L, arg + 1, LUA_TFUNCTION);
count = luaL_optint(L, arg + 3, 0);
func = hookf;
mask = makemask(smask, count);
}
if (gethooktable(L) == 0) { /* creating hook table? */
lua_pushstring(L, "k");
lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
lua_pushvalue(L, -1);
lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
}
lua_pushthread(L1);
lua_xmove(L1, L, 1);
lua_pushvalue(L, arg + 1);
lua_rawset(L, -3); /* set new hook */
lua_sethook(L1, func, mask, count); /* set hooks */
return 0;
2013-05-22 02:23:42 +08:00
}
static int db_gethook(lua_State *L) {
2019-03-10 07:00:59 +08:00
int arg;
lua_State *L1 = getthread(L, &arg);
char buff[5];
int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1);
if (hook != NULL && hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else {
gethooktable(L);
lua_pushthread(L1);
lua_xmove(L1, L, 1);
lua_rawget(L, -2); /* get hook */
lua_remove(L, -2); /* remove hook table */
}
lua_pushstring(L, unmakemask(mask, buff));
lua_pushinteger(L, lua_gethookcount(L1));
return 3;
2013-05-22 02:23:42 +08:00
}
static int db_debug(lua_State *L) {
2019-03-10 07:00:59 +08:00
for (;;) {
char buffer[250];
luai_writestringerror("%s", "lua_debug> ");
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0)
2019-03-10 07:00:59 +08:00
return 0;
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
lua_pcall(L, 0, 0, 0))
2019-03-10 07:00:59 +08:00
luai_writestringerror("%s\n", lua_tostring(L, -1));
lua_settop(L, 0); /* remove eventual returns */
}
2013-05-22 02:23:42 +08:00
}
static int db_traceback(lua_State *L) {
2019-03-10 07:00:59 +08:00
int arg;
lua_State *L1 = getthread(L, &arg);
const char *msg = lua_tostring(L, arg + 1);
if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
lua_pushvalue(L, arg + 1); /* return it untouched */
else {
int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0);
luaL_traceback(L, L1, msg, level);
}
return 1;
2013-05-22 02:23:42 +08:00
}
static const luaL_Reg dblib[] = {
2019-03-10 07:00:59 +08:00
{"debug", db_debug},
{"getuservalue", db_getuservalue},
{"gethook", db_gethook},
{"getinfo", db_getinfo},
{"getlocal", db_getlocal},
{"getregistry", db_getregistry},
{"getmetatable", db_getmetatable},
{"getupvalue", db_getupvalue},
{"upvaluejoin", db_upvaluejoin},
{"upvalueid", db_upvalueid},
{"setuservalue", db_setuservalue},
{"sethook", db_sethook},
{"setlocal", db_setlocal},
{"setmetatable", db_setmetatable},
{"setupvalue", db_setupvalue},
{"traceback", db_traceback},
{NULL, NULL}
2013-05-22 02:23:42 +08:00
};
LUAMOD_API int luaopen_debug(lua_State *L) {
2019-03-10 07:00:59 +08:00
luaL_newlib(L, dblib);
return 1;
2013-05-22 02:23:42 +08:00
}