Browse Source

new version of protected execution

Roberto Ierusalimschy 25 years ago
parent
commit
13635f7de7
5 changed files with 149 additions and 100 deletions
  1. 104 64
      ldo.c
  2. 4 2
      ldo.h
  3. 29 20
      lstate.c
  4. 2 12
      lstate.h
  5. 10 2
      ltests.c

+ 104 - 64
ldo.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldo.c,v 1.95 2000/09/11 20:29:27 roberto Exp roberto $
+** $Id: ldo.c,v 1.96 2000/09/12 13:47:39 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -199,88 +199,60 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
 }
 }
 
 
 
 
-static void message (lua_State *L, const char *s) {
-  const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE);
-  if (*luaO_typename(em) == 'f') {
-    *L->top = *em;
-    incr_top;
-    lua_pushstring(L, s);
-    luaD_call(L, L->top-2, 0);
-  }
-}
-
-
-void luaD_breakrun (lua_State *L, int errcode) {
-  if (L->errorJmp) {
-    L->errorJmp->status = errcode;
-    longjmp(L->errorJmp->b, 1);
-  }
-  else {
-    if (errcode != LUA_ERRMEM)
-      message(L, "unable to recover; exiting\n");
-    exit(EXIT_FAILURE);
-  }
-}
-
 /*
 /*
-** Reports an error, and jumps up to the available recovery label
+** Execute a protected call.
 */
 */
-void lua_error (lua_State *L, const char *s) {
-  if (s) message(L, s);
-  luaD_breakrun(L, LUA_ERRRUN);
-}
-
-
-static void chain_longjmp (lua_State *L, struct lua_longjmp *lj) {
-  lj->status = 0;
-  lj->base = L->Cbase;
-  lj->previous = L->errorJmp;
-  L->errorJmp = lj;
+struct CallS {  /* data to `f_call' */
+  StkId func;
+  int nresults;
+};
+
+static void f_call (lua_State *L, void *ud) {
+  struct CallS *c = (struct CallS *)ud;
+  luaD_call(L, c->func, c->nresults);
 }
 }
 
 
 
 
-static int restore_longjmp (lua_State *L, struct lua_longjmp *lj) {
-  L->Cbase = lj->base;
-  L->errorJmp = lj->previous;
-  return lj->status;
+int lua_call (lua_State *L, int nargs, int nresults) {
+  StkId func = L->top - (nargs+1);  /* function to be called */
+  struct CallS c;
+  int status;
+  c.func = func; c.nresults = nresults;
+  status = luaD_runprotected(L, f_call, &c);
+  if (status != 0)  /* an error occurred? */
+    L->top = func;  /* remove parameters from the stack */
+  return status;
 }
 }
 
 
 
 
 /*
 /*
-** Execute a protected call.
+** Execute a protected parser.
 */
 */
-int lua_call (lua_State *L, int nargs, int nresults) {
-  StkId func = L->top - (nargs+1);  /* function to be called */
-  struct lua_longjmp myErrorJmp;
-  chain_longjmp(L, &myErrorJmp);
-  if (setjmp(myErrorJmp.b) == 0) {
-    luaD_call(L, func, nresults);
-  }
-  else {  /* an error occurred: restore the state */
-    L->top = func;  /* remove garbage from the stack */
-    restore_stack_limit(L);
-  }
-  return restore_longjmp(L, &myErrorJmp);
+struct ParserS {  /* data to `f_parser' */
+  ZIO *z;
+  int bin;
+};
+
+static void f_parser (lua_State *L, void *ud) {
+  struct ParserS *p = (struct ParserS *)ud;
+  Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
+  luaV_Lclosure(L, tf, 0);
 }
 }
 
 
 
 
 static int protectedparser (lua_State *L, ZIO *z, int bin) {
 static int protectedparser (lua_State *L, ZIO *z, int bin) {
-  struct lua_longjmp myErrorJmp;
+  struct ParserS p;
   unsigned long old_blocks;
   unsigned long old_blocks;
+  int status;
+  p.z = z; p.bin = bin;
   luaC_checkGC(L);
   luaC_checkGC(L);
   old_blocks = L->nblocks;
   old_blocks = L->nblocks;
-  chain_longjmp(L, &myErrorJmp);
-  if (setjmp(myErrorJmp.b) == 0) {
-    Proto *tf = bin ? luaU_undump(L, z) : luaY_parser(L, z);
-    luaV_Lclosure(L, tf, 0);
-  }
-  else {  /* an error occurred: correct error code */
-    if (myErrorJmp.status == LUA_ERRRUN)
-      myErrorJmp.status = LUA_ERRSYNTAX;
-  }
+  status = luaD_runprotected(L, f_parser, &p);
+  if (status == LUA_ERRRUN)  /* an error occurred: correct error code */
+    status = LUA_ERRSYNTAX;
   /* add new memory to threshould (as it probably will stay) */
   /* add new memory to threshould (as it probably will stay) */
   L->GCthreshold += (L->nblocks - old_blocks);
   L->GCthreshold += (L->nblocks - old_blocks);
-  return restore_longjmp(L, &myErrorJmp);  /* error code */
+  return status;
 }
 }
 
 
 
 
@@ -339,3 +311,71 @@ int lua_dostring (lua_State *L, const char *str) {
   return lua_dobuffer(L, str, strlen(str), str);
   return lua_dobuffer(L, str, strlen(str), str);
 }
 }
 
 
+
+/*
+** {======================================================
+** Error-recover functions (based on long jumps)
+** =======================================================
+*/
+
+/* chain list of long jump buffers */
+struct lua_longjmp {
+  jmp_buf b;
+  struct lua_longjmp *previous;
+  volatile int status;  /* error code */
+};
+
+
+static void message (lua_State *L, const char *s) {
+  const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE);
+  if (*luaO_typename(em) == 'f') {
+    *L->top = *em;
+    incr_top;
+    lua_pushstring(L, s);
+    luaD_call(L, L->top-2, 0);
+  }
+}
+
+
+/*
+** Reports an error, and jumps up to the available recovery label
+*/
+void lua_error (lua_State *L, const char *s) {
+  if (s) message(L, s);
+  luaD_breakrun(L, LUA_ERRRUN);
+}
+
+
+void luaD_breakrun (lua_State *L, int errcode) {
+  if (L->errorJmp) {
+    L->errorJmp->status = errcode;
+    longjmp(L->errorJmp->b, 1);
+  }
+  else {
+    if (errcode != LUA_ERRMEM)
+      message(L, "unable to recover; exiting\n");
+    exit(EXIT_FAILURE);
+  }
+}
+
+
+int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) {
+  StkId oldCbase = L->Cbase;
+  StkId oldtop = L->top;
+  struct lua_longjmp lj;
+  lj.status = 0;
+  lj.previous = L->errorJmp;  /* chain new error handler */
+  L->errorJmp = &lj;
+  if (setjmp(lj.b) == 0)
+    (*f)(L, ud);
+  else {  /* an error occurred: restore the state */
+    L->Cbase = oldCbase;
+    L->top = oldtop;
+    restore_stack_limit(L);
+  }
+  L->errorJmp = lj.previous;  /* restore old error handler */
+  return lj.status;
+}
+
+/* }====================================================== */
+

+ 4 - 2
ldo.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldo.h,v 1.23 2000/08/28 17:57:04 roberto Exp roberto $
+** $Id: ldo.h,v 1.24 2000/08/29 14:48:16 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -24,8 +24,10 @@ void luaD_adjusttop (lua_State *L, StkId base, int extra);
 void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook);
 void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook);
 void luaD_call (lua_State *L, StkId func, int nResults);
 void luaD_call (lua_State *L, StkId func, int nResults);
 void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults);
 void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults);
-void luaD_breakrun (lua_State *L, int errcode);
 void luaD_checkstack (lua_State *L, int n);
 void luaD_checkstack (lua_State *L, int n);
 
 
+void luaD_breakrun (lua_State *L, int errcode);
+int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud);
+
 
 
 #endif
 #endif

+ 29 - 20
lstate.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.c,v 1.39 2000/09/12 18:42:32 roberto Exp roberto $
+** $Id: lstate.c,v 1.40 2000/09/21 14:41:25 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -20,7 +20,7 @@
 
 
 
 
 #ifdef DEBUG
 #ifdef DEBUG
-extern lua_State *lua_state;
+static lua_State *lua_state = NULL;
 void luaB_opentests (lua_State *L);
 void luaB_opentests (lua_State *L);
 #endif
 #endif
 
 
@@ -38,8 +38,29 @@ static int errormessage (lua_State *L) {
 }
 }
 
 
 
 
+/*
+** open parts that may cause memory-allocation errors
+*/
+static void f_luaopen (lua_State *L, void *ud) {
+  int stacksize = *(int *)ud;
+  if (stacksize == 0)
+    stacksize = DEFAULT_STACK_SIZE;
+  else
+    stacksize += LUA_MINSTACK;
+  L->gt = luaH_new(L, 10);
+  luaD_init(L, stacksize);
+  luaS_init(L);
+  luaX_init(L);
+  luaT_init(L);
+  lua_register(L, LUA_ERRORMESSAGE, errormessage);
+#ifdef DEBUG
+  luaB_opentests(L);
+  if (lua_state == NULL) lua_state = L;  /* keep first state to be opened */
+#endif
+}
+
+
 lua_State *lua_open (int stacksize) {
 lua_State *lua_open (int stacksize) {
-  struct lua_longjmp myErrorJmp;
   lua_State *L = luaM_new(NULL, lua_State);
   lua_State *L = luaM_new(NULL, lua_State);
   if (L == NULL) return NULL;  /* memory allocation error */
   if (L == NULL) return NULL;  /* memory allocation error */
   L->stack = NULL;
   L->stack = NULL;
@@ -62,26 +83,14 @@ lua_State *lua_open (int stacksize) {
   L->callhook = NULL;
   L->callhook = NULL;
   L->linehook = NULL;
   L->linehook = NULL;
   L->allowhooks = 1;
   L->allowhooks = 1;
-  L->errorJmp = &myErrorJmp;
-  if (setjmp(myErrorJmp.b) == 0) {  /* to catch memory allocation errors */
-    L->gt = luaH_new(L, 10);
-    luaD_init(L, (stacksize == 0) ? DEFAULT_STACK_SIZE :
-                                    stacksize+LUA_MINSTACK);
-    luaS_init(L);
-    luaX_init(L);
-    luaT_init(L);
-    lua_register(L, LUA_ERRORMESSAGE, errormessage);
-#ifdef DEBUG
-    luaB_opentests(L);
-#endif
-    L->GCthreshold = L->nblocks*4;
-    L->errorJmp = NULL;
-    return L;
-  }
-  else {  /* memory allocation error: free partial state */
+  L->errorJmp = NULL;
+  if (luaD_runprotected(L, f_luaopen, &stacksize) != 0) {
+    /* memory allocation error: free partial state */
     lua_close(L);
     lua_close(L);
     return NULL;
     return NULL;
   }
   }
+  L->GCthreshold = L->nblocks*4;
+  return L;
 }
 }
 
 
 
 

+ 2 - 12
lstate.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.h,v 1.37 2000/08/28 17:57:04 roberto Exp roberto $
+** $Id: lstate.h,v 1.38 2000/09/11 17:38:42 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -7,8 +7,6 @@
 #ifndef lstate_h
 #ifndef lstate_h
 #define lstate_h
 #define lstate_h
 
 
-#include <setjmp.h>
-
 #include "lobject.h"
 #include "lobject.h"
 #include "lua.h"
 #include "lua.h"
 #include "luadebug.h"
 #include "luadebug.h"
@@ -33,15 +31,7 @@ struct Ref {
 };
 };
 
 
 
 
-/*
-** chain list of long jumps
-*/
-struct lua_longjmp {
-  jmp_buf b;
-  struct lua_longjmp *previous;
-  volatile int status;  /* error code */
-  StkId base;
-};
+struct lua_longjmp;  /* defined in ldo.c */
 
 
 
 
 typedef struct stringtable {
 typedef struct stringtable {

+ 10 - 2
ltests.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltests.c,v 1.42 2000/09/14 14:09:31 roberto Exp roberto $
+** $Id: ltests.c,v 1.43 2000/09/25 14:48:42 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -422,11 +422,19 @@ static int testC (lua_State *L) {
     else if EQ("concat") {
     else if EQ("concat") {
       lua_concat(L, getnum);
       lua_concat(L, getnum);
     }
     }
-    else if EQ("call") {
+    else if EQ("rawcall") {
       int narg = getnum;
       int narg = getnum;
       int nres = getnum;
       int nres = getnum;
       lua_rawcall(L, narg, nres);
       lua_rawcall(L, narg, nres);
     }
     }
+    else if EQ("call") {
+      int narg = getnum;
+      int nres = getnum;
+      lua_call(L, narg, nres);
+    }
+    else if EQ("dostring") {
+      lua_dostring(L, luaL_check_string(L, getnum));
+    }
     else if EQ("type") {
     else if EQ("type") {
       lua_pushstring(L, lua_type(L, getnum));
       lua_pushstring(L, lua_type(L, getnum));
     }
     }