Browse Source

reordering of some functions + cleaner way to code lua_resume/resume +
small bug in lua_resume (in case of calling errors lua_resume should
remove only new arguments from the stack and push error message).

Roberto Ierusalimschy 15 years ago
parent
commit
2bb19ccf08
1 changed files with 55 additions and 55 deletions
  1. 55 55
      ldo.c

+ 55 - 55
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.74 2009/11/27 15:37:59 roberto Exp roberto $
+** $Id: ldo.c,v 2.75 2009/12/08 18:59:24 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -59,9 +59,7 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
       setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
       break;
     }
-    case LUA_ERRSYNTAX:
-    case LUA_ERRGCMM:
-    case LUA_ERRRUN: {
+    default: {
       setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */
       break;
     }
@@ -405,33 +403,67 @@ static void unroll (lua_State *L, void *ud) {
 
 
 /*
-** data to be passed to 'resume' by 'lua_resume'
+** check whether thread has a suspended protected call
 */
-struct ResumeData {
-  StkId firstArg;  /* stack index of first argument */
-  int recover;  /* should try to recover in case of errors */
-};
+static CallInfo *findpcall (lua_State *L) {
+  CallInfo *ci;
+  for (ci = L->ci; ci != NULL; ci = ci->previous) {  /* search for a pcall */
+    if (ci->callstatus & CIST_YPCALL)
+      return ci;
+  }
+  return NULL;  /* no pending pcall */
+}
+
+
+static int recover (lua_State *L, int status) {
+  StkId oldtop;
+  CallInfo *ci = findpcall(L);
+  if (ci == NULL) return 0;  /* no recovery point */
+  /* "finish" luaD_pcall */
+  oldtop = restorestack(L, ci->u.c.oldtop);
+  luaF_close(L, oldtop);
+  luaD_seterrorobj(L, status, oldtop);
+  L->ci = ci;
+  L->allowhook = ci->u.c.old_allowhook;
+  L->nny = 0;  /* should be zero to be yieldable */
+  luaD_shrinkstack(L);
+  L->errfunc = ci->u.c.old_errfunc;
+  ci->callstatus |= CIST_STAT;  /* call has error status */
+  ci->u.c.status = status;  /* (here it is) */
+  return 1;  /* continue running the coroutine */
+}
+
+
+/*
+** signal an error in the call to 'resume', not in the execution of the
+** coroutine itself. (Such errors should not be handled by any coroutine
+** error hanlder and should not kill the coroutine.)
+*/
+static void resume_error (lua_State *L, const char *msg, StkId firstArg) {
+  L->top = firstArg;  /* remove args from the stack */
+  setsvalue2s(L, L->top, luaS_new(L, msg));  /* push error message */
+  incr_top(L);
+  luaD_throw(L, -1);  /* jump back to 'lua_resume' */
+}
 
 
 /*
 ** do the work for 'lua_resume' in protected mode
 */
 static void resume (lua_State *L, void *ud) {
-  struct ResumeData *rd = cast(struct ResumeData *, ud);
+  StkId firstArg = cast(StkId, ud);
   CallInfo *ci = L->ci;
   if (G(L)->nCcalls >= LUAI_MAXCCALLS)
-    luaG_runerror(L, "C stack overflow");
+    resume_error(L, "C stack overflow", firstArg);
   if (L->status == LUA_OK) {  /* may be starting a coroutine */
-    if (ci != &L->base_ci) {  /* not in base level? */
-      rd->recover = 0;  /* thread may not be running as a coroutine */
-      luaG_runerror(L, "cannot resume non-suspended coroutine");
-    }
+    if (ci != &L->base_ci)  /* not in base level? */
+      resume_error(L, "cannot resume non-suspended coroutine", firstArg);
     /* coroutine is in base level; start running it */
-    if (!luaD_precall(L, rd->firstArg - 1, LUA_MULTRET))  /* Lua function? */
+    if (!luaD_precall(L, firstArg - 1, LUA_MULTRET))  /* Lua function? */
       luaV_execute(L);  /* call it */
   }
   else if (L->status != LUA_YIELD)
-    luaG_runerror(L, "cannot resume dead coroutine");
+    resume_error(L, "cannot resume dead coroutine", firstArg);
   else {  /* resuming from previous yield */
     L->status = LUA_OK;
     if (isLua(ci))  /* yielded inside a hook? */
@@ -446,58 +478,26 @@ static void resume (lua_State *L, void *ud) {
         n = (*ci->u.c.k)(L);  /* call continuation */
         lua_lock(L);
         api_checknelems(L, n);
-        rd->firstArg = L->top - n;  /* yield results come from continuation */
+        firstArg = L->top - n;  /* yield results come from continuation */
       }
       G(L)->nCcalls--;  /* finish 'luaD_call' */
-      luaD_poscall(L, rd->firstArg);  /* finish 'luaD_precall' */
+      luaD_poscall(L, firstArg);  /* finish 'luaD_precall' */
     }
     unroll(L, NULL);
   }
 }
 
 
-/*
-** check whether thread has a suspended protected call
-*/
-static CallInfo *findpcall (lua_State *L) {
-  CallInfo *ci;
-  for (ci = L->ci; ci != NULL; ci = ci->previous) {  /* search for a pcall */
-    if (ci->callstatus & CIST_YPCALL)
-      return ci;
-  }
-  return NULL;  /* no pending pcall */
-}
-
-
-static int recover (lua_State *L, int status) {
-  StkId oldtop;
-  CallInfo *ci = findpcall(L);
-  if (ci == NULL) return 0;  /* no recovery point */
-  /* "finish" luaD_pcall */
-  oldtop = restorestack(L, ci->u.c.oldtop);
-  luaF_close(L, oldtop);
-  luaD_seterrorobj(L, status, oldtop);
-  L->ci = ci;
-  L->allowhook = ci->u.c.old_allowhook;
-  L->nny = 0;  /* should be zero to be yieldable */
-  luaD_shrinkstack(L);
-  L->errfunc = ci->u.c.old_errfunc;
-  ci->callstatus |= CIST_STAT;  /* call has error status */
-  ci->u.c.status = status;  /* (here it is) */
-  return 1;  /* continue running the coroutine */
-}
-
-
 LUA_API int lua_resume (lua_State *L, int nargs) {
-  struct ResumeData rd;
   int status;
   lua_lock(L);
   luai_userstateresume(L, nargs);
   ++G(L)->nCcalls;  /* count resume */
   L->nny = 0;  /* allow yields */
-  rd.firstArg = L->top - nargs; rd.recover = 1;
-  status = luaD_rawrunprotected(L, resume, &rd);
-  if (rd.recover) {
+  status = luaD_rawrunprotected(L, resume, L->top - nargs);
+  if (status == -1)  /* error calling 'lua_resume'? */
+    status = LUA_ERRRUN;
+  else {  /* yield or regular error */
     while (status != LUA_OK && status != LUA_YIELD) {  /* error? */
       if (recover(L, status))  /* recover point? */
         status = luaD_rawrunprotected(L, unroll, NULL);  /* run continuation */