|
@@ -0,0 +1,213 @@
|
|
|
|
+/*
|
|
|
|
+** $Id: $
|
|
|
|
+** Interface from Lua to its debug API
|
|
|
|
+** See Copyright Notice in lua.h
|
|
|
|
+*/
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#include <stdlib.h>
|
|
|
|
+#include <string.h>
|
|
|
|
+
|
|
|
|
+#include "lauxlib.h"
|
|
|
|
+#include "lua.h"
|
|
|
|
+#include "luadebug.h"
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void settabss (lua_Object t, char *i, char *v) {
|
|
|
|
+ lua_pushobject(t);
|
|
|
|
+ lua_pushstring(i);
|
|
|
|
+ lua_pushstring(v);
|
|
|
|
+ lua_settable();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void settabsi (lua_Object t, char *i, int v) {
|
|
|
|
+ lua_pushobject(t);
|
|
|
|
+ lua_pushstring(i);
|
|
|
|
+ lua_pushnumber(v);
|
|
|
|
+ lua_settable();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static lua_Object getfuncinfo (lua_Object func) {
|
|
|
|
+ lua_Object result = lua_createtable();
|
|
|
|
+ char *name;
|
|
|
|
+ int line;
|
|
|
|
+ lua_funcinfo(func, &name, &line);
|
|
|
|
+ if (line == -1) /* C function? */
|
|
|
|
+ settabss(result, "kind", "C");
|
|
|
|
+ else if (line == 0) { /* "main"? */
|
|
|
|
+ settabss(result, "kind", "chunk");
|
|
|
|
+ settabss(result, "name", name);
|
|
|
|
+ }
|
|
|
|
+ else { /* Lua function */
|
|
|
|
+ settabss(result, "kind", "Lua");
|
|
|
|
+ settabsi(result, "def_line", line);
|
|
|
|
+ settabss(result, "def_chunk", name);
|
|
|
|
+ }
|
|
|
|
+ if (line != 0) { /* is it not a "main"? */
|
|
|
|
+ char *kind = lua_getobjname(func, &name);
|
|
|
|
+ if (*kind) {
|
|
|
|
+ settabss(result, "name", name);
|
|
|
|
+ settabss(result, "where", kind);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void getstack (void) {
|
|
|
|
+ lua_Object func = lua_stackedfunction(luaL_check_int(1));
|
|
|
|
+ if (func == LUA_NOOBJECT) /* level out of range? */
|
|
|
|
+ return;
|
|
|
|
+ else {
|
|
|
|
+ lua_Object result = getfuncinfo(func);
|
|
|
|
+ int currline = lua_currentline(func);
|
|
|
|
+ if (currline > 0)
|
|
|
|
+ settabsi(result, "current", currline);
|
|
|
|
+ lua_pushobject(result);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void funcinfo (void) {
|
|
|
|
+ lua_pushobject(getfuncinfo(luaL_functionarg(1)));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int findlocal (lua_Object func, int arg) {
|
|
|
|
+ lua_Object v = lua_getparam(arg);
|
|
|
|
+ if (lua_isnumber(v))
|
|
|
|
+ return (int)lua_getnumber(v);
|
|
|
|
+ else {
|
|
|
|
+ char *name = luaL_check_string(arg);
|
|
|
|
+ int i = 0;
|
|
|
|
+ int result = -1;
|
|
|
|
+ char *vname;
|
|
|
|
+ while (lua_getlocal(func, ++i, &vname) != LUA_NOOBJECT) {
|
|
|
|
+ if (strcmp(name, vname) == 0)
|
|
|
|
+ result = i; /* keep looping to get the last var with this name */
|
|
|
|
+ }
|
|
|
|
+ if (result == -1)
|
|
|
|
+ luaL_verror("no local variable `%.50s' at given level", name);
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void getlocal (void) {
|
|
|
|
+ lua_Object func = lua_stackedfunction(luaL_check_int(1));
|
|
|
|
+ lua_Object val;
|
|
|
|
+ char *name;
|
|
|
|
+ if (func == LUA_NOOBJECT) /* level out of range? */
|
|
|
|
+ return; /* return nil */
|
|
|
|
+ else if (lua_getparam(2) != LUA_NOOBJECT) { /* 2nd argument? */
|
|
|
|
+ if ((val = lua_getlocal(func, findlocal(func, 2), &name)) != LUA_NOOBJECT) {
|
|
|
|
+ lua_pushobject(val);
|
|
|
|
+ lua_pushstring(name);
|
|
|
|
+ }
|
|
|
|
+ /* else return nil */
|
|
|
|
+ }
|
|
|
|
+ else { /* collect all locals in a table */
|
|
|
|
+ lua_Object result = lua_createtable();
|
|
|
|
+ int i;
|
|
|
|
+ for (i=1; ;i++) {
|
|
|
|
+ if ((val = lua_getlocal(func, i, &name)) == LUA_NOOBJECT)
|
|
|
|
+ break;
|
|
|
|
+ lua_pushobject(result);
|
|
|
|
+ lua_pushstring(name);
|
|
|
|
+ lua_pushobject(val);
|
|
|
|
+ lua_settable(); /* result[name] = value */
|
|
|
|
+ }
|
|
|
|
+ lua_pushobject(result);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void setlocal (void) {
|
|
|
|
+ lua_Object func = lua_stackedfunction(luaL_check_int(1));
|
|
|
|
+ int numvar;
|
|
|
|
+ luaL_arg_check(func != LUA_NOOBJECT, 1, "level out of range");
|
|
|
|
+ numvar = findlocal(func, 2);
|
|
|
|
+ lua_pushobject(luaL_nonnullarg(3));
|
|
|
|
+ if (!lua_setlocal(func, numvar))
|
|
|
|
+ lua_error("no such local variable");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int linehook = -1; /* Lua reference to line hook function */
|
|
|
|
+static int callhook = -1; /* Lua reference to call hook function */
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void dohook (int ref) {
|
|
|
|
+ lua_LHFunction oldlinehook = lua_linehook; /* save old hooks */
|
|
|
|
+ lua_CHFunction oldcallhook = lua_callhook;
|
|
|
|
+ lua_linehook = NULL; lua_callhook = NULL; /* to avoid recusive calls */
|
|
|
|
+ lua_callfunction(lua_getref(ref));
|
|
|
|
+ lua_linehook = oldlinehook; /* restore old hooks */
|
|
|
|
+ lua_callhook = oldcallhook;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void linef (int line) {
|
|
|
|
+ lua_pushnumber(line);
|
|
|
|
+ dohook(linehook);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void callf (lua_Function func, char *file, int line) {
|
|
|
|
+ if (func != LUA_NOOBJECT) {
|
|
|
|
+ lua_pushobject(func);
|
|
|
|
+ lua_pushstring(file);
|
|
|
|
+ lua_pushnumber(line);
|
|
|
|
+ }
|
|
|
|
+ dohook(callhook);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void setcallhook (void) {
|
|
|
|
+ lua_Object f = lua_getparam(1);
|
|
|
|
+ lua_unref(callhook);
|
|
|
|
+ if (f == LUA_NOOBJECT) {
|
|
|
|
+ callhook = -1;
|
|
|
|
+ lua_callhook = NULL;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ lua_pushobject(f);
|
|
|
|
+ callhook = lua_ref(1);
|
|
|
|
+ lua_callhook = callf;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void setlinehook (void) {
|
|
|
|
+ lua_Object f = lua_getparam(1);
|
|
|
|
+ lua_unref(linehook);
|
|
|
|
+ if (f == LUA_NOOBJECT) {
|
|
|
|
+ linehook = -1;
|
|
|
|
+ lua_linehook = NULL;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ lua_pushobject(f);
|
|
|
|
+ linehook = lua_ref(1);
|
|
|
|
+ lua_linehook = linef;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static struct luaL_reg dblib[] = {
|
|
|
|
+ {"funcinfo", funcinfo},
|
|
|
|
+ {"getlocal", getlocal},
|
|
|
|
+ {"getstack", getstack},
|
|
|
|
+ {"setcallhook", setcallhook},
|
|
|
|
+ {"setlinehook", setlinehook},
|
|
|
|
+ {"setlocal", setlocal}
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void lua_dblibopen (void) {
|
|
|
|
+ luaL_openlib(dblib, (sizeof(dblib)/sizeof(dblib[0])));
|
|
|
|
+}
|
|
|
|
+
|