new way to handle errors

This commit is contained in:
Roberto Ierusalimschy 2002-05-01 17:48:12 -03:00
parent b36b2a061c
commit 751cd867d3
13 changed files with 283 additions and 292 deletions

118
lapi.c
View File

@ -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);
}
/* }====================================================== */

View File

@ -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);

View File

@ -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);
/*

View File

@ -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");
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 */
}
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;
}
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);
}

View File

@ -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;
}

90
ldo.c
View File

@ -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);

5
ldo.h
View File

@ -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

4
lmem.c
View File

@ -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! */
}
}

5
lmem.h
View File

@ -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,

View File

@ -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;

View File

@ -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;

147
lua.c
View File

@ -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;

20
lua.h
View File

@ -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)