commit 751cd867d3e0338279fa6f3390c8b7ddc0108659
parent b36b2a061c88be22e36900146cbcad39bab07f5d
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed, 1 May 2002 17:47:50 -0300
new way to handle errors
Diffstat:
M | lapi.c | | | 118 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
M | lauxlib.c | | | 16 | ++-------------- |
M | lauxlib.h | | | 4 | +--- |
M | lbaselib.c | | | 140 | +++++++++++++++++++++++++------------------------------------------------------ |
M | ldblib.c | | | 10 | ++-------- |
M | ldo.c | | | 90 | ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
M | ldo.h | | | 5 | +++-- |
M | lmem.c | | | 4 | ++-- |
M | lmem.h | | | 5 | ++++- |
M | lstate.c | | | 8 | ++++++-- |
M | ltests.c | | | 8 | ++++++-- |
M | lua.c | | | 147 | +++++++++++++++++++++++++++++++++++++------------------------------------------ |
M | lua.h | | | 20 | +++++++++++--------- |
13 files changed, 283 insertions(+), 292 deletions(-)
diff --git a/lapi.c b/lapi.c
@@ -1,10 +1,12 @@
/*
-** $Id: lapi.c,v 1.184 2002/04/16 17:08:28 roberto Exp roberto $
+** $Id: lapi.c,v 1.185 2002/04/22 14:40:50 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
+#include <errno.h>
+#include <stdio.h>
#include <string.h>
#include "lua.h"
@@ -516,7 +518,7 @@ LUA_API void lua_setmetatable (lua_State *L, int objindex) {
/*
-** `do' functions (run Lua code)
+** `load' and `call' functions (run Lua code)
*/
LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) {
@@ -529,17 +531,6 @@ LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) {
}
-LUA_API int lua_call (lua_State *L, int nargs, int nresults) {
- int status;
- 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_pcall (lua_State *L, int nargs, int nresults, int errf) {
int status;
const TObject *err;
@@ -551,31 +542,11 @@ LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errf) {
}
-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);
+static int errfile (lua_State *L, const char *filename) {
+ char buff[150];
+ sprintf(buff, "cannot read file `%.80s' (%.40s)", filename, strerror(errno));
+ lua_pushstring(L, buff);
+ return LUA_ERRFILE;
}
@@ -585,12 +556,12 @@ LUA_API int lua_loadfile (lua_State *L, const char *filename) {
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 */
+ if (f == NULL) return errfile(L, filename); /* 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 (f == NULL) return errfile(L, filename); /* unable to reopen file */
}
if (filename == NULL)
lua_pushstring(L, "=stdin");
@@ -603,7 +574,8 @@ LUA_API int lua_loadfile (lua_State *L, const char *filename) {
filename = lua_tostring(L, -1); /* filename = `@'..filename */
luaZ_Fopen(&z, f, filename);
status = luaD_protectedparser(L, &z, bin);
- if (ferror(f)) status = LUA_ERRFILE;
+ if (ferror(f))
+ return errfile(L, filename);
lua_remove(L, nlevel); /* remove filename */
if (f != stdin)
fclose(f);
@@ -661,9 +633,10 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
*/
-LUA_API void lua_error (lua_State *L, const char *s) {
+LUA_API void lua_errorobj (lua_State *L) {
lua_lock(L);
- luaD_runerror(L, s);
+ api_checknelems(L, 1);
+ luaD_errorobj(L, L->top - 1, LUA_ERRRUN);
lua_unlock(L);
}
@@ -767,3 +740,62 @@ LUA_API int lua_pushupvalues (lua_State *L) {
}
+
+/*
+** {======================================================
+** compatibility code
+** =======================================================
+*/
+
+
+static void callalert (lua_State *L, int status) {
+ if (status != 0) {
+ int top = lua_gettop(L);
+ lua_getglobal(L, "_ALERT");
+ lua_insert(L, -2);
+ lua_pcall(L, 1, 0, 0);
+ lua_settop(L, top-1);
+ }
+}
+
+
+LUA_API int lua_call (lua_State *L, int nargs, int nresults) {
+ int status;
+ 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);
+ callalert(L, status);
+ 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 */
+ }
+ callalert(L, status);
+ 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);
+}
+
+/* }====================================================== */
diff --git a/lauxlib.c b/lauxlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.c,v 1.65 2002/04/04 20:25:55 roberto Exp roberto $
+** $Id: lauxlib.c,v 1.66 2002/04/16 12:00:02 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -21,19 +21,6 @@
#include "lualib.h"
-LUALIB_API const char *luaL_errstr (int errcode) {
- static const char *const errstr[] = {
- "ok",
- "run-time error",
- "cannot read file",
- "syntax error",
- "not enough memory",
- "error in error handling"
- };
- return errstr[errcode];
-}
-
-
LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
int i;
for (i=0; list[i]; i++)
@@ -42,6 +29,7 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
return -1; /* name not found */
}
+
LUALIB_API void luaL_argerror (lua_State *L, int narg, const char *extramsg) {
lua_Debug ar;
lua_getstack(L, 0, &ar);
diff --git a/lauxlib.h b/lauxlib.h
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.h,v 1.43 2002/03/20 12:54:08 roberto Exp roberto $
+** $Id: lauxlib.h,v 1.44 2002/04/02 20:42:49 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -52,8 +52,6 @@ LUALIB_API int luaL_findstring (const char *name,
LUALIB_API int luaL_ref (lua_State *L, int t);
LUALIB_API void luaL_unref (lua_State *L, int t, int ref);
-/* error messages corresponding to error codes */
-LUALIB_API const char *luaL_errstr (int errcode);
/*
diff --git a/lbaselib.c b/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.68 2002/04/15 20:54:41 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.69 2002/04/22 14:40:23 roberto Exp roberto $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -26,6 +26,7 @@
*/
static int luaB__ALERT (lua_State *L) {
fputs(luaL_check_string(L, 1), stderr);
+ putc('\n', stderr);
return 0;
}
@@ -35,26 +36,22 @@ static int luaB__ALERT (lua_State *L) {
** The library `liolib' redefines _ERRORMESSAGE for better error information.
*/
static int luaB__ERRORMESSAGE (lua_State *L) {
+ lua_Debug ar;
luaL_check_type(L, 1, LUA_TSTRING);
- lua_getglobal(L, LUA_ALERT);
- if (lua_isfunction(L, -1)) { /* avoid error loop if _ALERT is not defined */
- lua_Debug ar;
- lua_pushliteral(L, "error: ");
- lua_pushvalue(L, 1);
- if (lua_getstack(L, 1, &ar)) {
- lua_getinfo(L, "Sl", &ar);
- if (ar.source && ar.currentline > 0) {
- char buff[100];
- sprintf(buff, "\n <%.70s: line %d>", ar.short_src, ar.currentline);
- lua_pushstring(L, buff);
- lua_concat(L, 2);
- }
+ lua_pushliteral(L, "error: ");
+ lua_pushvalue(L, 1);
+ if (lua_getstack(L, 1, &ar)) {
+ lua_getinfo(L, "Sl", &ar);
+ if (ar.source && ar.currentline > 0) {
+ char buff[100];
+ sprintf(buff, "\n <%.70s: line %d>", ar.short_src, ar.currentline);
+ lua_pushstring(L, buff);
+ lua_concat(L, 2);
}
- lua_pushliteral(L, "\n");
- lua_concat(L, 3);
- lua_rawcall(L, 1, 0);
}
- return 0;
+ lua_pushliteral(L, "\n");
+ lua_concat(L, 3);
+ return 1;
}
@@ -114,7 +111,8 @@ static int luaB_tonumber (lua_State *L) {
static int luaB_error (lua_State *L) {
- lua_error(L, luaL_opt_string(L, 1, NULL));
+ lua_settop(L, 1);
+ lua_errorobj(L);
return 0; /* to avoid warnings */
}
@@ -217,53 +215,27 @@ static int luaB_nexti (lua_State *L) {
}
-static int passresults (lua_State *L, int status, int oldtop) {
- if (status == 0) {
- int nresults = lua_gettop(L) - oldtop;
- if (nresults > 0)
- return nresults; /* results are already on the stack */
- else {
- lua_pushboolean(L, 1); /* at least one result to signal no errors */
- return 1;
- }
- }
- else { /* error */
+static int passresults (lua_State *L, int status) {
+ if (status == 0) return 1;
+ else {
lua_pushnil(L);
- lua_pushstring(L, luaL_errstr(status)); /* error code */
+ lua_insert(L, -2);
return 2;
}
}
-static int luaB_dostring (lua_State *L) {
- int oldtop = lua_gettop(L);
- size_t l;
- const char *s = luaL_check_lstr(L, 1, &l);
- const char *chunkname = luaL_opt_string(L, 2, s);
- return passresults(L, lua_dobuffer(L, s, l, chunkname), oldtop);
-}
-
-
static int luaB_loadstring (lua_State *L) {
- int oldtop = lua_gettop(L);
size_t l;
const char *s = luaL_check_lstr(L, 1, &l);
const char *chunkname = luaL_opt_string(L, 2, s);
- return passresults(L, lua_loadbuffer(L, s, l, chunkname), oldtop);
-}
-
-
-static int luaB_dofile (lua_State *L) {
- int oldtop = lua_gettop(L);
- const char *fname = luaL_opt_string(L, 1, NULL);
- return passresults(L, lua_dofile(L, fname), oldtop);
+ return passresults(L, lua_loadbuffer(L, s, l, chunkname));
}
static int luaB_loadfile (lua_State *L) {
- int oldtop = lua_gettop(L);
const char *fname = luaL_opt_string(L, 1, NULL);
- return passresults(L, lua_loadfile(L, fname), oldtop);
+ return passresults(L, lua_loadfile(L, fname));
}
@@ -276,53 +248,29 @@ static int luaB_assert (lua_State *L) {
}
-static int aux_unpack (lua_State *L, int arg) {
+static int luaB_unpack (lua_State *L) {
int n, i;
- luaL_check_type(L, arg, LUA_TTABLE);
- n = lua_getn(L, arg);
+ luaL_check_type(L, 1, LUA_TTABLE);
+ n = lua_getn(L, 1);
luaL_check_stack(L, n+LUA_MINSTACK, "table too big to unpack");
for (i=1; i<=n; i++) /* push arg[1...n] */
- lua_rawgeti(L, arg, i);
+ lua_rawgeti(L, 1, i);
return n;
}
-static int luaB_unpack (lua_State *L) {
- return aux_unpack(L, 1);
-}
-
-
-static int luaB_call (lua_State *L) {
- int oldtop;
- const char *options = luaL_opt_string(L, 3, "");
- int err = 0; /* index of old error method */
+static int luaB_pcall (lua_State *L) {
int status;
- int n;
- if (!lua_isnone(L, 4)) { /* set new error method */
- lua_getglobal(L, "_ERRORMESSAGE");
- err = lua_gettop(L); /* get index */
- lua_pushvalue(L, 4);
- lua_setglobal(L, "_ERRORMESSAGE");
- }
- oldtop = lua_gettop(L); /* top before function-call preparation */
- /* push function */
- lua_pushvalue(L, 1);
- n = aux_unpack(L, 2); /* push arg[1...n] */
- status = lua_call(L, n, LUA_MULTRET);
- if (err != 0) { /* restore old error method */
- lua_pushvalue(L, err);
- lua_setglobal(L, "_ERRORMESSAGE");
- }
- if (status != 0) { /* error in call? */
- if (strchr(options, 'x'))
- lua_pushnil(L); /* return nil to signal the error */
- else
- lua_error(L, NULL); /* propagate error without additional messages */
- return 1;
+ luaL_check_any(L, 1);
+ luaL_check_any(L, 2);
+ status = lua_pcall(L, lua_gettop(L) - 2, LUA_MULTRET, 1);
+ if (status != 0)
+ return passresults(L, status);
+ else {
+ lua_pushboolean(L, 1);
+ lua_replace(L, 1);
+ return lua_gettop(L); /* return `true' + all results */
}
- if (strchr(options, 'p')) /* pack results? */
- lua_error(L, "obsolete option `p' in `call'");
- return lua_gettop(L) - oldtop; /* results are already on the stack */
}
@@ -433,7 +381,9 @@ static int luaB_require (lua_State *L) {
else { /* must load it */
while (status == LUA_ERRFILE && (path = nextpath(L, path)) != NULL) {
composename(L);
- status = lua_dofile(L, lua_tostring(L, -1)); /* try to load it */
+ status = lua_loadfile(L, lua_tostring(L, -1)); /* try to load it */
+ if (status == 0)
+ status = lua_pcall(L, 0, 0, 0);
lua_settop(L, 3); /* pop string and eventual results from dofile */
}
}
@@ -448,8 +398,8 @@ static int luaB_require (lua_State *L) {
luaL_verror(L, "could not load package `%.20s' from path `%.200s'",
lua_tostring(L, 1), lua_tostring(L, 3));
}
- default: { /* error loading package */
- lua_error(L, NULL);
+ default: {
+ lua_error(L, "error loading package");
return 0; /* to avoid warnings */
}
}
@@ -474,13 +424,11 @@ static const luaL_reg base_funcs[] = {
{"unpack", luaB_unpack},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
- {"call", luaB_call},
+ {"pcall", luaB_pcall},
{"collectgarbage", luaB_collectgarbage},
{"gcinfo", luaB_gcinfo},
{"loadfile", luaB_loadfile},
{"loadstring", luaB_loadstring},
- {"dofile", luaB_dofile},
- {"dostring", luaB_dostring},
{"require", luaB_require},
{NULL, NULL}
};
@@ -497,7 +445,7 @@ static int luaB_resume (lua_State *L) {
lua_State *co = (lua_State *)lua_getfrombox(L, lua_upvalueindex(1));
lua_settop(L, 0);
if (lua_resume(L, co) != 0)
- lua_error(L, "error running co-routine");
+ lua_errorobj(L);
return lua_gettop(L);
}
diff --git a/ldblib.c b/ldblib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldblib.c,v 1.47 2002/04/09 19:48:08 roberto Exp roberto $
+** $Id: ldblib.c,v 1.48 2002/04/22 14:40:50 roberto Exp roberto $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -189,7 +189,6 @@ static int errorfb (lua_State *L) {
lua_Debug ar;
luaL_Buffer b;
luaL_buffinit(L, &b);
- luaL_addstring(&b, "error: ");
luaL_addstring(&b, luaL_check_string(L, 1));
luaL_addstring(&b, "\n");
while (lua_getstack(L, level++, &ar)) {
@@ -243,12 +242,7 @@ static int errorfb (lua_State *L) {
luaL_addstring(&b, "\n");
}
luaL_pushresult(&b);
- lua_getglobal(L, LUA_ALERT);
- if (lua_isfunction(L, -1)) { /* avoid loop if _ALERT is not defined */
- lua_pushvalue(L, -2); /* error message */
- lua_rawcall(L, 1, 0);
- }
- return 0;
+ return 1;
}
diff --git a/ldo.c b/ldo.c
@@ -1,12 +1,11 @@
/*
-** $Id: ldo.c,v 1.171 2002/04/16 17:08:28 roberto Exp roberto $
+** $Id: ldo.c,v 1.172 2002/04/22 14:40:50 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
#include <setjmp.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -38,7 +37,7 @@ 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 */
+ TObject *err; /* error function -> message (start of `ud') */
};
@@ -110,7 +109,7 @@ 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_error(L, NULL, LUA_ERRERR); /* break run without error message */
+ luaD_error(L, "error in error handling", LUA_ERRERR);
else {
luaD_reallocCI(L, 2*L->size_ci);
if (L->size_ci > LUA_MAXCALLS)
@@ -303,7 +302,12 @@ static void move_results (lua_State *L, TObject *from, TObject *to) {
}
-static void resume (lua_State *L, void *numres) {
+struct ResS {
+ TObject err;
+ int numres;
+};
+
+static void resume (lua_State *L, void *ud) {
StkId firstResult;
CallInfo *ci = L->ci;
if (ci->savedpc != ci_func(ci)->l.p->code) { /* not first time? */
@@ -316,9 +320,9 @@ static void resume (lua_State *L, void *numres) {
}
firstResult = luaV_execute(L);
if (firstResult == NULL) /* yield? */
- *(int *)numres = L->ci->yield_results;
+ cast(struct ResS *, ud)->numres = L->ci->yield_results;
else { /* return */
- *(int *)numres = L->top - firstResult;
+ cast(struct ResS *, ud)->numres = L->top - firstResult;
luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
}
}
@@ -326,8 +330,7 @@ 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;
+ struct ResS ud;
int status;
lua_lock(L);
ci = co->ci;
@@ -335,11 +338,17 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) {
luaD_runerror(L, "thread is dead - cannot be resumed");
if (co->errorJmp != NULL) /* ?? */
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 (L->errorJmp) {
+ setobj(&ud.err, L->errorJmp->err);
+ }
+ else
+ setnilvalue(&ud.err);
+ status = luaD_runprotected(co, resume, &ud.err);
if (status == 0)
- move_results(L, co->top - numres, co->top);
+ move_results(L, co->top - ud.numres, co->top);
+ else {
+ setobj(L->top++, &ud.err);
+}
lua_unlock(L);
return status;
}
@@ -361,6 +370,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
** Execute a protected call.
*/
struct CallS { /* data to `f_call' */
+ TObject err; /* error field... */
StkId func;
int nresults;
};
@@ -377,10 +387,12 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) {
int status;
c.func = L->top - (nargs+1); /* function to be called */
c.nresults = nresults;
- status = luaD_runprotected(L, &f_call, err, &c);
+ c.err = *err;
+ status = luaD_runprotected(L, &f_call, &c.err);
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 */
+ setobj(L->top++, &c.err);
}
return status;
}
@@ -390,6 +402,7 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) {
** Execute a protected parser.
*/
struct SParser { /* data to `f_parser' */
+ TObject err; /* error field... */
ZIO *z;
int bin;
};
@@ -406,7 +419,6 @@ static void f_parser (lua_State *L, void *ud) {
int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
struct SParser p;
- TObject o;
lu_mem old_blocks;
int status;
lua_lock(L);
@@ -415,16 +427,18 @@ int luaD_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;
- setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE"));
- luaV_gettable(L, gt(L), &o, &o);
- status = luaD_runprotected(L, f_parser, &o, &p);
+ setnilvalue(&p.err);
+ status = luaD_runprotected(L, f_parser, &p.err);
if (status == 0) {
/* add new memory to threshold (as it probably will stay) */
lua_assert(G(L)->nblocks >= old_blocks);
G(L)->GCthreshold += (G(L)->nblocks - old_blocks);
}
- else if (status == LUA_ERRRUN) /* an error occurred: correct error code */
- status = LUA_ERRSYNTAX;
+ else {
+ setobj(L->top++, &p.err);
+ if (status == LUA_ERRRUN) /* an error occurred: correct error code */
+ status = LUA_ERRSYNTAX;
+ }
lua_unlock(L);
return status;
}
@@ -438,14 +452,18 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
*/
-static void message (lua_State *L, const char *msg) {
- TObject *m = &L->errorJmp->err;
- if (ttype(m) == LUA_TFUNCTION) {
+static void message (lua_State *L, const TObject *msg, int nofunc) {
+ TObject *m = L->errorJmp->err;
+ if (nofunc || ttype(m) != LUA_TFUNCTION) { /* no error function? */
+ setobj(m, msg); /* keep error message */
+ }
+ else { /* call error function */
setobj(L->top, m);
incr_top(L);
- setsvalue(L->top, luaS_new(L, msg));
+ setobj(L->top, msg);
incr_top(L);
- luaD_call(L, L->top - 2, 0);
+ luaD_call(L, L->top - 2, 1);
+ setobj(m, L->top - 1);
}
}
@@ -453,10 +471,10 @@ static void message (lua_State *L, const char *msg) {
/*
** Reports an error, and jumps up to the available recovery label
*/
-void luaD_error (lua_State *L, const char *s, int errcode) {
+void luaD_errorobj (lua_State *L, const TObject *s, int errcode) {
if (L->errorJmp) {
L->errorJmp->status = errcode;
- if (s) message(L, s);
+ message(L, s, (errcode >= LUA_ERRMEM));
longjmp(L->errorJmp->b, 1);
}
else {
@@ -466,24 +484,34 @@ void luaD_error (lua_State *L, const char *s, int errcode) {
}
+void luaD_error (lua_State *L, const char *s, int errcode) {
+ TObject errobj;
+ if (errcode == LUA_ERRMEM && (G(L) == NULL || G(L)->GCthreshold == 0))
+ setnilvalue(&errobj); /* error bulding state */
+ else
+ setsvalue(&errobj, luaS_new(L, s));
+ luaD_errorobj(L, &errobj, errcode);
+}
+
+
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) {
+int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
struct lua_longjmp lj;
lj.ci = L->ci;
lj.top = L->top;
lj.allowhooks = L->allowhooks;
lj.status = 0;
- lj.err = *err;
+ lj.err = ud;
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->ci = lj.ci;
+ else { /* an error occurred */
+ L->ci = lj.ci; /* restore the state */
L->top = lj.top;
L->allowhooks = lj.allowhooks;
restore_stack_limit(L);
diff --git a/ldo.h b/ldo.h
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.h,v 1.42 2002/03/25 17:47:14 roberto Exp roberto $
+** $Id: ldo.h,v 1.43 2002/04/22 14:40:50 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -42,8 +42,9 @@ 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, int errcode);
+void luaD_errorobj (lua_State *L, const TObject *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);
+int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud);
#endif
diff --git a/lmem.c b/lmem.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmem.c,v 1.52 2001/11/28 20:13:13 roberto Exp roberto $
+** $Id: lmem.c,v 1.53 2002/04/22 14:40:23 roberto Exp roberto $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@@ -58,7 +58,7 @@ void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
block = l_realloc(block, oldsize, size);
if (block == NULL) {
if (L)
- luaD_error(L, NULL, LUA_ERRMEM); /* break run without error message */
+ luaD_error(L, MEMERRMSG, LUA_ERRMEM);
else return NULL; /* error before creating state! */
}
}
diff --git a/lmem.h b/lmem.h
@@ -1,5 +1,5 @@
/*
-** $Id: lmem.h,v 1.24 2001/09/07 17:30:16 roberto Exp $
+** $Id: lmem.h,v 1.25 2001/11/28 20:13:13 roberto Exp roberto $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@@ -13,6 +13,9 @@
#include "llimits.h"
#include "lua.h"
+#define MEMERRMSG "not enough memory"
+
+
void *luaM_realloc (lua_State *L, void *oldblock, lu_mem oldsize, lu_mem size);
void *luaM_growaux (lua_State *L, void *block, int *size, int size_elem,
diff --git a/lstate.c b/lstate.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.c,v 1.90 2002/04/22 14:40:23 roberto Exp roberto $
+** $Id: lstate.c,v 1.91 2002/04/23 15:04:39 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -57,6 +57,7 @@ static void f_luaopen (lua_State *L, void *ud) {
UNUSED(ud);
/* create a new global state */
L->l_G = luaM_new(L, global_State);
+ G(L)->GCthreshold = 0; /* mark it as unfinished state */
G(L)->strt.size = 0;
G(L)->strt.nuse = 0;
G(L)->strt.hash = NULL;
@@ -83,6 +84,7 @@ static void f_luaopen (lua_State *L, void *ud) {
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
luaT_init(L);
luaX_init(L);
+ luaS_fix(luaS_newliteral(L, MEMERRMSG));
G(L)->GCthreshold = 4*G(L)->nblocks;
}
@@ -122,12 +124,14 @@ LUA_API lua_State *lua_newthread (lua_State *OL) {
LUA_API lua_State *lua_open (void) {
lua_State *L;
+ TObject dummy;
+ setnilvalue(&dummy);
L = luaM_new(NULL, lua_State);
if (L) { /* allocation OK? */
preinit_state(L);
L->l_G = NULL;
L->next = L->previous = L;
- if (luaD_runprotected(L, f_luaopen, &luaO_nilobject, NULL) != 0) {
+ if (luaD_runprotected(L, f_luaopen, &dummy) != 0) {
/* memory allocation error: free partial state */
close_state(L);
L = NULL;
diff --git a/ltests.c b/ltests.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltests.c,v 1.116 2002/04/05 18:54:31 roberto Exp roberto $
+** $Id: ltests.c,v 1.117 2002/04/24 20:07:46 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@@ -383,7 +383,11 @@ static int udataval (lua_State *L) {
static int doonnewstack (lua_State *L) {
lua_State *L1 = lua_newthread(L);
- int status = lua_dostring(L1, luaL_check_string(L, 1));
+ size_t l;
+ const char *s = luaL_check_lstr(L, 1, &l);
+ int status = lua_loadbuffer(L1, s, l, s);
+ if (status == 0)
+ status = lua_pcall(L1, 0, 0, 0);
lua_pushnumber(L, status);
lua_closethread(L, L1);
return 1;
diff --git a/lua.c b/lua.c
@@ -1,5 +1,5 @@
/*
-** $Id: lua.c,v 1.83 2002/04/22 14:40:50 roberto Exp roberto $
+** $Id: lua.c,v 1.84 2002/04/23 14:59:22 roberto Exp roberto $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -66,23 +66,30 @@ static void laction (int i) {
}
-/* Lua gives no message in such cases, so we provide one */
-static void report (int result) {
- if (result == LUA_ERRMEM || result == LUA_ERRERR)
- fprintf(stderr, "%s: %s\n", LUA_PROGNAME, luaL_errstr(result));
+static void report (int status) {
+ if (status == 0) return;
+ else {
+ const char *msg = lua_tostring(L, -1);
+ if (msg == NULL) msg = "(no message)";
+ fprintf(stderr, "error: %s\n", msg);
+ lua_pop(L, 1);
+ }
}
-static int ldo (int (*f)(lua_State *l, const char *), const char *name,
- int clear) {
- int result;
+static int lcall (int clear) {
+ int status;
int top = lua_gettop(L);
+ lua_getglobal(L, "_ERRORMESSAGE");
+ lua_insert(L, top);
signal(SIGINT, laction);
- result = f(L, name); /* dostring | dofile */
+ status = lua_pcall(L, 0, LUA_MULTRET, top);
signal(SIGINT, SIG_DFL);
- if (clear) lua_settop(L, top); /* remove eventual results */
- report(result);
- return result;
+ if (status == 0) {
+ if (clear) lua_settop(L, top); /* remove eventual results */
+ else lua_remove(L, top); /* else remove only error function */
+ }
+ return status;
}
@@ -138,16 +145,18 @@ static int l_getargs (lua_State *l) {
static int file_input (const char *name) {
- int result = ldo(lua_dofile, name, 1);
- if (result) {
- if (result == LUA_ERRFILE) {
- fprintf(stderr, "%s: %s ", LUA_PROGNAME, luaL_errstr(result));
- perror(name);
- }
- return EXIT_FAILURE;
- }
- else
- return EXIT_SUCCESS;
+ int status = lua_loadfile(L, name);
+ if (status == 0) status = lcall(1);
+ report(status);
+ return status;
+}
+
+
+static int dostring (const char *s) {
+ int status = lua_loadbuffer(L, s, strlen(s), s);
+ if (status == 0) status = lcall(1);
+ report(status);
+ return status;
}
@@ -177,85 +186,65 @@ static char *readline (const char *prompt) {
#endif
-static const char *get_prompt (int incomplete) {
+static const char *get_prompt (int firstline) {
const char *p = NULL;
- lua_getglobal(L, incomplete ? "_PROMPT2" : "_PROMPT");
+ lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
p = lua_tostring(L, -1);
- if (p == NULL) p = (incomplete ? PROMPT2 : PROMPT);
+ if (p == NULL) p = (firstline ? PROMPT : PROMPT2);
lua_pop(L, 1); /* remove global */
return p;
}
-static int incomplete = 0;
-
-static int trap_eof (lua_State *l) {
- const char *s = lua_tostring(l, 1);
- if (strstr(s, "last token read: `<eof>'") != NULL)
- incomplete = 1;
- else
- fprintf(stderr, "error: %s\n", s);
- return 0;
+static int incomplete (int status) {
+ if (status == LUA_ERRSYNTAX &&
+ strstr(lua_tostring(L, -1), "last token read: `<eof>'") != NULL) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ else
+ return 0;
}
static int load_string (void) {
- lua_getglobal(L, "_ERRORMESSAGE");
- lua_pushvalue(L, 1);
- lua_setglobal(L, "_ERRORMESSAGE");
- incomplete = 0;
- for (;;) { /* repeat until gets a complete line */
- int result;
- char *buffer = readline(get_prompt(incomplete));
+ int firstline = 1;
+ int status;
+ lua_settop(L, 0);
+ do { /* repeat until gets a complete line */
+ char *buffer = readline(get_prompt(firstline));
if (buffer == NULL) { /* input end? */
- lua_settop(L, 2);
- lua_setglobal(L, "_ERRORMESSAGE");
- return 0;
+ lua_settop(L, 0);
+ return -1; /* input end */
}
- if (!incomplete && buffer[0] == '=') {
+ if (firstline && buffer[0] == '=') {
buffer[0] = ' ';
lua_pushstring(L, "return");
}
+ firstline = 0;
push_line(buffer);
- lua_concat(L, lua_gettop(L)-2);
- incomplete = 0;
- result = lua_loadbuffer(L, lua_tostring(L, 3), lua_strlen(L, 3), "=stdin");
- if (incomplete) continue; /* repeat loop to get rest of `line' */
- save_line(lua_tostring(L, 3));
- lua_remove(L, 3);
- if (result == 0) {
- lua_insert(L, 2); /* swap compiled chunk with old _ERRORMESSAGE */
- lua_setglobal(L, "_ERRORMESSAGE"); /* restore old _ERRORMESSAGE */
- return 1;
- }
- else
- report(result);
- }
-}
-
-
-static int lcall (lua_State *l, const char *name) {
- (void)name; /* to avoid warnings */
- return lua_call(l, 0, LUA_MULTRET);
+ lua_concat(L, lua_gettop(L));
+ status = lua_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
+ } while (incomplete(status)); /* repeat loop to get rest of `line' */
+ save_line(lua_tostring(L, 1));
+ lua_remove(L, 1);
+ return status;
}
static void manual_input (int version) {
+ int status;
if (version) print_version();
- lua_settop(L, 0);
- lua_pushcfunction(L, trap_eof); /* set up handler for incomplete lines */
- while (load_string()) {
- ldo(lcall, NULL, 0);
- if (lua_gettop(L) > 1) { /* any result to print? */
+ while ((status = load_string()) != -1) {
+ if (status == 0) status = lcall(0);
+ report(status);
+ if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
lua_getglobal(L, "print");
- lua_insert(L, 2);
- lua_call(L, lua_gettop(L)-2, 0);
+ lua_insert(L, 1);
+ lua_call(L, lua_gettop(L)-1, 0);
}
- else
- lua_settop(L, 1); /* remove eventual results */
}
printf("\n");
- lua_pop(L, 1); /* remove trap_eof */
}
@@ -265,7 +254,7 @@ static int handle_argv (char *argv[], int *toclose) {
manual_input(1);
}
else
- ldo(lua_dofile, NULL, 1); /* executes stdin as a file */
+ file_input(NULL); /* executes stdin as a file */
}
else { /* other arguments; loop over them */
int i;
@@ -274,12 +263,12 @@ static int handle_argv (char *argv[], int *toclose) {
if (strchr(argv[i], '='))
assign(argv[i]);
else
- if (file_input(argv[i]) != EXIT_SUCCESS)
+ if (file_input(argv[i]))
return EXIT_FAILURE; /* stop if file fails */
}
else switch (argv[i][1]) { /* option */
case '\0': {
- ldo(lua_dofile, NULL, 1); /* executes stdin as a file */
+ file_input(NULL); /* executes stdin as a file */
break;
}
case 'i': {
@@ -300,7 +289,7 @@ static int handle_argv (char *argv[], int *toclose) {
print_usage();
return EXIT_FAILURE;
}
- if (ldo(lua_dostring, argv[i], 1) != 0) {
+ if (dostring(argv[i]) != 0) {
fprintf(stderr, "%s: error running argument `%.99s'\n",
LUA_PROGNAME, argv[i]);
return EXIT_FAILURE;
diff --git a/lua.h b/lua.h
@@ -1,5 +1,5 @@
/*
-** $Id: lua.h,v 1.128 2002/04/22 14:40:23 roberto Exp roberto $
+** $Id: lua.h,v 1.129 2002/05/01 20:40:42 roberto Exp roberto $
** Lua - An Extensible Extension Language
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** e-mail: info@lua.org
@@ -35,7 +35,7 @@
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
-/* error codes for `lua_do*' and the like */
+/* error codes for `lua_load*' and `lua_pcall' */
#define LUA_ERRRUN 1
#define LUA_ERRFILE 2
#define LUA_ERRSYNTAX 3
@@ -166,18 +166,13 @@ LUA_API void lua_setmetatable (lua_State *L, int objindex);
/*
-** `load' and `do' functions (load and run Lua code)
+** `load' and `call' functions (load and run Lua code)
*/
-LUA_API int lua_call (lua_State *L, int nargs, int nresults);
LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults);
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errf);
LUA_API int lua_loadfile (lua_State *L, const char *filename);
LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size,
- const char *name);
-LUA_API int lua_dofile (lua_State *L, const char *filename);
-LUA_API int lua_dostring (lua_State *L, const char *str);
-LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
- const char *name);
+ const char *name);
/*
@@ -243,10 +238,17 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size);
(sizeof(s)/sizeof(char))-1)
+
/*
** compatibility macros and functions
*/
+LUA_API int lua_call (lua_State *L, int nargs, int nresults);
+LUA_API int lua_dofile (lua_State *L, const char *filename);
+LUA_API int lua_dostring (lua_State *L, const char *str);
+LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
+ const char *name);
+
LUA_API int lua_pushupvalues (lua_State *L);
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)