diff --git a/lauxlib.c b/lauxlib.c index b7b82661..af38c670 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,33 +1,36 @@ /* -** $Id: lauxlib.c,v 1.70 2002/05/15 18:57:44 roberto Exp roberto $ +** $Id: lauxlib.c,v 1.71 2002/05/16 18:39:46 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ +#include #include #include #include +#ifndef lua_filerror +#include +#define lua_fileerror (strerror(errno)) +#endif + + /* This file uses only the official API of Lua. ** Any function declared here could be written as an application function. -** With care, these functions can be used by other libraries. */ #include "lua.h" #include "lauxlib.h" #include "luadebug.h" -#include "lualib.h" -LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { - int i; - for (i=0; list[i]; i++) - if (strcmp(list[i], name) == 0) - return i; - return -1; /* name not found */ -} +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { @@ -54,6 +57,33 @@ static void tag_error (lua_State *L, int narg, int tag) { } +LUALIB_API int luaL_verror (lua_State *L, const char *fmt, ...) { + lua_Debug ar; + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = lua_pushvfstring(L, fmt, argp); + va_end(argp); + if (lua_getstack(L, 1, &ar)) { /* check calling function */ + lua_getinfo(L, "Snl", &ar); + if (ar.currentline > 0) + lua_pushfstring(L, "%s:%d: %s", ar.short_src, ar.currentline, msg); + } + return lua_errorobj(L); +} + +/* }====================================================== */ + + +LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { + int i; + for (i=0; list[i]; i++) + if (strcmp(list[i], name) == 0) + return i; + return -1; /* name not found */ +} + + LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *mes) { if (!lua_checkstack(L, space)) luaL_verror(L, "stack overflow (%s)", mes); @@ -143,21 +173,6 @@ LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname, } -LUALIB_API int luaL_verror (lua_State *L, const char *fmt, ...) { - lua_Debug ar; - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = lua_pushvfstring(L, fmt, argp); - va_end(argp); - if (lua_getstack(L, 1, &ar)) { /* check calling function */ - lua_getinfo(L, "Snl", &ar); - if (ar.currentline > 0) - lua_pushfstring(L, "%s:%d: %s", ar.short_src, ar.currentline, msg); - } - return lua_errorobj(L); -} - /* ** {====================================================== @@ -284,3 +299,144 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { } } + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + FILE *f; + char buff[LUAL_BUFFERSIZE]; +} LoadF; + + +static const char *getF (void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f); + return (*size > 0) ? lf->buff : NULL; +} + + +static int errfile (lua_State *L, const char *filename) { + if (filename == NULL) filename = "stdin"; + lua_pushfstring(L, "cannot read %s: %s", filename, lua_fileerror); + return LUA_ERRFILE; +} + + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { + LoadF lf; + int status; + int c; + int old_top = lua_gettop(L); + lf.f = (filename == NULL) ? stdin : fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, filename); /* unable to open file */ + c = ungetc(getc(lf.f), lf.f); + if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */ + fclose(lf.f); + lf.f = fopen(filename, "rb"); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, filename); /* unable to reopen file */ + } + if (filename == NULL) + lua_pushliteral(L, "=stdin"); + else + lua_pushfstring(L, "@%s", filename); + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + lua_remove(L, old_top+1); /* remove filename from stack */ + if (ferror(lf.f)) { + lua_settop(L, old_top); /* ignore results from `lua_load' */ + return errfile(L, filename); + } + if (lf.f != stdin) + fclose(lf.f); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** 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); + } +} + + +LUALIB_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; +} + + +LUALIB_API int lua_dofile (lua_State *L, const char *filename) { + return aux_do(L, luaL_loadfile(L, filename)); +} + + +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + return aux_do(L, luaL_loadbuffer(L, buff, size, name)); +} + + +LUALIB_API int lua_dostring (lua_State *L, const char *str) { + return lua_dobuffer(L, str, strlen(str), str); +} + +/* }====================================================== */ diff --git a/lauxlib.h b/lauxlib.h index f8c0235e..227e77a6 100644 --- a/lauxlib.h +++ b/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.46 2002/05/06 19:05:10 roberto Exp roberto $ +** $Id: lauxlib.h,v 1.47 2002/05/16 18:39:46 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -51,6 +51,10 @@ 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); +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename); +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name); + /* @@ -113,6 +117,12 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B); #define luaL_checktype luaL_check_type #define luaL_checkany luaL_check_any +LUALIB_API int lua_call (lua_State *L, int nargs, int nresults); +LUALIB_API int lua_dofile (lua_State *L, const char *filename); +LUALIB_API int lua_dostring (lua_State *L, const char *str); +LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, + const char *name); + #endif diff --git a/lbaselib.c b/lbaselib.c index 9c711c8d..88c8db67 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.74 2002/05/16 18:39:46 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.75 2002/05/16 19:09:19 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -174,7 +174,7 @@ static int luaB_nexti (lua_State *L) { else { /* `for' step */ i++; /* next value */ lua_pushnumber(L, i); - lua_rawgeti(L, 1, i); + lua_rawgeti(L, 1, (int)i); return (lua_isnil(L, -1)) ? 0 : 2; } } @@ -194,20 +194,20 @@ static int luaB_loadstring (lua_State *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)); + return passresults(L, luaL_loadbuffer(L, s, l, chunkname)); } static int luaB_loadfile (lua_State *L) { const char *fname = luaL_opt_string(L, 1, NULL); - return passresults(L, lua_loadfile(L, fname)); + return passresults(L, luaL_loadfile(L, fname)); } static int luaB_assert (lua_State *L) { luaL_check_any(L, 1); if (!lua_toboolean(L, 1)) - return luaL_verror(L, "assertion failed! %s", luaL_opt_string(L, 2, "")); + return luaL_verror(L, "%s", luaL_opt_string(L, 2, "assertion failed!")); lua_settop(L, 1); return 1; } @@ -349,7 +349,7 @@ static int luaB_require (lua_State *L) { lua_settop(L, 3); /* reset stack position */ if ((path = pushnextpath(L, path)) == NULL) break; pushcomposename(L); - status = lua_loadfile(L, lua_tostring(L, -1)); /* try to load it */ + status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */ } } switch (status) { diff --git a/ltests.c b/ltests.c index 02b74eb2..c348a87c 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.121 2002/05/13 13:10:04 roberto Exp roberto $ +** $Id: ltests.c,v 1.122 2002/05/16 14:59:49 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -397,7 +397,7 @@ static int doonnewstack (lua_State *L) { lua_State *L1 = lua_newthread(L); size_t l; const char *s = luaL_check_lstr(L, 1, &l); - int status = lua_loadbuffer(L1, s, l, s); + int status = luaL_loadbuffer(L1, s, l, s); if (status == 0) status = lua_pcall(L1, 0, 0, 0); lua_pushnumber(L, status); @@ -641,10 +641,10 @@ static int testC (lua_State *L) { else if EQ("loadstring") { size_t sl; const char *s = luaL_check_lstr(L, getnum, &sl); - lua_loadbuffer(L, s, sl, s); + luaL_loadbuffer(L, s, sl, s); } else if EQ("loadfile") { - lua_loadfile(L, luaL_check_string(L, getnum)); + luaL_loadfile(L, luaL_check_string(L, getnum)); } else if EQ("setmetatable") { lua_setmetatable(L, getnum); diff --git a/lua.c b/lua.c index 621abb83..5e1f4d5a 100644 --- a/lua.c +++ b/lua.c @@ -1,5 +1,5 @@ /* -** $Id: lua.c,v 1.87 2002/05/16 19:09:19 roberto Exp roberto $ +** $Id: lua.c,v 1.88 2002/05/23 19:43:04 roberto Exp roberto $ ** Lua stand-alone interpreter ** See Copyright Notice in lua.h */ @@ -107,16 +107,23 @@ static void print_usage (void) { } +static int l_panic (lua_State *l) { + (void)l; + fputs("unable to recover; exiting\n", stderr); + return 0; +} + + static void print_version (void) { printf("%.80s %.80s\n", LUA_VERSION, LUA_COPYRIGHT); } -static void assign (char *arg) { - char *eq = strchr(arg, '='); - *eq = '\0'; /* spilt `arg' in two strings (name & value) */ - lua_pushstring(L, eq+1); - lua_setglobal(L, arg); +static void assign (const char *arg) { + char *eq = strchr(arg, '='); /* arg is `name=value'; find the `=' */ + lua_pushlstring(L, arg, eq-arg); /* push name */ + lua_pushstring(L, eq+1); /* push value */ + lua_settable(L, LUA_GLOBALSINDEX); /* _G.name = value */ } @@ -158,12 +165,12 @@ static int docall (int status) { static int file_input (const char *name) { - return docall(lua_loadfile(L, name)); + return docall(luaL_loadfile(L, name)); } static int dostring (const char *s, const char *name) { - return docall(lua_loadbuffer(L, s, strlen(s), name)); + return docall(luaL_loadbuffer(L, s, strlen(s), name)); } @@ -231,7 +238,7 @@ static int load_string (void) { firstline = 0; push_line(buffer); lua_concat(L, lua_gettop(L)); - status = lua_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); + status = luaL_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); @@ -363,6 +370,7 @@ int main (int argc, char *argv[]) { int toclose = 0; (void)argc; /* to avoid warnings */ L = lua_open(); /* create state */ + lua_setpanicf(L, l_panic); LUA_USERINIT(L); /* open libraries */ register_own(argv); /* create own function */ status = handle_luainit();