Browse Source

new way to handle errors (temporary version)

Roberto Ierusalimschy 23 years ago
parent
commit
ee4859b3e3
5 changed files with 133 additions and 94 deletions
  1. 80 12
      lapi.c
  2. 2 2
      ldblib.c
  3. 36 71
      ldo.c
  4. 10 4
      ldo.h
  5. 5 5
      lua.c

+ 80 - 12
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.183 2002/04/05 18:54:31 roberto Exp roberto $
+** $Id: lapi.c,v 1.184 2002/04/16 17:08:28 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -19,6 +19,7 @@
 #include "lstring.h"
 #include "ltable.h"
 #include "ltm.h"
+#include "lundump.h"
 #include "lvm.h"
 
 
@@ -528,30 +529,97 @@ LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) {
 }
 
 
-LUA_API int lua_dofile (lua_State *L, const char *filename) {
+LUA_API int lua_call (lua_State *L, int nargs, int nresults) {
   int status;
-  status = lua_loadfile(L, filename);
-  if (status == 0)  /* parse OK? */
-    status = lua_call(L, 0, LUA_MULTRET);  /* call main */
+  int errpos = lua_gettop(L) - nargs;
+  lua_getglobal(L, "_ERRORMESSAGE");
+  lua_insert(L, errpos);  /* put below function and args */
+  status = lua_pcall(L, nargs, nresults, errpos);
+  lua_remove(L, errpos);
   return status;
 }
 
 
-LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
-                          const char *name) {
+LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errf) {
   int status;
-  status = lua_loadbuffer(L, buff, size, name);
-  if (status == 0)  /* parse OK? */
-    status = lua_call(L, 0, LUA_MULTRET);  /* call main */
+  const TObject *err;
+  lua_lock(L);
+  err = (errf == 0) ? &luaO_nilobject : luaA_index(L, errf);
+  status = luaD_pcall(L, nargs, nresults, err);
+  lua_unlock(L);
+  return status;
+}
+
+
+static int aux_do (lua_State *L, int status) {
+  if (status == 0) {  /* parse OK? */
+    int err = lua_gettop(L);
+    lua_getglobal(L, "_ERRORMESSAGE");
+    lua_insert(L, err);
+    status = lua_pcall(L, 0, LUA_MULTRET, err);  /* call main */
+    lua_remove(L, err);  /* remove error function */
+  }
   return status;
 }
 
 
+LUA_API int lua_dofile (lua_State *L, const char *filename) {
+  return aux_do(L, lua_loadfile(L, filename));
+}
+
+
+LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
+                          const char *name) {
+  return aux_do(L, lua_loadbuffer(L, buff, size, name));
+}
+
+
 LUA_API int lua_dostring (lua_State *L, const char *str) {
   return lua_dobuffer(L, str, strlen(str), str);
 }
 
 
+LUA_API int lua_loadfile (lua_State *L, const char *filename) {
+  ZIO z;
+  int status;
+  int bin;  /* flag for file mode */
+  int nlevel;  /* level on the stack of filename */
+  FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
+  if (f == NULL) return LUA_ERRFILE;  /* unable to open file */
+  bin = (ungetc(getc(f), f) == LUA_SIGNATURE[0]);
+  if (bin && f != stdin) {
+    fclose(f);
+    f = fopen(filename, "rb");  /* reopen in binary mode */
+    if (f == NULL) return LUA_ERRFILE;  /* unable to reopen file */
+  }
+  if (filename == NULL)
+    lua_pushstring(L, "=stdin");
+  else {
+    lua_pushliteral(L, "@");
+    lua_pushstring(L, filename);
+    lua_concat(L, 2);
+  }
+  nlevel = lua_gettop(L);
+  filename = lua_tostring(L, -1);  /* filename = `@'..filename */
+  luaZ_Fopen(&z, f, filename);
+  status = luaD_protectedparser(L, &z, bin);
+  if (ferror(f)) status = LUA_ERRFILE;
+  lua_remove(L, nlevel);  /* remove filename */
+  if (f != stdin)
+    fclose(f);
+  return status;
+}
+
+
+LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size,
+                          const char *name) {
+  ZIO z;
+  if (!name) name = "?";
+  luaZ_mopen(&z, buff, size, name);
+  return luaD_protectedparser(L, &z, buff[0]==LUA_SIGNATURE[0]);
+}
+
+
 
 /*
 ** Garbage-collection functions
@@ -595,7 +663,7 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
 
 LUA_API void lua_error (lua_State *L, const char *s) {
   lua_lock(L);
-  luaD_error(L, s);
+  luaD_runerror(L, s);
   lua_unlock(L);
 }
 
@@ -662,7 +730,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
     L->top -= (n-1);
     luaC_checkGC(L);
   }
-  else if (n == 0) {  /* push null string */
+  else if (n == 0) {  /* push empty string */
     setsvalue(L->top, luaS_newlstr(L, NULL, 0));
     api_incr_top(L);
   }

+ 2 - 2
ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.46 2002/04/02 20:41:59 roberto Exp roberto $
+** $Id: ldblib.c,v 1.47 2002/04/09 19:48:08 roberto Exp roberto $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -265,7 +265,7 @@ static const luaL_reg dblib[] = {
 
 LUALIB_API int lua_dblibopen (lua_State *L) {
   luaL_opennamedlib(L, "dbg", dblib, 0);
-  lua_register(L, LUA_ERRORMESSAGE, errorfb);
+  lua_register(L, "_ERRORMESSAGE", errorfb);
   return 0;
 }
 

+ 36 - 71
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.170 2002/04/15 19:34:42 roberto Exp roberto $
+** $Id: ldo.c,v 1.171 2002/04/16 17:08:28 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -38,9 +38,11 @@ struct lua_longjmp {
   jmp_buf b;
   int allowhooks;  /* `allowhook' state when protection was set */
   volatile int status;  /* error code */
+  TObject err;  /* function to be called in case of errors */
 };
 
 
+
 static void correctstack (lua_State *L, TObject *oldstack) {
   struct lua_longjmp *lj;
   CallInfo *ci;
@@ -108,11 +110,11 @@ void luaD_growstack (lua_State *L, int n) {
 static void luaD_growCI (lua_State *L) {
   L->ci--;
   if (L->size_ci > LUA_MAXCALLS)  /* overflow while handling overflow? */
-    luaD_breakrun(L, LUA_ERRERR);  /* break run without error message */
+    luaD_error(L, NULL, LUA_ERRERR);  /* break run without error message */
   else {
     luaD_reallocCI(L, 2*L->size_ci);
     if (L->size_ci > LUA_MAXCALLS)
-      luaD_error(L, "stack overflow");
+      luaD_runerror(L, "stack overflow");
   }
   L->ci++;
 }
@@ -278,7 +280,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
     firstResult = luaV_execute(L);  /* call it */
     if (firstResult == NULL) {
       luaD_poscall(L, 0, L->top);
-      luaD_error(L, "attempt to `yield' across tag-method/C-call boundary");
+      luaD_runerror(L, "attempt to `yield' across tag-method/C-call boundary");
     }
   }
   luaD_poscall(L, nResults, firstResult);
@@ -325,14 +327,17 @@ static void resume (lua_State *L, void *numres) {
 LUA_API int lua_resume (lua_State *L, lua_State *co) {
   CallInfo *ci;
   int numres;
+  TObject o;
   int status;
   lua_lock(L);
   ci = co->ci;
   if (ci == co->base_ci)  /* no activation record? ?? */
-    luaD_error(L, "thread is dead - cannot be resumed");
+    luaD_runerror(L, "thread is dead - cannot be resumed");
   if (co->errorJmp != NULL)  /* ?? */
-    luaD_error(L, "thread is active - cannot be resumed");
-  status = luaD_runprotected(co, resume, &numres);
+    luaD_runerror(L, "thread is active - cannot be resumed");
+  setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE"));
+  luaV_gettable(L, gt(L), &o, &o);
+  status = luaD_runprotected(co, resume, &o, &numres);
   if (status == 0)  
     move_results(L, co->top - numres, co->top);
   lua_unlock(L);
@@ -345,7 +350,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
   lua_lock(L);
   ci = L->ci;
   if (ci_func(ci-1)->c.isC)
-    luaD_error(L, "cannot `yield' a C function");
+    luaD_runerror(L, "cannot `yield' a C function");
   ci->yield_results = nresults;
   lua_unlock(L);
   return -1;
@@ -360,24 +365,23 @@ struct CallS {  /* data to `f_call' */
   int nresults;
 };
 
+
 static void f_call (lua_State *L, void *ud) {
   struct CallS *c = cast(struct CallS *, ud);
   luaD_call(L, c->func, c->nresults);
 }
 
 
-LUA_API int lua_call (lua_State *L, int nargs, int nresults) {
+int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) {
   struct CallS c;
   int status;
-  lua_lock(L);
   c.func = L->top - (nargs+1);  /* function to be called */
   c.nresults = nresults;
-  status = luaD_runprotected(L, f_call, &c);
+  status = luaD_runprotected(L, &f_call, err, &c);
   if (status != 0) {  /* an error occurred? */
     L->top -= nargs+1;  /* remove parameters and func from the stack */
     luaF_close(L, L->top);  /* close eventual pending closures */
   }
-  lua_unlock(L);
   return status;
 }
 
@@ -400,8 +404,9 @@ static void f_parser (lua_State *L, void *ud) {
 }
 
 
-static int protectedparser (lua_State *L, ZIO *z, int bin) {
+int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
   struct SParser p;
+  TObject o;
   lu_mem old_blocks;
   int status;
   lua_lock(L);
@@ -410,7 +415,9 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) {
   if (G(L)->nblocks/8 >= G(L)->GCthreshold/10)
     luaC_collectgarbage(L);
   old_blocks = G(L)->nblocks;
-  status = luaD_runprotected(L, f_parser, &p);
+  setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE"));
+  luaV_gettable(L, gt(L), &o, &o);
+  status = luaD_runprotected(L, f_parser, &o, &p);
   if (status == 0) {
     /* add new memory to threshold (as it probably will stay) */
     lua_assert(G(L)->nblocks >= old_blocks);
@@ -423,47 +430,6 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) {
 }
 
 
-LUA_API int lua_loadfile (lua_State *L, const char *filename) {
-  ZIO z;
-  int status;
-  int bin;  /* flag for file mode */
-  int nlevel;  /* level on the stack of filename */
-  FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
-  if (f == NULL) return LUA_ERRFILE;  /* unable to open file */
-  bin = (ungetc(getc(f), f) == LUA_SIGNATURE[0]);
-  if (bin && f != stdin) {
-    fclose(f);
-    f = fopen(filename, "rb");  /* reopen in binary mode */
-    if (f == NULL) return LUA_ERRFILE;  /* unable to reopen file */
-  }
-  if (filename == NULL)
-    lua_pushstring(L, "=stdin");
-  else {
-    lua_pushliteral(L, "@");
-    lua_pushstring(L, filename);
-    lua_concat(L, 2);
-  }
-  nlevel = lua_gettop(L);
-  filename = lua_tostring(L, -1);  /* filename = `@'..filename */
-  luaZ_Fopen(&z, f, filename);
-  status = protectedparser(L, &z, bin);
-  if (ferror(f)) status = LUA_ERRFILE;
-  lua_remove(L, nlevel);  /* remove filename */
-  if (f != stdin)
-    fclose(f);
-  return status;
-}
-
-
-LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size,
-                          const char *name) {
-  ZIO z;
-  if (!name) name = "?";
-  luaZ_mopen(&z, buff, size, name);
-  return protectedparser(L, &z, buff[0]==LUA_SIGNATURE[0]);
-}
-
-
 
 /*
 ** {======================================================
@@ -472,16 +438,14 @@ LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size,
 */
 
 
-static void message (lua_State *L, const char *s) {
-  TObject o, m;
-  setsvalue(&o, luaS_newliteral(L, LUA_ERRORMESSAGE));
-  luaV_gettable(L, gt(L), &o, &m);
-  if (ttype(&m) == LUA_TFUNCTION) {
-    setobj(L->top, &m);
+static void message (lua_State *L, const char *msg) {
+  TObject *m = &L->errorJmp->err;
+  if (ttype(m) == LUA_TFUNCTION) {
+    setobj(L->top, m);
     incr_top(L);
-    setsvalue(L->top, luaS_new(L, s));
+    setsvalue(L->top, luaS_new(L, msg));
     incr_top(L);
-    luaD_call(L, L->top-2, 0);
+    luaD_call(L, L->top - 2, 0);
   }
 }
 
@@ -489,15 +453,10 @@ static void message (lua_State *L, const char *s) {
 /*
 ** Reports an error, and jumps up to the available recovery label
 */
-void luaD_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) {
+void luaD_error (lua_State *L, const char *s, int errcode) {
   if (L->errorJmp) {
     L->errorJmp->status = errcode;
+    if (s) message(L, s);
     longjmp(L->errorJmp->b, 1);
   }
   else {
@@ -507,12 +466,18 @@ void luaD_breakrun (lua_State *L, int errcode) {
 }
 
 
-int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) {
+void luaD_runerror (lua_State *L, const char *s) {
+  luaD_error(L, s, LUA_ERRRUN);
+}
+
+
+int luaD_runprotected (lua_State *L, Pfunc f, const TObject *err, void *ud) {
   struct lua_longjmp lj;
   lj.ci = L->ci;
   lj.top = L->top;
   lj.allowhooks = L->allowhooks;
   lj.status = 0;
+  lj.err = *err;
   lj.previous = L->errorJmp;  /* chain new error handler */
   L->errorJmp = &lj;
   if (setjmp(lj.b) == 0)

+ 10 - 4
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 1.41 2002/03/20 12:52:32 roberto Exp roberto $
+** $Id: ldo.h,v 1.42 2002/03/25 17:47:14 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -10,6 +10,7 @@
 
 #include "lobject.h"
 #include "lstate.h"
+#include "lzio.h"
 
 
 /*
@@ -27,17 +28,22 @@
 #define restorestack(L,n)	((TObject *)((char *)L->stack + (n)))
 
 
+/* type of protected functions, to be ran by `runprotected' */
+typedef void (*Pfunc) (lua_State *L, void *v);
+
+int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
 void luaD_lineHook (lua_State *L, int line);
 StkId luaD_precall (lua_State *L, StkId func);
 void luaD_call (lua_State *L, StkId func, int nResults);
+int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err);
 void luaD_poscall (lua_State *L, int wanted, StkId firstResult);
 void luaD_reallocCI (lua_State *L, int newsize);
 void luaD_reallocstack (lua_State *L, int newsize);
 void luaD_growstack (lua_State *L, int n);
 
-void luaD_error (lua_State *L, const char *s);
-void luaD_breakrun (lua_State *L, int errcode);
-int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud);
+void luaD_error (lua_State *L, const char *s, int errcode);
+void luaD_runerror (lua_State *L, const char *s);
+int luaD_runprotected (lua_State *L, Pfunc f, const TObject *err, void *ud);
 
 
 #endif

+ 5 - 5
lua.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.81 2002/04/05 18:54:31 roberto Exp roberto $
+** $Id: lua.c,v 1.82 2002/04/09 20:19:06 roberto Exp roberto $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
@@ -200,16 +200,16 @@ static int trap_eof (lua_State *l) {
 
 
 static int load_string (void) {
-  lua_getglobal(L, LUA_ERRORMESSAGE);
+  lua_getglobal(L, "_ERRORMESSAGE");
   lua_pushvalue(L, 1);
-  lua_setglobal(L, LUA_ERRORMESSAGE);
+  lua_setglobal(L, "_ERRORMESSAGE");
   incomplete = 0;
   for (;;) {  /* repeat until gets a complete line */
     int result;
     char *buffer = readline(get_prompt(incomplete));
     if (buffer == NULL) {  /* input end? */
       lua_settop(L, 2);
-      lua_setglobal(L, LUA_ERRORMESSAGE);
+      lua_setglobal(L, "_ERRORMESSAGE");
       return 0;
     }
     if (!incomplete && buffer[0] == '=') {
@@ -225,7 +225,7 @@ static int load_string (void) {
     lua_remove(L, 3);
     if (result == 0) {
       lua_insert(L, 2);  /* swap compiled chunk with old _ERRORMESSAGE */
-      lua_setglobal(L, LUA_ERRORMESSAGE);  /* restore old _ERRORMESSAGE */
+      lua_setglobal(L, "_ERRORMESSAGE");  /* restore old _ERRORMESSAGE */
       return 1;
     }
     else