commit df1dc3f1f54a75174cea7298d5c40bc7b99e60ea
parent 513d0258d9d6ec5b52efc612ebc52aa5161c23fa
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Tue, 1 Dec 2009 14:49:24 -0200
strings in C scripts may be delimited by quotes + new functionality to
set C scripts as C hooks
Diffstat:
M | ltests.c | | | 92 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
1 file changed, 76 insertions(+), 16 deletions(-)
diff --git a/ltests.c b/ltests.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltests.c,v 2.79 2009/11/06 17:08:43 roberto Exp roberto $
+** $Id: ltests.c,v 2.80 2009/11/27 15:39:31 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@@ -810,6 +810,9 @@ static int int2fb_aux (lua_State *L) {
** =======================================================
*/
+
+static void sethookaux (lua_State *L, int mask, int count, const char *code);
+
static const char *const delimits = " \t\n,;";
static void skip (const char **pc) {
@@ -842,11 +845,21 @@ static int getnum_aux (lua_State *L, const char **pc) {
return sig*res;
}
-static const char *getname_aux (char *buff, const char **pc) {
+static const char *getname_aux (lua_State *L, char *buff, const char **pc) {
int i = 0;
skip(pc);
- while (**pc != '\0' && !strchr(delimits, **pc))
- buff[i++] = *(*pc)++;
+ if (**pc == '"' || **pc == '\'') { /* quoted string? */
+ int quote = *(*pc)++;
+ while (**pc != quote) {
+ if (**pc == '\0') luaL_error(L, "unfinished string in C script");
+ buff[i++] = *(*pc)++;
+ }
+ (*pc)++;
+ }
+ else {
+ while (**pc != '\0' && !strchr(delimits, **pc))
+ buff[i++] = *(*pc)++;
+ }
buff[i] = '\0';
return buff;
}
@@ -866,7 +879,7 @@ static int getindex_aux (lua_State *L, const char **pc) {
#define EQ(s1) (strcmp(s1, inst) == 0)
#define getnum (getnum_aux(L, &pc))
-#define getname (getname_aux(buff, &pc))
+#define getname (getname_aux(L, buff, &pc))
#define getindex (getindex_aux(L, &pc))
@@ -874,8 +887,8 @@ static int testC (lua_State *L);
static int Cfunck (lua_State *L);
static int runC (lua_State *L, lua_State *L1, const char *pc) {
- char buff[30];
- if (pc == NULL) return luaL_error(L, "attempt to runC null code");
+ char buff[300];
+ if (pc == NULL) return luaL_error(L, "attempt to runC null script");
for (;;) {
const char *inst = getname;
if EQ("") return 0;
@@ -1079,6 +1092,11 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
int i = getindex;
lua_pushinteger(L1, lua_objlen(L1, i));
}
+ else if EQ("append") {
+ int t = getindex;
+ int i = lua_objlen(L1, t);
+ lua_rawseti(L1, t, i + 1);
+ }
else if EQ("getctx") {
static const char *const codes[] = {"OK", "YIELD", "ERRRUN",
"ERRSYNTAX", "ERRMEM", "ERRGCMM", "ERRERR"};
@@ -1105,6 +1123,11 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
lua_tostring(L, b),
lua_tostring(L, c));
}
+ else if EQ("sethook") {
+ int mask = getnum;
+ int count = getnum;
+ sethookaux(L1, mask, count, getname);
+ }
else if EQ("throw") {
#if defined(__cplusplus)
static struct X { int x; } x;
@@ -1163,25 +1186,62 @@ static int makeCfunc (lua_State *L) {
/*
** {======================================================
-** tests for yield inside hooks
+** tests for C hooks
** =======================================================
*/
-static void yieldf (lua_State *L, lua_Debug *ar) {
- UNUSED(ar);
- lua_yield(L, 0);
+/*
+** C hook that runs the C script stored in registry.C_HOOK[L]
+*/
+static void Chook (lua_State *L, lua_Debug *ar) {
+ const char *scpt;
+ const char *const events [] = {"call", "ret", "line", "count", "tailcall"};
+ lua_getfield(L, LUA_REGISTRYINDEX, "C_HOOK");
+ lua_pushlightuserdata(L, L);
+ lua_gettable(L, -2); /* get C_HOOK[L] (script saved by sethookaux) */
+ scpt = lua_tostring(L, -1); /* not very religious (string will be popped) */
+ lua_pop(L, 2); /* remove C_HOOK and script */
+ lua_pushstring(L, events[ar->event]); /* may be used by script */
+ lua_pushinteger(L, ar->currentline); /* may be used by script */
+ runC(L, L, scpt); /* run script from C_HOOK[L] */
+}
+
+
+/*
+** sets registry.C_HOOK[L] = scpt and sets Chook as a hook
+*/
+static void sethookaux (lua_State *L, int mask, int count, const char *scpt) {
+ if (*scpt == '\0') { /* no script? */
+ lua_sethook(L, NULL, 0, 0); /* turn off hooks */
+ return;
+ }
+ lua_getfield(L, LUA_REGISTRYINDEX, "C_HOOK"); /* get C_HOOK table */
+ if (!lua_istable(L, -1)) { /* no hook table? */
+ lua_pop(L, 1); /* remove previous value */
+ lua_newtable(L); /* create new C_HOOK table */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, "C_HOOK"); /* register it */
+ }
+ lua_pushlightuserdata(L, L);
+ lua_pushstring(L, scpt);
+ lua_settable(L, -3); /* C_HOOK[L] = script */
+ lua_sethook(L, Chook, mask, count);
}
-static int setyhook (lua_State *L) {
+
+static int sethook (lua_State *L) {
if (lua_isnoneornil(L, 1))
lua_sethook(L, NULL, 0, 0); /* turn off hooks */
else {
- const char *smask = luaL_checkstring(L, 1);
- int count = luaL_optint(L, 2, 0);
+ const char *scpt = luaL_checkstring(L, 1);
+ const char *smask = luaL_checkstring(L, 2);
+ int count = luaL_optint(L, 3, 0);
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;
- lua_sethook(L, yieldf, mask, count);
+ sethookaux(L, mask, count, scpt);
}
return 0;
}
@@ -1232,7 +1292,7 @@ static const struct luaL_Reg tests_funcs[] = {
{"ref", tref},
{"resume", coresume},
{"s2d", s2d},
- {"setyhook", setyhook},
+ {"sethook", sethook},
{"stacklevel", stacklevel},
{"testC", testC},
{"makeCfunc", makeCfunc},