lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hello all,

First, I'd like to tell you that I compiled lua-5.0.2 for "homebrew" on PlayStation2 and gave out a binary distribution of it on the ps2dev.net website. I also added a link at the lua-wiki in the binary distributions page (http://lua-users.org/wiki/LuaBinaries). This is not a 100% vanilla lua, since I've added another mathlib which is only using some float functions (that is, cosf, sinf, etc...) instead of doubles. That way, the host program is able to either let the normal luamath go (and then, produce slowness when calling math function) or have a #ifdef around it so that when run from ps2, it would call the mathlibf. I also compiled that distribution with a USE_FLOAT in the config, since the PS2 can't really handle doubles (its cop1 only handles floats). I have to say this package is completely untested :) But I honestly think it should run: the ps2sdk we are hosting is now quite mature and shouldn't produce problems in the lua's core. Some poeple should give that package a shoot really soon (tm), but I think people over here have better ideas about how to conduct tests for lua.

Second, I created some patches I'd like to submit here. There are two of them, quite independant. I've attached them within that mail.

The first one is to add a "CallWrap", when lua is calling a C closure. That way, if the host program want to, a callback is called to wrap the closure. For example, one usage is, when using C++, encapsulating that call into a try{...} catch{ lua_error(...) } block. That's what I am doing with this patch, but I can sense other operations with it, such as creating a sandbox. I know that one solution to get around that would be to register the wrapper as the actual C closure, but since I am handling kindof "plugins", I can't control the way they are registering their closures into the Lua state. So this is for me a nice solution.

The second patch is to implement a "user_break". I am actually having a console where the user can interactively enter lua code. Problem is, if the user enters an infinite loop, there are quite no good method to "break" the actual lua longrun, and return from there. At least, I've tried several methods, and none worked correctly for me. So, now, I am having this patch, and a line hook. The line hook checks a certain semaphore into my interface that tells if the user has done a user break (like hitting a button in the interface or whatever) then it calls lua_break(). Afterward, when the line hook returns, after the core checks if the hook yield, it also check if the hook did a break. Maybe there should be other positions where this break check should be done (maybe, around each hook, or more generally, after each callback) but I am not sure... Anyway: if this check matches, the code throws an error, thus returning nicely to an idle state, allowing my user to continue working with something else. I remember that one of my test was to do the lua_error directly inside the line hook. I think that was not successful, but I can't remember the exact reason.

 Cheers,

 -- Nicolas Noble.

diff -ur lua-5.0.2/include/lua.h lua-5.0.2-userbreak/include/lua.h
--- lua-5.0.2/include/lua.h	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-userbreak/include/lua.h	Sun Jan  2 06:10:13 2005
@@ -219,6 +219,8 @@
 
 LUA_API void  lua_concat (lua_State *L, int n);
 
+LUA_API void  lua_break (lua_State *L);
+
 
 
 /* 
diff -ur lua-5.0.2/src/ldo.c lua-5.0.2-userbreak/src/ldo.c
--- lua-5.0.2/src/ldo.c	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-userbreak/src/ldo.c	Sun Jan  2 06:10:13 2005
@@ -404,6 +404,13 @@
   return -1;
 }
 
+LUA_API void lua_break (lua_State *L) {
+  CallInfo * ci;
+  lua_lock(L);
+  ci = L->ci;
+  ci->state |= CI_BREAK;
+  lua_unlock(L);
+}
 
 int luaD_pcall (lua_State *L, Pfunc func, void *u,
                 ptrdiff_t old_top, ptrdiff_t ef) {
diff -ur lua-5.0.2/src/lstate.h lua-5.0.2-userbreak/src/lstate.h
--- lua-5.0.2/src/lstate.h	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-userbreak/src/lstate.h	Sun Jan  2 06:10:13 2005
@@ -100,6 +100,7 @@
 #define CI_CALLING	(1<<2)
 #define CI_SAVEDPC	(1<<3)  /* 1 if `savedpc' is updated */
 #define CI_YIELD	(1<<4)  /* 1 if thread is suspended */
+#define CI_BREAK	(1<<5)  /* 1 if user break */
 
 
 #define ci_func(ci)	(clvalue((ci)->base - 1))
diff -ur lua-5.0.2/src/lvm.c lua-5.0.2-userbreak/src/lvm.c
--- lua-5.0.2/src/lvm.c	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-userbreak/src/lvm.c	Sun Jan  2 06:10:13 2005
@@ -423,6 +423,10 @@
         L->ci->state = CI_YIELD | CI_SAVEDPC;
         return NULL;
       }
+      if (L->ci->state & CI_BREAK) {  /* did hook break? */
+        luaG_runerror(L, "breaking");
+        L->ci->state &= ~CI_BREAK;
+      }
     }
     /* warning!! several calls may realloc the stack and invalidate `ra' */
     base = L->base;
diff -ur lua-5.0.2/include/lua.h lua-5.0.2-callwrap/include/lua.h
--- lua-5.0.2/include/lua.h	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-callwrap/include/lua.h	Sun Jan  2 06:10:01 2005
@@ -330,6 +330,7 @@
 typedef struct lua_Debug lua_Debug;  /* activation record */
 
 typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
+typedef int (*lua_CallWrap) (lua_State *L, lua_CFunction func);
 
 
 LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
@@ -343,6 +344,8 @@
 LUA_API lua_Hook lua_gethook (lua_State *L);
 LUA_API int lua_gethookmask (lua_State *L);
 LUA_API int lua_gethookcount (lua_State *L);
+
+LUA_API lua_CallWrap lua_setcallwrap (lua_State *L, lua_CallWrap func);
 
 
 #define LUA_IDSIZE	60
diff -ur lua-5.0.2/src/ldebug.c lua-5.0.2-callwrap/src/ldebug.c
--- lua-5.0.2/src/ldebug.c	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-callwrap/src/ldebug.c	Sun Jan  2 06:10:01 2005
@@ -91,6 +91,16 @@
 }
 
 
+LUA_API lua_CallWrap lua_setcallwrap (lua_State *L, lua_CallWrap func) {
+  lua_CallWrap old_func;
+  lua_lock(L);
+  old_func = L->callwrap;
+  L->callwrap = func;
+  lua_unlock(L);
+  return old_func;
+}
+
+
 LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
   int status;
   CallInfo *ci;
diff -ur lua-5.0.2/src/ldo.c lua-5.0.2-callwrap/src/ldo.c
--- lua-5.0.2/src/ldo.c	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-callwrap/src/ldo.c	Sun Jan  2 06:10:01 2005
@@ -257,7 +257,11 @@
 #ifdef LUA_COMPATUPVALUES
     lua_pushupvalues(L);
 #endif
-    n = (*clvalue(L->base - 1)->c.f)(L);  /* do the actual call */
+    if (L->callwrap) {
+        n = L->callwrap(L, clvalue(L->base - 1)->c.f);  /* wrap the call */
+    } else {
+        n = (*clvalue(L->base - 1)->c.f)(L);  /* do the actual call */
+    }
     lua_lock(L);
     return L->top - n;
   }
diff -ur lua-5.0.2/src/lstate.c lua-5.0.2-callwrap/src/lstate.c
--- lua-5.0.2/src/lstate.c	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-callwrap/src/lstate.c	Sun Jan  2 06:10:01 2005
@@ -137,6 +137,7 @@
   L->nCcalls = 0;
   L->base_ci = L->ci = NULL;
   L->errfunc = 0;
+  L->callwrap = 0;
   setnilvalue(gt(L));
 }
 
diff -ur lua-5.0.2/src/lstate.h lua-5.0.2-callwrap/src/lstate.h
--- lua-5.0.2/src/lstate.h	Sun Jan  2 06:07:21 2005
+++ lua-5.0.2-callwrap/src/lstate.h	Sun Jan  2 06:10:01 2005
@@ -152,6 +152,7 @@
   GCObject *gclist;
   struct lua_longjmp *errorJmp;  /* current error recover point */
   ptrdiff_t errfunc;  /* current error handling function (stack index) */
+  lua_CallWrap callwrap;
 };