diff options
author | Lua Team <team@lua.org> | 2005-09-09 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 2005-09-09 12:00:00 +0000 |
commit | bd80c4ee9b6d9464cf9f3ff4ee41890d8b3ca9e6 (patch) | |
tree | e1d7c1b341ccb9a3a1fb044ac6e67b5a5e0259b7 /src | |
parent | bf6b5550cdfbc0c4a3a4577776ad76628d80718e (diff) | |
download | lua-github-bd80c4ee9b6d9464cf9f3ff4ee41890d8b3ca9e6.tar.gz |
Lua 5.1-alpha5.1-alpha
Diffstat (limited to 'src')
-rw-r--r-- | src/lapi.c | 27 | ||||
-rw-r--r-- | src/lauxlib.c | 181 | ||||
-rw-r--r-- | src/lauxlib.h | 57 | ||||
-rw-r--r-- | src/lbaselib.c | 74 | ||||
-rw-r--r-- | src/lcode.c | 85 | ||||
-rw-r--r-- | src/lcode.h | 5 | ||||
-rw-r--r-- | src/ldblib.c | 18 | ||||
-rw-r--r-- | src/ldebug.c | 24 | ||||
-rw-r--r-- | src/ldo.c | 164 | ||||
-rw-r--r-- | src/ldo.h | 15 | ||||
-rw-r--r-- | src/ldump.c | 79 | ||||
-rw-r--r-- | src/lgc.c | 19 | ||||
-rw-r--r-- | src/lgc.h | 17 | ||||
-rw-r--r-- | src/linit.c | 8 | ||||
-rw-r--r-- | src/liolib.c | 145 | ||||
-rw-r--r-- | src/llex.h | 4 | ||||
-rw-r--r-- | src/llimits.h | 21 | ||||
-rw-r--r-- | src/lmathlib.c | 44 | ||||
-rw-r--r-- | src/loadlib.c | 373 | ||||
-rw-r--r-- | src/lobject.c | 24 | ||||
-rw-r--r-- | src/lobject.h | 23 | ||||
-rw-r--r-- | src/lopcodes.c | 10 | ||||
-rw-r--r-- | src/lopcodes.h | 11 | ||||
-rw-r--r-- | src/loslib.c | 11 | ||||
-rw-r--r-- | src/lparser.c | 166 | ||||
-rw-r--r-- | src/lstate.c | 5 | ||||
-rw-r--r-- | src/lstate.h | 10 | ||||
-rw-r--r-- | src/lstrlib.c | 117 | ||||
-rw-r--r-- | src/ltable.c | 16 | ||||
-rw-r--r-- | src/ltable.h | 4 | ||||
-rw-r--r-- | src/ltablib.c | 14 | ||||
-rw-r--r-- | src/ltm.c | 4 | ||||
-rw-r--r-- | src/ltm.h | 6 | ||||
-rw-r--r-- | src/lua.c | 56 | ||||
-rw-r--r-- | src/lua.h | 17 | ||||
-rw-r--r-- | src/luac.c | 8 | ||||
-rw-r--r-- | src/luaconf.h | 307 | ||||
-rw-r--r-- | src/lualib.h | 4 | ||||
-rw-r--r-- | src/lundump.c | 242 | ||||
-rw-r--r-- | src/lundump.h | 49 | ||||
-rw-r--r-- | src/lvm.c | 143 | ||||
-rw-r--r-- | src/lvm.h | 4 | ||||
-rw-r--r-- | src/lzio.c | 22 | ||||
-rw-r--r-- | src/print.c | 8 |
44 files changed, 1433 insertions, 1208 deletions
@@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.41 2005/05/17 19:49:15 roberto Exp $ +** $Id: lapi.c,v 2.48 2005/09/01 17:42:22 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -113,11 +113,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { if (from == to) return; lua_lock(to); api_checknelems(from, n); - api_check(L, G(from) == G(to)); + api_check(from, G(from) == G(to)); + api_check(from, to->ci->top - to->top >= n); from->top -= n; for (i = 0; i < n; i++) { - setobj2s(to, to->top, from->top + i); - api_incr_top(to); + setobj2s(to, to->top++, from->top + i); } lua_unlock(to); } @@ -153,7 +153,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { LUA_API int lua_gettop (lua_State *L) { - return (L->top - L->base); + return cast(int, L->top - L->base); } @@ -344,6 +344,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { return NULL; } luaC_checkGC(L); + o = index2adr(L, idx); /* previous call may reallocate the stack */ lua_unlock(L); } if (len != NULL) *len = tsvalue(o)->len; @@ -351,7 +352,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { } -LUA_API size_t lua_objsize (lua_State *L, int idx) { +LUA_API size_t lua_objlen (lua_State *L, int idx) { StkId o = index2adr(L, idx); switch (ttype(o)) { case LUA_TSTRING: return tsvalue(o)->len; @@ -618,6 +619,9 @@ LUA_API void lua_getfenv (lua_State *L, int idx) { case LUA_TUSERDATA: sethvalue(L, L->top, uvalue(o)->env); break; + case LUA_TTHREAD: + setobj2s(L, L->top, gt(thvalue(o))); + break; default: setnilvalue(L->top); break; @@ -736,6 +740,9 @@ LUA_API int lua_setfenv (lua_State *L, int idx) { case LUA_TUSERDATA: uvalue(o)->env = hvalue(L->top - 1); break; + case LUA_TTHREAD: + sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); + break; default: res = 0; break; @@ -868,7 +875,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { if (isLfunction(o)) status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); else - status = 0; + status = 1; lua_unlock(L); return status; } @@ -969,10 +976,10 @@ LUA_API int lua_next (lua_State *L, int idx) { LUA_API void lua_concat (lua_State *L, int n) { lua_lock(L); - luaC_checkGC(L); api_checknelems(L, n); if (n >= 2) { - luaV_concat(L, n, L->top - L->base - 1); + luaC_checkGC(L); + luaV_concat(L, n, cast(int, L->top - L->base) - 1); L->top -= (n-1); } else if (n == 0) { /* push empty string */ @@ -985,7 +992,7 @@ LUA_API void lua_concat (lua_State *L, int n) { LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { - *ud = G(L)->ud; + if (ud) *ud = G(L)->ud; return G(L)->frealloc; } diff --git a/src/lauxlib.c b/src/lauxlib.c index 964f5eb0..b643d6c3 100644 --- a/src/lauxlib.c +++ b/src/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.133 2005/05/17 19:49:15 roberto Exp $ +** $Id: lauxlib.c,v 1.152 2005/09/06 17:20:11 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -42,7 +42,8 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { lua_Debug ar; - lua_getstack(L, 0, &ar); + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); lua_getinfo(L, "n", &ar); if (strcmp(ar.namewhat, "method") == 0) { narg--; /* do not count `self' */ @@ -65,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { static void tag_error (lua_State *L, int narg, int tag) { - luaL_typerror(L, narg, lua_typename(L, tag)); + luaL_typerror(L, narg, lua_typename(L, tag)); } @@ -95,12 +96,16 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { /* }====================================================== */ -LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { +LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, narg, def) : + luaL_checkstring(L, narg); int i; - for (i=0; list[i]; i++) - if (strcmp(list[i], name) == 0) + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) return i; - return -1; /* name not found */ + return luaL_argerror(L, narg, + lua_pushfstring(L, "invalid option " LUA_QS, name)); } @@ -112,31 +117,17 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { lua_newtable(L); /* create metatable */ lua_pushvalue(L, -1); lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - lua_pushvalue(L, -1); - lua_pushstring(L, tname); - lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */ return 1; } -LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) { - lua_getfield(L, LUA_REGISTRYINDEX, tname); -} - - LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - const char *tn; - if (!lua_getmetatable(L, ud)) return NULL; /* no metatable? */ - lua_rawget(L, LUA_REGISTRYINDEX); /* get registry[metatable] */ - tn = lua_tostring(L, -1); - if (tn && (strcmp(tn, tname) == 0)) { - lua_pop(L, 1); - return lua_touserdata(L, ud); - } - else { - lua_pop(L, 1); - return NULL; - } + void *p = lua_touserdata(L, ud); + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ + if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2)) + luaL_typerror(L, ud, tname); + lua_pop(L, 2); /* remove both metatables */ + return p; } @@ -230,26 +221,27 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { } -LUALIB_API void luaL_openlib (lua_State *L, const char *libname, - const luaL_reg *l, int nup) { +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l) { + luaI_openlib(L, libname, l, 0); +} + + +LUALIB_API void luaI_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { if (libname) { /* check whether lib already exists */ - luaL_getfield(L, LUA_GLOBALSINDEX, libname); - if (lua_isnil(L, -1)) { /* not found? */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, -1, libname); /* get _LOADED[libname] */ + if (!lua_istable(L, -1)) { /* not found? */ lua_pop(L, 1); /* remove previous result */ - lua_newtable(L); /* create it */ - if (lua_getmetatable(L, LUA_GLOBALSINDEX)) - lua_setmetatable(L, -2); /* share metatable with global table */ - /* register it with given name */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, libname) != NULL) + luaL_error(L, "name conflict for module " LUA_QS, libname); lua_pushvalue(L, -1); - luaL_setfield(L, LUA_GLOBALSINDEX, libname); + lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ } - else if (!lua_istable(L, -1)) - luaL_error(L, "name conflict for library " LUA_QS, libname); - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_pushvalue(L, -2); - lua_setfield(L, -2, libname); /* _LOADED[modname] = new table */ - lua_pop(L, 1); /* remove _LOADED table */ + lua_remove(L, -2); /* remove _LOADED table */ lua_insert(L, -(nup+1)); /* move library table to below upvalues */ } for (; l->name; l++) { @@ -270,7 +262,7 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname, ** ======================================================= */ -#ifndef luaL_getn +#if defined(LUA_COMPAT_GETN) static int checkint (lua_State *L, int topop) { int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; @@ -313,7 +305,7 @@ LUALIB_API int luaL_getn (lua_State *L, int t) { if ((n = checkint(L, 2)) >= 0) return n; lua_getfield(L, t, "n"); /* else try t.n */ if ((n = checkint(L, 1)) >= 0) return n; - return lua_objsize(L, t); + return lua_objlen(L, t); } #endif @@ -321,21 +313,11 @@ LUALIB_API int luaL_getn (lua_State *L, int t) { /* }====================================================== */ -static const char *pushnexttemplate (lua_State *L, const char *path) { - const char *l; - if (*path == '\0') return NULL; /* no more templates */ - if (*path == LUA_PATHSEP) path++; /* skip separator */ - l = strchr(path, LUA_PATHSEP); /* find next separator */ - if (l == NULL) l = path+strlen(path); - lua_pushlstring(L, path, l - path); /* template */ - return l; -} - LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, const char *r) { const char *wild; - int l = strlen(p); + size_t l = strlen(p); luaL_Buffer b; luaL_buffinit(L, &b); while ((wild = strstr(s, p)) != NULL) { @@ -343,65 +325,19 @@ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, luaL_addstring(&b, r); /* push replacement in place of pattern */ s = wild + l; /* continue after `p' */ } - luaL_addstring(&b, s); /* push last suffix (`n' already includes this) */ + luaL_addstring(&b, s); /* push last suffix */ luaL_pushresult(&b); return lua_tostring(L, -1); } -static int readable (const char *fname) { - int err; - FILE *f = fopen(fname, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - getc(f); /* try to read it */ - err = ferror(f); - fclose(f); - return (err == 0); -} - - -LUALIB_API const char *luaL_searchpath (lua_State *L, const char *name, - const char *path) { - const char *p = path; - for (;;) { - const char *fname; - if ((p = pushnexttemplate(L, p)) == NULL) { - lua_pushfstring(L, "no readable " LUA_QS " in path " LUA_QS "", - name, path); - return NULL; - } - fname = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); - lua_remove(L, -2); /* remove path template */ - if (readable(fname)) /* does file exist and is readable? */ - return fname; /* return that file name */ - lua_pop(L, 1); /* remove file name */ - } -} - - -LUALIB_API const char *luaL_getfield (lua_State *L, int idx, - const char *fname) { +LUALIB_API const char *luaL_findtable (lua_State *L, int idx, + const char *fname) { const char *e; lua_pushvalue(L, idx); - while ((e = strchr(fname, '.')) != NULL) { - lua_pushlstring(L, fname, e - fname); - lua_rawget(L, -2); - lua_remove(L, -2); /* remove previous table */ - fname = e + 1; - if (!lua_istable(L, -1)) return fname; - } - lua_pushstring(L, fname); - lua_rawget(L, -2); /* get last field */ - lua_remove(L, -2); /* remove previous table */ - return NULL; -} - - -LUALIB_API const char *luaL_setfield (lua_State *L, int idx, - const char *fname) { - const char *e; - lua_pushvalue(L, idx); - while ((e = strchr(fname, '.')) != NULL) { + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); lua_pushlstring(L, fname, e - fname); lua_rawget(L, -2); if (lua_isnil(L, -1)) { /* no such field? */ @@ -411,17 +347,13 @@ LUALIB_API const char *luaL_setfield (lua_State *L, int idx, lua_pushvalue(L, -2); lua_settable(L, -4); /* set new table into field */ } - lua_remove(L, -2); /* remove previous table */ - fname = e + 1; - if (!lua_istable(L, -1)) { + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ lua_pop(L, 2); /* remove table and value */ - return fname; + return fname; /* return problematic part of the name */ } - } - lua_pushstring(L, fname); - lua_pushvalue(L, -3); /* move value to the top */ - lua_rawset(L, -3); /* set last field */ - lua_pop(L, 2); /* remove value and table */ + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); return NULL; } @@ -480,7 +412,7 @@ LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { while (l--) - luaL_putchar(B, *s++); + luaL_addchar(B, *s++); } @@ -538,7 +470,7 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ } else { /* no free elements */ - ref = lua_objsize(L, t); + ref = lua_objlen(L, t); ref++; /* create new reference */ } lua_rawseti(L, t, ref); @@ -661,6 +593,12 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, } +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + + + /* }====================================================== */ @@ -671,21 +609,22 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { free(ptr); return NULL; } - else + else return realloc(ptr, nsize); } static int panic (lua_State *L) { (void)L; /* to avoid warnings */ - fprintf(stderr, "PANIC: unprotected error during Lua-API call\n"); + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); return 0; } LUALIB_API lua_State *luaL_newstate (void) { lua_State *L = lua_newstate(l_alloc, NULL); - lua_atpanic(L, &panic); + if (L) lua_atpanic(L, &panic); return L; } diff --git a/src/lauxlib.h b/src/lauxlib.h index 83c807e9..aa07cb2b 100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.75 2005/03/29 16:20:48 roberto Exp $ +** $Id: lauxlib.h,v 1.85 2005/09/06 17:19:51 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -15,24 +15,34 @@ #include "lua.h" -#if !LUA_COMPAT_GETN -#define luaL_getn(L,i) lua_objsize(L, i) +#if defined(LUA_COMPAT_GETN) +LUALIB_API int (luaL_getn) (lua_State *L, int t); +LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); +#else +#define luaL_getn(L,i) ((int)lua_objlen(L, i)) #define luaL_setn(L,i,j) ((void)0) /* no op! */ #endif +#if defined(LUA_COMPAT_OPENLIB) +#define luaI_openlib luaL_openlib +#endif + /* extra error code for `luaL_load' */ #define LUA_ERRFILE (LUA_ERRERR+1) -typedef struct luaL_reg { +typedef struct luaL_Reg { const char *name; lua_CFunction func; -} luaL_reg; +} luaL_Reg; + -LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, - const luaL_reg *l, int nup); +LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l); LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); @@ -53,36 +63,31 @@ LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); LUALIB_API void (luaL_checkany) (lua_State *L, int narg); LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -LUALIB_API void (luaL_getmetatable) (lua_State *L, const char *tname); LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); LUALIB_API void (luaL_where) (lua_State *L, int lvl); LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); -LUALIB_API int (luaL_findstring) (const char *st, const char *const lst[]); - -LUALIB_API const char *(luaL_searchpath) (lua_State *L, const char *name, - const char *path); +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); 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_getn) (lua_State *L, int t); -LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); - LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); LUALIB_API lua_State *(luaL_newstate) (void); LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, const char *r); -LUALIB_API const char *(luaL_getfield) (lua_State *L, int idx, - const char *fname); -LUALIB_API const char *(luaL_setfield) (lua_State *L, int idx, - const char *fname); + +LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, + const char *fname); + @@ -103,6 +108,13 @@ LUALIB_API const char *(luaL_setfield) (lua_State *L, int idx, #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) +#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, 0, 0)) + +#define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, 0, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + + /* ** {====================================================== ** Generic Buffer manipulation @@ -118,10 +130,13 @@ typedef struct luaL_Buffer { char buffer[LUAL_BUFFERSIZE]; } luaL_Buffer; -#define luaL_putchar(B,c) \ +#define luaL_addchar(B,c) \ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ (*(B)->p++ = (char)(c))) +/* compatibility only */ +#define luaL_putchar(B,c) luaL_addchar(B,c) + #define luaL_addsize(B,n) ((B)->p += (n)) LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); @@ -149,6 +164,8 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); #define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) +#define luaL_reg luaL_Reg + #endif diff --git a/src/lbaselib.c b/src/lbaselib.c index d69d83ff..fb21da4b 100644 --- a/src/lbaselib.c +++ b/src/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.176 2005/05/17 19:49:15 roberto Exp $ +** $Id: lbaselib.c,v 1.182 2005/08/26 17:36:32 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -133,7 +133,7 @@ static void getfunc (lua_State *L) { static int luaB_getfenv (lua_State *L) { getfunc(L); if (lua_iscfunction(L, -1)) /* is a C function? */ - lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the global env. */ + lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ else lua_getfenv(L, -1); return 1; @@ -145,7 +145,10 @@ static int luaB_setfenv (lua_State *L) { getfunc(L); lua_pushvalue(L, 2); if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { - lua_replace(L, LUA_GLOBALSINDEX); + /* change environment of current thread */ + lua_pushthread(L); + lua_insert(L, -2); + lua_setfenv(L, -2); return 0; } else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) @@ -192,9 +195,8 @@ static int luaB_collectgarbage (lua_State *L) { "count", "step", "setpause", "setstepmul", NULL}; static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; - int o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts); + int o = luaL_checkoption(L, 1, "collect", opts); int ex = luaL_optinteger(L, 2, 0); - luaL_argcheck(L, o >= 0, 1, "invalid option"); lua_pushinteger(L, lua_gc(L, optsnum[o], ex)); return 1; } @@ -268,15 +270,7 @@ static int luaB_loadstring (lua_State *L) { static int luaB_loadfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); - const char *path = luaL_optstring(L, 2, NULL); - int status; - if (path == NULL) - status = luaL_loadfile(L, fname); - else { - fname = luaL_searchpath(L, fname, path); - status = (fname) ? luaL_loadfile(L, fname) : 1; - } - return load_aux(L, status); + return load_aux(L, luaL_loadfile(L, fname)); } @@ -331,13 +325,6 @@ static int luaB_assert (lua_State *L) { } -static int luaB_getn (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushinteger(L, lua_objsize(L, 1)); - return 1; -} - - static int luaB_unpack (lua_State *L) { int i = luaL_optint(L, 2, 1); int e = luaL_optint(L, 3, -1); @@ -442,32 +429,31 @@ static int luaB_newproxy (lua_State *L) { } -static const luaL_reg base_funcs[] = { +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, {"error", luaB_error}, - {"getmetatable", luaB_getmetatable}, - {"setmetatable", luaB_setmetatable}, + {"gcinfo", luaB_gcinfo}, {"getfenv", luaB_getfenv}, - {"setfenv", luaB_setfenv}, + {"getmetatable", luaB_getmetatable}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, + {"loadstring", luaB_loadstring}, {"next", luaB_next}, + {"pcall", luaB_pcall}, {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setfenv", luaB_setfenv}, + {"setmetatable", luaB_setmetatable}, {"tonumber", luaB_tonumber}, {"tostring", luaB_tostring}, {"type", luaB_type}, - {"assert", luaB_assert}, - {"getn", luaB_getn}, {"unpack", luaB_unpack}, - {"select", luaB_select}, - {"rawequal", luaB_rawequal}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"pcall", luaB_pcall}, {"xpcall", luaB_xpcall}, - {"collectgarbage", luaB_collectgarbage}, - {"gcinfo", luaB_gcinfo}, - {"loadfile", luaB_loadfile}, - {"dofile", luaB_dofile}, - {"loadstring", luaB_loadstring}, - {"load", luaB_load}, {NULL, NULL} }; @@ -593,13 +579,13 @@ static int luaB_corunning (lua_State *L) { } -static const luaL_reg co_funcs[] = { +static const luaL_Reg co_funcs[] = { {"create", luaB_cocreate}, - {"wrap", luaB_cowrap}, {"resume", luaB_coresume}, - {"yield", luaB_yield}, - {"status", luaB_costatus}, {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, {NULL, NULL} }; @@ -616,7 +602,7 @@ static void auxopen (lua_State *L, const char *name, static void base_open (lua_State *L) { lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */ + luaL_register(L, NULL, base_funcs); /* open lib into global table */ lua_pushliteral(L, LUA_VERSION); lua_setglobal(L, "_VERSION"); /* set global _VERSION */ /* `ipairs' and `pairs' need auxliliary functions as upvalues */ @@ -641,7 +627,7 @@ static void base_open (lua_State *L) { LUALIB_API int luaopen_base (lua_State *L) { base_open(L); - luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0); + luaL_register(L, LUA_COLIBNAME, co_funcs); return 2; } diff --git a/src/lcode.c b/src/lcode.c index 1e8d80fb..04838f33 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.12 2005/03/16 16:59:21 roberto Exp $ +** $Id: lcode.c,v 2.16 2005/08/29 20:49:21 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -53,6 +53,11 @@ int luaK_jump (FuncState *fs) { } +void luaK_ret (FuncState *fs, int first, int nret) { + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { luaK_codeABC(fs, op, A, B, C); return luaK_jump(fs); @@ -101,49 +106,50 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) { ** check whether list has any jump that do not produce a value ** (or produce an inverted value) */ -static int need_value (FuncState *fs, int list, int cond) { +static int need_value (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) { Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; + if (GET_OPCODE(i) != OP_TESTSET) return 1; } return 0; /* not found */ } static void patchtestreg (Instruction *i, int reg) { - if (reg == NO_REG) reg = GETARG_B(*i); - SETARG_A(*i, reg); + if (reg != NO_REG) + SETARG_A(*i, reg); + else /* no register to put value; change TESTSET to TEST */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); } -static void patchlistaux (FuncState *fs, int list, - int ttarget, int treg, int ftarget, int freg, int dtarget) { +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction *i = getjumpcontrol(fs, list); + if (GET_OPCODE(*i) == OP_TESTSET) + patchtestreg(i, NO_REG); + } +} + + +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { while (list != NO_JUMP) { int next = getjump(fs, list); Instruction *i = getjumpcontrol(fs, list); - if (GET_OPCODE(*i) != OP_TEST) { - lua_assert(dtarget != NO_JUMP); - fixjump(fs, list, dtarget); /* jump to default target */ - } - else { - if (GETARG_C(*i)) { - lua_assert(ttarget != NO_JUMP); - patchtestreg(i, treg); - fixjump(fs, list, ttarget); - } - else { - lua_assert(ftarget != NO_JUMP); - patchtestreg(i, freg); - fixjump(fs, list, ftarget); - } + if (GET_OPCODE(*i) == OP_TESTSET) { + patchtestreg(i, reg); + fixjump(fs, list, vtarget); } + else + fixjump(fs, list, dtarget); /* jump to default target */ list = next; } } static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc); + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); fs->jpc = NO_JUMP; } @@ -153,7 +159,7 @@ void luaK_patchlist (FuncState *fs, int list, int target) { luaK_patchtohere(fs, list); else { lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); + patchlistaux(fs, list, target, NO_REG, target); } } @@ -223,7 +229,7 @@ static int addk (FuncState *fs, TValue *k, TValue *v) { MAXARG_Bx, "constant table overflow"); while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); setobj(L, &f->k[fs->nk], v); - luaC_barriert(L, f, v); + luaC_barrier(L, f, v); return fs->nk++; } } @@ -373,7 +379,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { int final; /* position after whole expression */ int p_f = NO_JUMP; /* position of an eventual LOAD false */ int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) { + if (need_value(fs, e->t) || need_value(fs, e->f)) { int fj = NO_JUMP; /* first jump (over LOAD ops.) */ if (e->k != VJMP) fj = luaK_jump(fs); @@ -382,8 +388,8 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { luaK_patchtohere(fs, fj); } final = luaK_getlabel(fs); - patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); } e->f = e->t = NO_JUMP; e->info = reg; @@ -492,7 +498,8 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { static void invertjump (FuncState *fs, expdesc *e) { Instruction *pc = getjumpcontrol(fs, e->info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TEST); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); SETARG_A(*pc, !(GETARG_A(*pc))); } @@ -502,13 +509,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { Instruction ie = getcode(fs, e); if (GET_OPCODE(ie) == OP_NOT) { fs->pc--; /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); } /* else go through */ } discharge2anyreg(fs, e); freeexp(fs, e); - return condjump(fs, OP_TEST, NO_REG, e->info, cond); + return condjump(fs, OP_TESTSET, NO_REG, e->info, cond); } @@ -535,6 +542,8 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { } } luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + luaK_patchtohere(fs, e->t); + e->t = NO_JUMP; } @@ -560,6 +569,8 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { } } luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + luaK_patchtohere(fs, e->f); + e->f = NO_JUMP; } @@ -593,6 +604,8 @@ static void codenot (FuncState *fs, expdesc *e) { } /* interchange true and false lists */ { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); + removevalues(fs, e->t); } @@ -607,7 +620,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { case OPR_MINUS: { luaK_exp2val(fs, e); if (e->k == VK && ttisnumber(&fs->f->k[e->info])) - e->info = luaK_numberK(fs, luai_numunm(nvalue(&fs->f->k[e->info]))); + e->info = luaK_numberK(fs, luai_numunm(L, nvalue(&fs->f->k[e->info]))); else { luaK_exp2anyreg(fs, e); freeexp(fs, e); @@ -620,10 +633,10 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { codenot(fs, e); break; } - case OPR_SIZE: { + case OPR_LEN: { luaK_exp2anyreg(fs, e); freeexp(fs, e); - e->info = luaK_codeABC(fs, OP_SIZ, 0, e->info, 0); + e->info = luaK_codeABC(fs, OP_LEN, 0, e->info, 0); e->k = VRELOCABLE; break; } @@ -636,14 +649,10 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { switch (op) { case OPR_AND: { luaK_goiftrue(fs, v); - luaK_patchtohere(fs, v->t); - v->t = NO_JUMP; break; } case OPR_OR: { luaK_goiffalse(fs, v); - luaK_patchtohere(fs, v->f); - v->f = NO_JUMP; break; } case OPR_CONCAT: { diff --git a/src/lcode.h b/src/lcode.h index 19a3284e..ed1a95bc 100644 --- a/src/lcode.h +++ b/src/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.43 2005/04/25 19:24:10 roberto Exp $ +** $Id: lcode.h,v 1.45 2005/08/29 20:49:21 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -34,7 +34,7 @@ typedef enum BinOpr { #define binopistest(op) ((op) >= OPR_NE) -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_SIZE, OPR_NOUNOPR } UnOpr; +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; #define getcode(fs,e) ((fs)->f->code[(e)->info]) @@ -65,6 +65,7 @@ LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); diff --git a/src/ldblib.c b/src/ldblib.c index 6c1a1776..e7458634 100644 --- a/src/ldblib.c +++ b/src/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.98 2005/05/17 19:49:15 roberto Exp $ +** $Id: ldblib.c,v 1.101 2005/08/26 17:36:32 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -365,26 +365,26 @@ static int db_errorfb (lua_State *L) { } -static const luaL_reg dblib[] = { - {"getmetatable", db_getmetatable}, - {"setmetatable", db_setmetatable}, +static const luaL_Reg dblib[] = { + {"debug", db_debug}, {"getfenv", db_getfenv}, - {"setfenv", db_setfenv}, - {"getlocal", db_getlocal}, - {"getinfo", db_getinfo}, {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getmetatable", db_getmetatable}, {"getupvalue", db_getupvalue}, + {"setfenv", db_setfenv}, {"sethook", db_sethook}, {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, {"setupvalue", db_setupvalue}, - {"debug", db_debug}, {"traceback", db_errorfb}, {NULL, NULL} }; LUALIB_API int luaopen_debug (lua_State *L) { - luaL_openlib(L, LUA_DBLIBNAME, dblib, 0); + luaL_register(L, LUA_DBLIBNAME, dblib); return 1; } diff --git a/src/ldebug.c b/src/ldebug.c index 73a604ff..11166c0a 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.20 2005/05/17 19:49:15 roberto Exp $ +** $Id: ldebug.c,v 2.26 2005/08/04 13:37:38 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -92,7 +92,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { } if (level == 0 && ci > L->base_ci) { /* level found? */ status = 1; - ar->i_ci = ci - L->base_ci; + ar->i_ci = cast(int, ci - L->base_ci); } else if (level < 0) { /* level is of a lost tail call? */ status = 1; @@ -152,6 +152,7 @@ static void funcinfo (lua_Debug *ar, Closure *cl) { if (cl->c.isC) { ar->source = "=[C]"; ar->linedefined = -1; + ar->lastlinedefined = -1; ar->what = "C"; } else { @@ -164,7 +165,7 @@ static void funcinfo (lua_Debug *ar, Closure *cl) { } -static void info_tailcall (lua_State *L, lua_Debug *ar) { +static void info_tailcall (lua_Debug *ar) { ar->name = ar->namewhat = ""; ar->what = "tail"; ar->lastlinedefined = ar->linedefined = ar->currentline = -1; @@ -194,7 +195,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, Closure *f, CallInfo *ci) { int status = 1; if (f == NULL) { - info_tailcall(L, ar); + info_tailcall(ar); return status; } for (; *what; what++) { @@ -275,8 +276,11 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { static int precheck (const Proto *pt) { check(pt->maxstacksize <= MAXSTACK); + lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); + lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) || + (pt->is_vararg & VARARG_HASARG)); + check(pt->sizeupvalues <= pt->nups); check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); - lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize); check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); return 1; } @@ -389,8 +393,8 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) { } case OP_TFORLOOP: { check(c >= 1); /* at least one result (control variable) */ - checkreg(pt, a+3+c); /* space for results */ - if (reg >= a+3) last = pc; /* affect all regs above its call base */ + checkreg(pt, a+2+c); /* space for results */ + if (reg >= a+2) last = pc; /* affect all regs above its base */ break; } case OP_FORLOOP: @@ -440,7 +444,8 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) { break; } case OP_VARARG: { - check(pt->is_vararg & NEWSTYLEVARARG); + check((pt->is_vararg & VARARG_ISVARARG) && + !(pt->is_vararg & VARARG_NEEDSARG)); b--; if (b == LUA_MULTRET) check(checkopenop(pt, pc)); checkreg(pt, a+b-1); @@ -546,7 +551,8 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { const char *name = NULL; const char *t = luaT_typenames[ttype(o)]; const char *kind = (isinstack(L->ci, o)) ? - getobjname(L, L->ci, o - L->base, &name) : NULL; + getobjname(L, L->ci, cast(int, o - L->base), &name) : + NULL; if (kind) luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", op, kind, name, t); @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.23 2005/05/03 19:01:17 roberto Exp $ +** $Id: ldo.c,v 2.33 2005/09/09 18:16:28 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -48,7 +48,7 @@ struct lua_longjmp { }; -static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { +void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { switch (errcode) { case LUA_ERRMEM: { setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); @@ -68,14 +68,41 @@ static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { } +static void restore_stack_limit (lua_State *L) { + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ + int inuse = cast(int, L->ci - L->base_ci); + if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ + luaD_reallocCI(L, LUAI_MAXCALLS); + } +} + + +static void resetstack (lua_State *L, int status) { + L->ci = L->base_ci; + L->base = L->ci->base; + luaF_close(L, L->base); /* close eventual pending closures */ + luaD_seterrorobj(L, status, L->base); + L->nCcalls = 0; + L->allowhook = 1; + restore_stack_limit(L); + L->errfunc = 0; + L->errorJmp = NULL; +} + + void luaD_throw (lua_State *L, int errcode) { if (L->errorJmp) { L->errorJmp->status = errcode; LUAI_THROW(L, L->errorJmp); } else { - L->status = errcode; - if (G(L)->panic) G(L)->panic(L); + L->status = cast(lu_byte, errcode); + if (G(L)->panic) { + resetstack(L, errcode); + lua_unlock(L); + G(L)->panic(L); + } exit(EXIT_FAILURE); } } @@ -93,16 +120,6 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { return lj.status; } - -static void restore_stack_limit (lua_State *L) { - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ - int inuse = (L->ci - L->base_ci); - if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ - luaD_reallocCI(L, LUAI_MAXCALLS); - } -} - /* }====================================================== */ @@ -116,9 +133,8 @@ static void correctstack (lua_State *L, TValue *oldstack) { ci->top = (ci->top - oldstack) + L->stack; ci->base = (ci->base - oldstack) + L->stack; ci->func = (ci->func - oldstack) + L->stack; - lua_assert(lua_checkpc(L, ci)); } - L->base = L->ci->base; + L->base = (L->base - oldstack) + L->stack; } @@ -173,7 +189,7 @@ void luaD_callhook (lua_State *L, int event, int line) { if (event == LUA_HOOKTAILRET) ar.i_ci = 0; /* tail call; no debug information about it */ else - ar.i_ci = L->ci - L->base_ci; + ar.i_ci = cast(int, L->ci - L->base_ci); luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ L->ci->top = L->top + LUA_MINSTACK; lua_assert(L->ci->top <= L->stack_last); @@ -189,18 +205,17 @@ void luaD_callhook (lua_State *L, int event, int line) { } -static StkId adjust_varargs (lua_State *L, int nfixargs, int actual, - int style) { +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { int i; + int nfixargs = p->numparams; Table *htab = NULL; StkId base, fixed; - if (actual < nfixargs) { - for (; actual < nfixargs; ++actual) - setnilvalue(L->top++); - } -#if LUA_COMPAT_VARARG - if (style != NEWSTYLEVARARG) { /* compatibility with old-style vararg */ + for (; actual < nfixargs; ++actual) + setnilvalue(L->top++); +#if defined(LUA_COMPAT_VARARG) + if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ int nvar = actual - nfixargs; /* number of extra arguments */ + lua_assert(p->is_vararg & VARARG_HASARG); luaC_checkGC(L); htab = luaH_new(L, nvar, 1); /* create `arg' table */ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ @@ -259,16 +274,14 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { CallInfo *ci; StkId st, base; Proto *p = cl->p; - if (p->is_vararg) { /* varargs? */ - int nargs = L->top - restorestack(L, funcr) - 1; - luaD_checkstack(L, p->maxstacksize + nargs); - base = adjust_varargs(L, p->numparams, nargs, p->is_vararg); - func = restorestack(L, funcr); - } - else { - luaD_checkstack(L, p->maxstacksize); - func = restorestack(L, funcr); + luaD_checkstack(L, p->maxstacksize); + func = restorestack(L, funcr); + if (!p->is_vararg) /* no varargs? */ base = func + 1; + else { /* vararg function */ + int nargs = cast(int, L->top - func) - 1; + base = adjust_varargs(L, p, nargs); + func = restorestack(L, funcr); /* previous call may change the stack */ } ci = inc_ci(L); /* now `enter' new function */ ci->func = func; @@ -281,6 +294,11 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { for (st = L->top; st < ci->top; st++) setnilvalue(st); L->top = ci->top; + if (L->hookmask & LUA_MASKCALL) { + L->savedpc++; /* hooks assume 'pc' is already incremented */ + luaD_callhook(L, LUA_HOOKCALL, -1); + L->savedpc--; /* correct 'pc' */ + } return PCRLUA; } else { /* if is a C function, call it */ @@ -292,13 +310,14 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { L->base = ci->base = ci->func + 1; ci->top = L->top + LUA_MINSTACK; lua_assert(ci->top <= L->stack_last); + ci->nresults = nresults; if (L->hookmask & LUA_MASKCALL) luaD_callhook(L, LUA_HOOKCALL, -1); lua_unlock(L); n = (*curr_func(L)->c.f)(L); /* do the actual call */ lua_lock(L); if (n >= 0) { /* no yielding? */ - luaD_poscall(L, nresults, L->top - n); + luaD_poscall(L, L->top - n); return PCRC; } else { @@ -320,22 +339,24 @@ static StkId callrethooks (lua_State *L, StkId firstResult) { } -void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { +int luaD_poscall (lua_State *L, StkId firstResult) { StkId res; + int wanted, i; + CallInfo *ci; if (L->hookmask & LUA_MASKRET) firstResult = callrethooks(L, firstResult); - res = L->ci->func; /* res == final position of 1st result */ - L->ci--; - L->base = L->ci->base; /* restore base */ - L->savedpc = L->ci->savedpc; /* restore savedpc */ + ci = L->ci--; + res = ci->func; /* res == final position of 1st result */ + wanted = ci->nresults; + L->base = (ci - 1)->base; /* restore base */ + L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ /* move results to correct place */ - while (wanted != 0 && firstResult < L->top) { + for (i = wanted; i != 0 && firstResult < L->top; i--) setobjs2s(L, res++, firstResult++); - wanted--; - } - while (wanted-- > 0) + while (i-- > 0) setnilvalue(res++); L->top = res; + return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ } @@ -352,38 +373,34 @@ void luaD_call (lua_State *L, StkId func, int nResults) { else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ } - if (luaD_precall(L, func, nResults) == PCRLUA) { /* is a Lua function? */ - StkId firstResult = luaV_execute(L, 1); /* call it */ - luaD_poscall(L, nResults, firstResult); - } + if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ + luaV_execute(L, 1); /* call it */ L->nCcalls--; luaC_checkGC(L); } static void resume (lua_State *L, void *ud) { - StkId firstResult; - int nargs = *cast(int *, ud); + StkId firstArg = cast(StkId, ud); CallInfo *ci = L->ci; - if (L->status != LUA_YIELD) { - lua_assert(ci == L->base_ci && nargs < L->top - L->base); - luaD_precall(L, L->top - (nargs + 1), LUA_MULTRET); /* start coroutine */ + if (L->status != LUA_YIELD) { /* start coroutine */ + lua_assert(ci == L->base_ci && firstArg > L->base); + if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) + return; } else { /* resuming from previous yield */ if (!f_isLua(ci)) { /* `common' yield? */ /* finish interrupted execution of `OP_CALL' */ - int nresults = ci->nresults; lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); - luaD_poscall(L, nresults, L->top - nargs); /* complete it */ - if (nresults >= 0) L->top = L->ci->top; - } /* else yielded inside a hook: just continue its execution */ + if (luaD_poscall(L, firstArg)) /* complete it... */ + L->top = L->ci->top; /* and correct top if not multiple results */ + } + else /* yielded inside a hook: just continue its execution */ + L->base = L->ci->base; } L->status = 0; - firstResult = luaV_execute(L, L->ci - L->base_ci); - if (firstResult != NULL) { /* return? */ - luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ - } + luaV_execute(L, cast(int, L->ci - L->base_ci)); } @@ -399,17 +416,18 @@ static int resume_error (lua_State *L, const char *msg) { LUA_API int lua_resume (lua_State *L, int nargs) { int status; lua_lock(L); - lua_assert(L->errfunc == 0 && L->nCcalls == 0); if (L->status != LUA_YIELD) { if (L->status != 0) return resume_error(L, "cannot resume dead coroutine"); else if (L->ci != L->base_ci) return resume_error(L, "cannot resume non-suspended coroutine"); } - status = luaD_rawrunprotected(L, resume, &nargs); + luai_userstateresume(L, nargs); + lua_assert(L->errfunc == 0 && L->nCcalls == 0); + status = luaD_rawrunprotected(L, resume, L->top - nargs); if (status != 0) { /* error? */ - L->status = status; /* mark thread as `dead' */ - seterrorobj(L, status, L->top); + L->status = cast(lu_byte, status); /* mark thread as `dead' */ + luaD_seterrorobj(L, status, L->top); } else status = L->status; @@ -419,19 +437,11 @@ LUA_API int lua_resume (lua_State *L, int nargs) { LUA_API int lua_yield (lua_State *L, int nresults) { - CallInfo *ci; + luai_userstateyield(L, nresults); lua_lock(L); - ci = L->ci; if (L->nCcalls > 0) luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); - if (!f_isLua(ci)) { /* usual yield */ - if (L->top - nresults > L->base) { /* is there garbage in the stack? */ - int i; - for (i=0; i<nresults; i++) /* move down results */ - setobjs2s(L, L->base + i, L->top - nresults + i); - L->top = L->base + nresults; - } - } /* else it's an yield inside a hook: nothing to do */ + L->base = L->top - nresults; /* protect stack slots below */ L->status = LUA_YIELD; lua_unlock(L); return -1; @@ -441,7 +451,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t old_top, ptrdiff_t ef) { int status; - int oldnCcalls = L->nCcalls; + unsigned short oldnCcalls = L->nCcalls; ptrdiff_t old_ci = saveci(L, L->ci); lu_byte old_allowhooks = L->allowhook; ptrdiff_t old_errfunc = L->errfunc; @@ -450,7 +460,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, if (status != 0) { /* an error occurred? */ StkId oldtop = restorestack(L, old_top); luaF_close(L, oldtop); /* close eventual pending closures */ - seterrorobj(L, status, oldtop); + luaD_seterrorobj(L, status, oldtop); L->nCcalls = oldnCcalls; L->ci = restoreci(L, old_ci); L->base = L->ci->base; @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.4 2005/04/25 19:24:10 roberto Exp $ +** $Id: ldo.h,v 2.7 2005/08/24 16:15:49 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -13,16 +13,6 @@ #include "lzio.h" -/* -** macro to control inclusion of some hard tests on stack reallocation -*/ -#ifndef HARDSTACKTESTS -#define condhardstacktests(x) ((void)0) -#else -#define condhardstacktests(x) x -#endif - - #define luaD_checkstack(L,n) \ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ luaD_growstack(L, n); \ @@ -53,7 +43,7 @@ LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC void luaD_poscall (lua_State *L, int wanted, StkId firstResult); +LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); LUAI_FUNC void luaD_growstack (lua_State *L, int n); @@ -61,6 +51,7 @@ LUAI_FUNC void luaD_growstack (lua_State *L, int n); LUAI_FUNC void luaD_throw (lua_State *L, int errcode); LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); +LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); #endif diff --git a/src/ldump.c b/src/ldump.c index 0c9f00d1..e580047b 100644 --- a/src/ldump.c +++ b/src/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 1.10 2005/05/12 00:26:50 lhf Exp $ +** $Id: ldump.c,v 1.12 2005/06/08 14:40:44 lhf Exp $ ** save pre-compiled Lua chunks ** See Copyright Notice in lua.h */ @@ -16,17 +16,20 @@ #include "lstate.h" #include "lundump.h" -#define DumpVector(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpLiteral(s,D) DumpBlock("" s,(sizeof(s))-1,D) - typedef struct { lua_State* L; - lua_Chunkwriter writer; + lua_Writer writer; void* data; int strip; int status; } DumpState; +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) +#define DumpLines(f,D) DumpVector(f->lineinfo,f->sizelineinfo,sizeof(int),D) +#define DumpLiteral(s,D) DumpBlock("" s,(sizeof(s))-1,D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) +#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) + static void DumpBlock(const void* b, size_t size, DumpState* D) { if (D->status==0) @@ -37,45 +40,43 @@ static void DumpBlock(const void* b, size_t size, DumpState* D) } } -static void DumpByte(int y, DumpState* D) +static void DumpChar(int y, DumpState* D) { char x=(char)y; - DumpBlock(&x,sizeof(x),D); + DumpVar(x,D); } static void DumpInt(int x, DumpState* D) { - DumpBlock(&x,sizeof(x),D); + DumpVar(x,D); } -static void DumpSize(size_t x, DumpState* D) +static void DumpNumber(lua_Number x, DumpState* D) { - DumpBlock(&x,sizeof(x),D); + DumpVar(x,D); } -static void DumpNumber(lua_Number x, DumpState* D) +static void DumpVector(const void* b, int n, size_t size, DumpState* D) { - DumpBlock(&x,sizeof(x),D); + DumpInt(n,D); + DumpMem(b,n,size,D); } static void DumpString(const TString* s, DumpState* D) { if (s==NULL || getstr(s)==NULL) - DumpSize(0,D); + { + size_t size=0; + DumpVar(size,D); + } else { size_t size=s->tsv.len+1; /* include trailing '\0' */ - DumpSize(size,D); + DumpVar(size,D); DumpBlock(getstr(s),size,D); } } -static void DumpCode(const Proto* f, DumpState* D) -{ - DumpInt(f->sizecode,D); - DumpVector(f->code,f->sizecode,sizeof(*f->code),D); -} - static void DumpLocals(const Proto* f, DumpState* D) { int i,n=f->sizelocvars; @@ -88,12 +89,6 @@ static void DumpLocals(const Proto* f, DumpState* D) } } -static void DumpLines(const Proto* f, DumpState* D) -{ - DumpInt(f->sizelineinfo,D); - DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D); -} - static void DumpUpvalues(const Proto* f, DumpState* D) { int i,n=f->sizeupvalues; @@ -105,18 +100,18 @@ static void DumpFunction(const Proto* f, const TString* p, DumpState* D); static void DumpConstants(const Proto* f, DumpState* D) { - int i,n; - DumpInt(n=f->sizek,D); + int i,n=f->sizek; + DumpInt(n,D); for (i=0; i<n; i++) { const TValue* o=&f->k[i]; - DumpByte(ttype(o),D); + DumpChar(ttype(o),D); switch (ttype(o)) { case LUA_TNIL: break; case LUA_TBOOLEAN: - DumpByte(bvalue(o),D); + DumpChar(bvalue(o),D); break; case LUA_TNUMBER: DumpNumber(nvalue(o),D); @@ -129,7 +124,8 @@ static void DumpConstants(const Proto* f, DumpState* D) break; } } - DumpInt(n=f->sizep,D); + n=f->sizep; + DumpInt(n,D); for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D); } @@ -138,10 +134,10 @@ static void DumpFunction(const Proto* f, const TString* p, DumpState* D) DumpString((f->source==p) ? NULL : f->source,D); DumpInt(f->linedefined,D); DumpInt(f->lastlinedefined,D); - DumpByte(f->nups,D); - DumpByte(f->numparams,D); - DumpByte(f->is_vararg,D); - DumpByte(f->maxstacksize,D); + DumpChar(f->nups,D); + DumpChar(f->numparams,D); + DumpChar(f->is_vararg,D); + DumpChar(f->maxstacksize,D); if (D->strip) DumpInt(0,D); else DumpLines(f,D); if (D->strip) DumpInt(0,D); else DumpLocals(f,D); if (D->strip) DumpInt(0,D); else DumpUpvalues(f,D); @@ -151,20 +147,15 @@ static void DumpFunction(const Proto* f, const TString* p, DumpState* D) static void DumpHeader(DumpState* D) { - DumpLiteral(LUA_SIGNATURE,D); - DumpByte(VERSION,D); - DumpByte(luaU_endianness(),D); - DumpByte(sizeof(int),D); - DumpByte(sizeof(size_t),D); - DumpByte(sizeof(Instruction),D); - DumpByte(sizeof(lua_Number),D); - DumpNumber(TEST_NUMBER,D); + char h[LUAC_HEADERSIZE]; + luaU_header(h); + DumpBlock(h,LUAC_HEADERSIZE,D); } /* ** dump Lua function as precompiled chunk */ -int luaU_dump (lua_State* L, const Proto* f, lua_Chunkwriter w, void* data, int strip) +int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) { DumpState D; D.L=L; @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.32 2005/05/05 15:34:03 roberto Exp $ +** $Id: lgc.c,v 2.36 2005/08/24 17:06:36 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -240,8 +240,8 @@ static void traverseclosure (global_State *g, Closure *cl) { static void checkstacksizes (lua_State *L, StkId max) { - int ci_used = L->ci - L->base_ci; /* number of `ci' in use */ - int s_used = max - L->stack; /* part of stack in use */ + int ci_used = cast(int, L->ci - L->base_ci); /* number of `ci' in use */ + int s_used = cast(int, max - L->stack); /* part of stack in use */ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ return; /* do not touch the stacks */ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) @@ -287,7 +287,6 @@ static l_mem propagatemark (global_State *g) { black2gray(o); /* keep it gray */ return sizeof(Table) + sizeof(TValue) * h->sizearray + sizeof(Node) * sizenode(h); - break; } case LUA_TFUNCTION: { Closure *cl = gco2cl(o); @@ -295,7 +294,6 @@ static l_mem propagatemark (global_State *g) { traverseclosure(g, cl); return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : sizeLclosure(cl->l.nupvalues); - break; } case LUA_TTHREAD: { lua_State *th = gco2th(o); @@ -306,7 +304,6 @@ static l_mem propagatemark (global_State *g) { traversestack(g, th); return sizeof(lua_State) + sizeof(TValue) * th->stacksize + sizeof(CallInfo) * th->size_ci; - break; } case LUA_TPROTO: { Proto *p = gco2p(o); @@ -318,7 +315,6 @@ static l_mem propagatemark (global_State *g) { sizeof(int) * p->sizelineinfo + sizeof(LocVar) * p->sizelocvars + sizeof(TString *) * p->sizeupvalues; - break; } default: lua_assert(0); return 0; } @@ -528,10 +524,10 @@ static void remarkupvals (global_State *g) { static void atomic (lua_State *L) { global_State *g = G(L); size_t udsize; /* total size of userdata to be finalized */ - /* remark objects cautch by write barrier */ - propagateall(g); /* remark occasional upvalues of (maybe) dead threads */ remarkupvals(g); + /* traverse objects cautch by write barrier and by 'remarkupvals' */ + propagateall(g); /* remark weak tables */ g->gray = g->weak; g->weak = NULL; @@ -673,12 +669,13 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { } -void luaC_barrierback (lua_State *L, GCObject *o) { +void luaC_barrierback (lua_State *L, Table *t) { global_State *g = G(L); + GCObject *o = obj2gco(t); lua_assert(isblack(o) && !isdead(g, o)); lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); black2gray(o); /* make table gray (again) */ - gco2h(o)->gclist = g->grayagain; + t->gclist = g->grayagain; g->grayagain = o; } @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.13 2005/04/25 19:24:10 roberto Exp $ +** $Id: lgc.h,v 2.15 2005/08/24 16:15:49 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -77,23 +77,24 @@ #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) -#define luaC_checkGC(L) { if (G(L)->totalbytes >= G(L)->GCthreshold) \ +#define luaC_checkGC(L) { \ + condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ + if (G(L)->totalbytes >= G(L)->GCthreshold) \ luaC_step(L); } #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ luaC_barrierf(L,obj2gco(p),gcvalue(v)); } -#define luaC_barriert(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierback(L,obj2gco(p)); } +#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ + luaC_barrierback(L,t); } #define luaC_objbarrier(L,p,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ luaC_barrierf(L,obj2gco(p),obj2gco(o)); } -#define luaC_objbarriert(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrierback(L,obj2gco(p)); } +#define luaC_objbarriert(L,t,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); LUAI_FUNC void luaC_callGCTM (lua_State *L); @@ -103,7 +104,7 @@ LUAI_FUNC void luaC_fullgc (lua_State *L); LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); #endif diff --git a/src/linit.c b/src/linit.c index afcd338b..d30ff1e3 100644 --- a/src/linit.c +++ b/src/linit.c @@ -1,5 +1,5 @@ /* -** $Id: linit.c,v 1.11 2005/04/13 17:24:20 roberto Exp $ +** $Id: linit.c,v 1.13 2005/08/26 17:36:32 roberto Exp $ ** Initialization of libraries for lua.c ** See Copyright Notice in lua.h */ @@ -14,7 +14,7 @@ #include "lauxlib.h" -static const luaL_reg lualibs[] = { +static const luaL_Reg lualibs[] = { {"", luaopen_base}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, @@ -22,13 +22,13 @@ static const luaL_reg lualibs[] = { {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_DBLIBNAME, luaopen_debug}, - {LUA_LOADLIBNAME, luaopen_loadlib}, + {LUA_LOADLIBNAME, luaopen_package}, {NULL, NULL} }; LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_reg *lib = lualibs; + const luaL_Reg *lib = lualibs; for (; lib->func; lib++) { lua_pushcfunction(L, lib->func); lua_pushstring(L, lib->name); diff --git a/src/liolib.c b/src/liolib.c index 1dba7eff..a7f8743f 100644 --- a/src/liolib.c +++ b/src/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.60 2005/05/16 21:19:00 roberto Exp $ +** $Id: liolib.c,v 2.67 2005/08/26 17:36:32 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -20,8 +20,8 @@ -#define IO_INPUT 1 -#define IO_OUTPUT 2 +#define IO_INPUT 1 +#define IO_OUTPUT 2 static const char *const fnames[] = {"input", "output"}; @@ -50,17 +50,17 @@ static void fileerror (lua_State *L, int arg, const char *filename) { } -static FILE **topfile (lua_State *L) { - FILE **f = (FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE); - if (f == NULL) luaL_argerror(L, 1, "bad file"); - return f; -} +#define topfile(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) static int io_type (lua_State *L) { - FILE **f = (FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE); - if (f == NULL) lua_pushnil(L); - else if (*f == NULL) + void *ud; + luaL_checkany(L, 1); + ud = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); + if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + lua_pushnil(L); /* not a file */ + else if (*((FILE **)ud) == NULL) lua_pushliteral(L, "closed file"); else lua_pushliteral(L, "file"); @@ -91,29 +91,45 @@ static FILE **newfile (lua_State *L) { } +/* +** this function has a separated environment, which defines the +** correct __close for 'popen' files +*/ +static int io_pclose (lua_State *L) { + FILE **p = topfile(L); + int ok = lua_pclose(L, *p); + if (ok) *p = NULL; + return pushresult(L, ok, NULL); +} + + +static int io_fclose (lua_State *L) { + FILE **p = topfile(L); + int ok = (fclose(*p) == 0); + if (ok) *p = NULL; + return pushresult(L, ok, NULL); +} + + static int aux_close (lua_State *L) { - FILE *f = tofile(L); - if (f == stdin || f == stdout || f == stderr) - return 0; /* file cannot be closed */ - else { - int ok = (fclose(f) == 0); - if (ok) - *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */ - return ok; - } + lua_getfenv(L, 1); + lua_getfield(L, -1, "__close"); + return (lua_tocfunction(L, -1))(L); } static int io_close (lua_State *L) { if (lua_isnone(L, 1)) lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); - return pushresult(L, aux_close(L), NULL); + tofile(L); /* make sure argument is a file */ + return aux_close(L); } static int io_gc (lua_State *L) { - FILE **f = topfile(L); - if (*f != NULL) /* ignore closed files */ + FILE *f = *topfile(L); + /* ignore closed files and standard files */ + if (f != NULL && f != stdin && f != stdout && f != stderr) aux_close(L); return 0; } @@ -138,6 +154,15 @@ static int io_open (lua_State *L) { } +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = lua_popen(L, filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + static int io_tmpfile (lua_State *L) { FILE **pf = newfile(L); *pf = tmpfile(); @@ -148,7 +173,6 @@ static int io_tmpfile (lua_State *L) { static FILE *getiofile (lua_State *L, int findex) { FILE *f; lua_rawgeti(L, LUA_ENVIRONINDEX, findex); - lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE)); f = *(FILE **)lua_touserdata(L, -1); if (f == NULL) luaL_error(L, "standard %s file is closed", fnames[findex - 1]); @@ -169,7 +193,6 @@ static int g_iofile (lua_State *L, int f, const char *mode) { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } - lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE)); lua_rawseti(L, LUA_ENVIRONINDEX, f); } /* return current value */ @@ -352,7 +375,7 @@ static int io_readline (lua_State *L) { luaL_error(L, "file is already closed"); sucess = read_line(L, f); if (ferror(f)) - luaL_error(L, "%s", strerror(errno)); + return luaL_error(L, "%s", strerror(errno)); if (sucess) return 1; else { /* EOF */ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ @@ -400,9 +423,8 @@ static int f_seek (lua_State *L) { static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; static const char *const modenames[] = {"set", "cur", "end", NULL}; FILE *f = tofile(L); - int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames); + int op = luaL_checkoption(L, 2, "cur", modenames); lua_Integer offset = luaL_optinteger(L, 3, 0); - luaL_argcheck(L, op != -1, 2, "invalid mode"); op = fseek(f, offset, mode[op]); if (op) return pushresult(L, 0, NULL); /* error */ @@ -417,9 +439,10 @@ static int f_setvbuf (lua_State *L) { static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; static const char *const modenames[] = {"no", "full", "line", NULL}; FILE *f = tofile(L); - int op = luaL_findstring(luaL_checkstring(L, 2), modenames); - luaL_argcheck(L, op != -1, 2, "invalid mode"); - return pushresult(L, setvbuf(f, NULL, mode[op], 0) == 0, NULL); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, BUFSIZ); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); } @@ -434,13 +457,14 @@ static int f_flush (lua_State *L) { } -static const luaL_reg iolib[] = { - {"input", io_input}, - {"output", io_output}, - {"lines", io_lines}, +static const luaL_Reg iolib[] = { {"close", io_close}, {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, {"read", io_read}, {"tmpfile", io_tmpfile}, {"type", io_type}, @@ -449,14 +473,14 @@ static const luaL_reg iolib[] = { }; -static const luaL_reg flib[] = { +static const luaL_Reg flib[] = { + {"close", io_close}, {"flush", f_flush}, - {"read", f_read}, {"lines", f_lines}, + {"read", f_read}, {"seek", f_seek}, {"setvbuf", f_setvbuf}, {"write", f_write}, - {"close", io_close}, {"__gc", io_gc}, {"__tostring", io_tostring}, {NULL, NULL} @@ -467,34 +491,41 @@ static void createmeta (lua_State *L) { luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ lua_pushvalue(L, -1); /* push metatable */ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_openlib(L, NULL, flib, 0); /* file methods */ + luaL_register(L, NULL, flib); /* file methods */ } -static void createupval (lua_State *L) { - lua_newtable(L); - /* create (and set) default files */ - *newfile(L) = stdin; - lua_rawseti(L, -2, IO_INPUT); - *newfile(L) = stdout; - lua_rawseti(L, -2, IO_OUTPUT); +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { + *newfile(L) = f; + if (k > 0) { + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_ENVIRONINDEX, k); + } + lua_setfield(L, -2, fname); } - LUALIB_API int luaopen_io (lua_State *L) { createmeta(L); - createupval(L); - lua_pushvalue(L, -1); + /* create new (private) environment */ + lua_newtable(L); lua_replace(L, LUA_ENVIRONINDEX); - luaL_openlib(L, LUA_IOLIBNAME, iolib, 0); - /* put predefined file handles into `io' table */ - lua_rawgeti(L, -2, IO_INPUT); /* get current input from upval */ - lua_setfield(L, -2, "stdin"); /* io.stdin = upval[IO_INPUT] */ - lua_rawgeti(L, -2, IO_OUTPUT); /* get current output from upval */ - lua_setfield(L, -2, "stdout"); /* io.stdout = upval[IO_OUTPUT] */ - *newfile(L) = stderr; - lua_setfield(L, -2, "stderr"); /* io.stderr = newfile(stderr) */ + /* open library */ + luaL_register(L, LUA_IOLIBNAME, iolib); + /* create (and set) default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, 0, "stderr"); + /* create environment for 'popen' */ + lua_getfield(L, -1, "popen"); + lua_newtable(L); + lua_pushcfunction(L, io_pclose); + lua_setfield(L, -2, "__close"); + lua_setfenv(L, -2); + lua_pop(L, 1); /* pop 'popen' */ + /* set default close function */ + lua_pushcfunction(L, io_fclose); + lua_setfield(L, LUA_ENVIRONINDEX, "__close"); return 1; } @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.54 2005/04/25 19:24:10 roberto Exp $ +** $Id: llex.h,v 1.55 2005/06/06 13:30:25 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -37,7 +37,7 @@ enum RESERVED { /* array with token `names' */ -extern const char *const luaX_tokens []; +LUAI_DATA const char *const luaX_tokens []; typedef union { diff --git a/src/llimits.h b/src/llimits.h index 7a536a16..68c28c8c 100644 --- a/src/llimits.h +++ b/src/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.65 2005/03/09 16:28:07 roberto Exp $ +** $Id: llimits.h,v 1.67 2005/08/24 16:15:49 roberto Exp $ ** Limits, basic types, and some other `installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -93,4 +93,23 @@ typedef lu_int32 Instruction; #endif +#ifndef lua_lock +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +#ifndef luai_threadyield +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#ifndef HARDSTACKTESTS +#define condhardstacktests(x) ((void)0) +#else +#define condhardstacktests(x) x +#endif + #endif diff --git a/src/lmathlib.c b/src/lmathlib.c index bba99b0d..d181a731 100644 --- a/src/lmathlib.c +++ b/src/lmathlib.c @@ -1,5 +1,5 @@ /* -** $Id: lmathlib.c,v 1.63 2005/03/04 18:57:03 roberto Exp $ +** $Id: lmathlib.c,v 1.67 2005/08/26 17:36:32 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ @@ -88,7 +88,7 @@ static int math_floor (lua_State *L) { return 1; } -static int math_mod (lua_State *L) { +static int math_fmod (lua_State *L) { lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } @@ -212,35 +212,35 @@ static int math_randomseed (lua_State *L) { } -static const luaL_reg mathlib[] = { +static const luaL_Reg mathlib[] = { {"abs", math_abs}, - {"sin", math_sin}, - {"sinh", math_sinh}, - {"cos", math_cos}, - {"cosh", math_cosh}, - {"tan", math_tan}, - {"tanh", math_tanh}, - {"asin", math_asin}, {"acos", math_acos}, - {"atan", math_atan}, + {"asin", math_asin}, {"atan2", math_atan2}, + {"atan", math_atan}, {"ceil", math_ceil}, + {"cosh", math_cosh}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, {"floor", math_floor}, - {"mod", math_mod}, - {"modf", math_modf}, + {"fmod", math_fmod}, {"frexp", math_frexp}, {"ldexp", math_ldexp}, - {"sqrt", math_sqrt}, - {"min", math_min}, - {"max", math_max}, - {"log", math_log}, {"log10", math_log10}, - {"exp", math_exp}, - {"deg", math_deg}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, {"pow", math_pow}, {"rad", math_rad}, {"random", math_random}, {"randomseed", math_randomseed}, + {"sinh", math_sinh}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tanh", math_tanh}, + {"tan", math_tan}, {NULL, NULL} }; @@ -249,11 +249,15 @@ static const luaL_reg mathlib[] = { ** Open math library */ LUALIB_API int luaopen_math (lua_State *L) { - luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0); + luaL_register(L, LUA_MATHLIBNAME, mathlib); lua_pushnumber(L, PI); lua_setfield(L, -2, "pi"); lua_pushnumber(L, HUGE_VAL); lua_setfield(L, -2, "huge"); +#if defined(LUA_COMPAT_MOD) + lua_getfield(L, -1, "fmod"); + lua_setfield(L, -2, "mod"); +#endif return 1; } diff --git a/src/loadlib.c b/src/loadlib.c index 1ae9ab57..767fdb8e 100644 --- a/src/loadlib.c +++ b/src/loadlib.c @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.28 2005/05/17 19:49:15 roberto Exp $ +** $Id: loadlib.c,v 1.44 2005/09/06 17:20:25 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** @@ -38,6 +38,13 @@ #define LIB_FAIL "open" +/* error codes for ll_loadfunc */ +#define ERRLIB 1 +#define ERRFUNC 2 + +#define setprogdir(L) ((void)0) + + static void ll_unloadlib (void *lib); static void *ll_load (lua_State *L, const char *path); static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); @@ -88,6 +95,21 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { #include <windows.h> +#undef setprogdir + +void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileName(NULL, buff, nsize); + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + *lb = '\0'; + luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); + lua_remove(L, -2); /* remove original string */ +} + + static void pusherror (lua_State *L) { int error = GetLastError(); char buffer[128]; @@ -267,96 +289,148 @@ static void **ll_register (lua_State *L, const char *path) { */ static int gctm (lua_State *L) { void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); - if (lib) { - if (*lib) ll_unloadlib(*lib); - *lib = NULL; /* mark library as closed */ - } + if (*lib) ll_unloadlib(*lib); + *lib = NULL; /* mark library as closed */ return 0; } static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { - const char *reason; void **reg = ll_register(L, path); if (*reg == NULL) *reg = ll_load(L, path); if (*reg == NULL) - reason = LIB_FAIL; + return ERRLIB; /* unable to load library */ else { lua_CFunction f = ll_sym(L, *reg, sym); - if (f) { - lua_pushcfunction(L, f); - return 1; /* return function */ - } - reason = "init"; + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); + return 0; /* return function */ } - lua_pushnil(L); - lua_insert(L, -2); - lua_pushstring(L, reason); - return 3; /* return nil, ll_error, reason */ } static int ll_loadlib (lua_State *L) { const char *path = luaL_checkstring(L, 1); const char *init = luaL_checkstring(L, 2); - return ll_loadfunc(L, path, init); + int stat = ll_loadfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } } /* ** {====================================================== -** `require' and `module' functions +** 'require' function ** ======================================================= */ -static int loader_Lua (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP); - const char *path = NULL; -#if LUA_COMPAT_PATH - /* try first `LUA_PATH' for compatibility */ - lua_pushstring(L, "LUA_PATH"); - lua_rawget(L, LUA_GLOBALSINDEX); +static int readable (const char *filename) { + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; +} + + +static const char *pushnexttemplate (lua_State *L, const char *path) { + const char *l; + while (*path == *LUA_PATHSEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATHSEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname) { + const char *path; + name = luaL_gsub(L, name, ".", LUA_DIRSEP); + lua_getfield(L, LUA_ENVIRONINDEX, pname); path = lua_tostring(L, -1); -#endif - if (!path) { - lua_pop(L, 1); - lua_getfield(L, LUA_ENVIRONINDEX, "path"); - path = lua_tostring(L, -1); - } if (path == NULL) - luaL_error(L, LUA_QL("package.path") " must be a string"); - fname = luaL_searchpath(L, fname, path); - if (fname == NULL) return 0; /* library not found in this path */ - if (luaL_loadfile(L, fname) != 0) - luaL_error(L, "error loading package " LUA_QS " (%s)", - name, lua_tostring(L, -1)); + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *filename; + filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pop(L, 2); /* remove path template and file name */ + } + return NULL; /* not found */ +} + + +static void loaderror (lua_State *L) { + luaL_error(L, "error loading module " LUA_QS " (%s)", + lua_tostring(L, 1), lua_tostring(L, -1)); +} + + +static int loader_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path"); + if (filename == NULL) return 0; /* library not found in this path */ + if (luaL_loadfile(L, filename) != 0) + loaderror(L); return 1; /* library loaded successfully */ } +static const char *mkfuncname (lua_State *L, const char *modname) { + const char *funcname; + const char *mark = strchr(modname, *LUA_IGMARK); + if (mark) modname = mark + 1; + funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); + funcname = lua_pushfstring(L, POF"%s", funcname); + lua_remove(L, -2); /* remove 'gsub' result */ + return funcname; +} + + static int loader_C (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP); - const char *path; const char *funcname; - lua_getfield(L, LUA_ENVIRONINDEX, "cpath"); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, LUA_QL("package.cpath") " must be a string"); - fname = luaL_searchpath(L, fname, path); - if (fname == NULL) return 0; /* library not found in this path */ - funcname = luaL_gsub(L, name, ".", LUA_OFSEP); - funcname = lua_pushfstring(L, "%s%s", POF, funcname); - if (ll_loadfunc(L, fname, funcname) != 1) - luaL_error(L, "error loading package " LUA_QS " (%s)", - name, lua_tostring(L, -2)); + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath"); + if (filename == NULL) return 0; /* library not found in this path */ + funcname = mkfuncname(L, name); + if (ll_loadfunc(L, filename, funcname) != 0) + loaderror(L); return 1; /* library loaded successfully */ } +static int loader_Croot (lua_State *L) { + const char *funcname; + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath"); + if (filename == NULL) return 0; /* root not found */ + funcname = mkfuncname(L, name); + if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { + if (stat == ERRFUNC) return 0; /* function not found */ + else + loaderror(L); /* real error */ + } + return 1; +} + + static int loader_preload (lua_State *L) { lua_getfield(L, LUA_ENVIRONINDEX, "preload"); if (!lua_istable(L, -1)) @@ -366,38 +440,58 @@ static int loader_preload (lua_State *L) { } +static const int sentinel = 0; + + static int ll_require (lua_State *L) { const char *name = luaL_checkstring(L, 1); int i; - lua_settop(L, 1); + lua_settop(L, 1); /* _LOADED table will be at index 2 */ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, 2, name); - if (lua_toboolean(L, -1)) /* is it there? */ - return 1; /* package is already loaded; return its result */ - /* else must load it; first mark it as loaded */ - lua_pushboolean(L, 1); - lua_setfield(L, 2, name); /* _LOADED[name] = true */ - /* iterate over available loaders */ + if (lua_toboolean(L, -1)) { /* is it there? */ + if (lua_touserdata(L, -1) == &sentinel) /* check loops */ + luaL_error(L, "loop or previous error loading module " LUA_QS, name); + return 1; /* package is already loaded */ + } + /* else must load it; iterate over available loaders */ lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); if (!lua_istable(L, -1)) luaL_error(L, LUA_QL("package.loaders") " must be a table"); - for (i=1;; i++) { + for (i=1; ; i++) { lua_rawgeti(L, -1, i); /* get a loader */ if (lua_isnil(L, -1)) - return luaL_error(L, "package " LUA_QS " not found", name); + luaL_error(L, "module " LUA_QS " not found", name); lua_pushstring(L, name); lua_call(L, 1, 1); /* call it */ - if (lua_isnil(L, -1)) lua_pop(L, 1); + if (lua_isnil(L, -1)) lua_pop(L, 1); /* did not found module */ else break; /* module loaded successfully */ } - lua_pushvalue(L, 1); /* pass name as argument to module */ + lua_pushlightuserdata(L, (void *)&sentinel); + lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ + lua_pushstring(L, name); /* pass name as argument to module */ lua_call(L, 1, 1); /* run loaded module */ if (!lua_isnil(L, -1)) /* non-nil return? */ - lua_setfield(L, 2, name); /* update _LOADED[name] with returned value */ - lua_getfield(L, 2, name); /* return _LOADED[name] */ + lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ + lua_getfield(L, 2, name); + if (lua_touserdata(L, -1) == &sentinel) { /* module did not set a value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* _LOADED[name] = true */ + } return 1; } +/* }====================================================== */ + + + +/* +** {====================================================== +** 'module' function +** ======================================================= +*/ + static void setfenv (lua_State *L) { lua_Debug ar; @@ -405,49 +499,72 @@ static void setfenv (lua_State *L) { lua_getinfo(L, "f", &ar); lua_pushvalue(L, -2); lua_setfenv(L, -2); + lua_pop(L, 1); +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } +} + + +static void modinit (lua_State *L, const char *modname) { + const char *dot; + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_M"); /* module._M = module */ + lua_pushstring(L, modname); + lua_setfield(L, -2, "_NAME"); + dot = strrchr(modname, '.'); /* look for last dot in module name */ + if (dot == NULL) dot = modname; + else dot++; + /* set _PACKAGE as package name (full module name minus last part) */ + lua_pushlstring(L, modname, dot - modname); + lua_setfield(L, -2, "_PACKAGE"); } static int ll_module (lua_State *L) { const char *modname = luaL_checkstring(L, 1); - const char *dot; - lua_settop(L, 1); + int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - /* try to find given table */ - luaL_getfield(L, LUA_GLOBALSINDEX, modname); - if (lua_isnil(L, -1)) { /* not found? */ + lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ + if (!lua_istable(L, -1)) { /* not found? */ lua_pop(L, 1); /* remove previous result */ - lua_newtable(L); /* create it */ - /* register it with given name */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, modname) != NULL) + return luaL_error(L, "name conflict for module " LUA_QS, modname); lua_pushvalue(L, -1); - luaL_setfield(L, LUA_GLOBALSINDEX, modname); + lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ } - else if (!lua_istable(L, -1)) - return luaL_error(L, "name conflict for module " LUA_QS, modname); /* check whether table already has a _NAME field */ lua_getfield(L, -1, "_NAME"); if (!lua_isnil(L, -1)) /* is table an initialized module? */ lua_pop(L, 1); else { /* no; initialize it */ lua_pop(L, 1); - lua_newtable(L); /* create new metatable */ - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setfield(L, -2, "__index"); /* mt.__index = _G */ - lua_setmetatable(L, -2); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_M"); /* module._M = module */ - lua_pushstring(L, modname); - lua_setfield(L, -2, "_NAME"); - dot = strrchr(modname, '.'); /* look for last dot in module name */ - if (dot == NULL) dot = modname; - else dot++; - /* set _PACKAGE as package name (full module name minus last part) */ - lua_pushlstring(L, modname, dot - modname); - lua_setfield(L, -2, "_PACKAGE"); + modinit(L, modname); } lua_pushvalue(L, -1); - lua_setfield(L, 2, modname); /* _LOADED[modname] = new table */ setfenv(L); + dooptions(L, loaded - 1); + return 0; +} + + +static int ll_seeall (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + if (!lua_getmetatable(L, 1)) { + lua_newtable(L); /* create new metatable */ + lua_pushvalue(L, -1); + lua_setmetatable(L, 1); + } + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ return 0; } @@ -455,28 +572,57 @@ static int ll_module (lua_State *L) { /* }====================================================== */ -static const luaL_reg ll_funcs[] = { - {"require", ll_require}, + +/* auxiliary mark (for internal use) */ +#define AUXMARK "\1" + +static void setpath (lua_State *L, const char *fieldname, const char *envname, + const char *def) { + const char *path = getenv(envname); + if (path == NULL) /* no environment variable? */ + lua_pushstring(L, def); /* use default */ + else { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, + LUA_PATHSEP AUXMARK LUA_PATHSEP); + luaL_gsub(L, path, AUXMARK, def); + lua_remove(L, -2); + } + setprogdir(L); + lua_setfield(L, -2, fieldname); +} + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"seeall", ll_seeall}, + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { {"module", ll_module}, + {"require", ll_require}, {NULL, NULL} }; static const lua_CFunction loaders[] = - {loader_preload, loader_C, loader_Lua, NULL}; + {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; -LUALIB_API int luaopen_loadlib (lua_State *L) { - const char *path; +LUALIB_API int luaopen_package (lua_State *L) { int i; /* create new type _LOADLIB */ luaL_newmetatable(L, "_LOADLIB"); lua_pushcfunction(L, gctm); lua_setfield(L, -2, "__gc"); /* create `package' table */ - lua_newtable(L); - lua_pushvalue(L, -1); - lua_setglobal(L, LUA_LOADLIBNAME); + luaL_register(L, LUA_LOADLIBNAME, pk_funcs); +#if defined(LUA_COMPAT_LOADLIB) + lua_getfield(L, -1, "loadlib"); + lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); +#endif lua_pushvalue(L, -1); lua_setfield(L, LUA_REGISTRYINDEX, "_PACKAGE"); lua_pushvalue(L, -1); @@ -488,33 +634,22 @@ LUALIB_API int luaopen_loadlib (lua_State *L) { lua_pushcfunction(L, loaders[i]); lua_rawseti(L, -2, i+1); } - /* put it in field `loaders' */ - lua_setfield(L, -2, "loaders"); - /* set field `path' */ - path = getenv(LUA_PATH); - if (path == NULL) path = LUA_PATH_DEFAULT; - lua_pushstring(L, path); - lua_setfield(L, -2, "path"); - /* set field `cpath' */ - path = getenv(LUA_CPATH); - if (path == NULL) path = LUA_CPATH_DEFAULT; - lua_pushstring(L, path); - lua_setfield(L, -2, "cpath"); + lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ + setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ + setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ + /* store config information */ + lua_pushstring(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" + LUA_EXECDIR "\n" LUA_IGMARK); + lua_setfield(L, -2, "config"); /* set field `loaded' */ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_setfield(L, -2, "loaded"); /* set field `preload' */ lua_newtable(L); lua_setfield(L, -2, "preload"); - /* create `loadlib' function */ - lua_pushcfunction(L, ll_loadlib); -#if LUA_COMPAT_LOADLIB - lua_pushvalue(L, -1); - lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); -#endif - lua_setfield(L, -2, "loadlib"); lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_openlib(L, NULL, ll_funcs, 0); /* open lib into global table */ - return 1; + luaL_register(L, NULL, ll_funcs); /* open lib into global table */ + lua_pop(L, 1); + return 1; /* return 'package' table */ } diff --git a/src/lobject.c b/src/lobject.c index 98b08351..9aa9760f 100644 --- a/src/lobject.c +++ b/src/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.13 2005/05/16 21:19:00 roberto Exp $ +** $Id: lobject.c,v 2.18 2005/08/01 04:22:23 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -75,7 +75,7 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) { case LUA_TNIL: return 1; case LUA_TNUMBER: - return luai_numeq(nvalue(t1), nvalue(t2)); + return luai_numeq(L, nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ case LUA_TLIGHTUSERDATA: @@ -89,11 +89,11 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) { int luaO_str2d (const char *s, lua_Number *result) { char *endptr; - lua_Number res = lua_str2number(s, &endptr); - if (endptr == s) return 0; /* no conversion */ + *result = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* conversion failed */ + if (*endptr == '\0') return 1; /* most common case */ while (isspace(cast(unsigned char, *endptr))) endptr++; if (*endptr != '\0') return 0; /* invalid trailing characters? */ - *result = res; return 1; } @@ -116,7 +116,9 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { incr_top(L); switch (*(e+1)) { case 's': { - pushstr(L, va_arg(argp, char *)); + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s); break; } case 'c': { @@ -159,7 +161,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { fmt = e+2; } pushstr(L, fmt); - luaV_concat(L, n+1, L->top - L->base - 1); + luaV_concat(L, n+1, cast(int, L->top - L->base) - 1); L->top -= n; return svalue(L->top - 1); } @@ -175,26 +177,26 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { } -void luaO_chunkid (char *out, const char *source, int bufflen) { +void luaO_chunkid (char *out, const char *source, size_t bufflen) { if (*source == '=') { strncpy(out, source+1, bufflen); /* remove first char */ out[bufflen-1] = '\0'; /* ensures null termination */ } else { /* out = "source", or "...source" */ if (*source == '@') { - int l; + size_t l; source++; /* skip the `@' */ bufflen -= sizeof(" '...' "); l = strlen(source); strcpy(out, ""); - if (l>bufflen) { + if (l > bufflen) { source += (l-bufflen); /* get last part of file name */ strcat(out, "..."); } strcat(out, source); } else { /* out = [string "string"] */ - int len = strcspn(source, "\n\r"); /* stop at first newline */ + size_t len = strcspn(source, "\n\r"); /* stop at first newline */ bufflen -= sizeof(" [string \"...\"] "); if (len > bufflen) len = bufflen; strcpy(out, "[string \""); diff --git a/src/lobject.h b/src/lobject.h index 4a77a539..1709fa3c 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.13 2005/05/05 20:47:02 roberto Exp $ +** $Id: lobject.h,v 2.17 2005/06/13 14:19:00 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -17,15 +17,17 @@ /* tags for values visible from Lua */ -#define NUM_TAGS LUA_TTHREAD +#define LAST_TAG LUA_TTHREAD + +#define NUM_TAGS (LAST_TAG+1) /* ** Extra tags for non-values */ -#define LUA_TPROTO (NUM_TAGS+1) -#define LUA_TUPVAL (NUM_TAGS+2) -#define LUA_TDEADKEY (NUM_TAGS+3) +#define LUA_TPROTO (LAST_TAG+1) +#define LUA_TUPVAL (LAST_TAG+2) +#define LUA_TDEADKEY (LAST_TAG+3) /* @@ -254,8 +256,10 @@ typedef struct Proto { } Proto; -/* mask for new-style vararg */ -#define NEWSTYLEVARARG 2 +/* masks for new-style vararg */ +#define VARARG_HASARG 1 +#define VARARG_ISVARARG 2 +#define VARARG_NEEDSARG 4 typedef struct LocVar { @@ -357,7 +361,7 @@ typedef struct Table { -extern const TValue luaO_nilobject; +LUAI_DATA const TValue luaO_nilobject; #define ceillog2(x) (luaO_log2((x)-1) + 1) @@ -369,7 +373,8 @@ LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaO_chunkid (char *out, const char *source, int len); +LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); #endif + diff --git a/src/lopcodes.c b/src/lopcodes.c index 46b30ba9..5e3bc5f7 100644 --- a/src/lopcodes.c +++ b/src/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.33 2005/05/04 20:42:28 roberto Exp $ +** $Id: lopcodes.c,v 1.35 2005/08/29 20:49:21 roberto Exp $ ** See Copyright Notice in lua.h */ @@ -36,13 +36,14 @@ const char *const luaP_opnames[NUM_OPCODES+1] = { "POW", "UNM", "NOT", - "SIZ", + "LEN", "CONCAT", "JMP", "EQ", "LT", "LE", "TEST", + "TESTSET", "CALL", "TAILCALL", "RETURN", @@ -81,13 +82,14 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_SIZ */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 0, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ diff --git a/src/lopcodes.h b/src/lopcodes.h index 77f60c00..b08b6798 100644 --- a/src/lopcodes.h +++ b/src/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.119 2005/05/04 20:42:28 roberto Exp $ +** $Id: lopcodes.h,v 1.122 2005/08/29 20:49:21 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -176,7 +176,7 @@ OP_MOD,/* A B C R(A) := RK(B) % RK(C) */ OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */ OP_UNM,/* A B R(A) := -R(B) */ OP_NOT,/* A B R(A) := not R(B) */ -OP_SIZ,/* A B R(A) := size of R(B) */ +OP_LEN,/* A B R(A) := length of R(B) */ OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ @@ -186,7 +186,8 @@ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ -OP_TEST,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ @@ -248,7 +249,7 @@ enum OpArgMask { OpArgK /* argument is a constant or register/constant */ }; -extern const lu_byte luaP_opmodes[NUM_OPCODES]; +LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) @@ -257,7 +258,7 @@ extern const lu_byte luaP_opmodes[NUM_OPCODES]; #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) -extern const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ +LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ /* number of list items to accumulate before a SETLIST instruction */ diff --git a/src/loslib.c b/src/loslib.c index 52532143..4cee7ba5 100644 --- a/src/loslib.c +++ b/src/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.9 2005/05/17 19:49:15 roberto Exp $ +** $Id: loslib.c,v 1.13 2005/09/09 18:22:46 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -93,6 +93,8 @@ static void setfield (lua_State *L, const char *key, int value) { } static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ lua_pushboolean(L, value); lua_setfield(L, -2, key); } @@ -197,9 +199,8 @@ static int io_setloc (lua_State *L) { static const char *const catnames[] = {"all", "collate", "ctype", "monetary", "numeric", "time", NULL}; const char *l = lua_tostring(L, 1); - int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames); + int op = luaL_checkoption(L, 2, "all", catnames); luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected"); - luaL_argcheck(L, op != -1, 2, "invalid option"); lua_pushstring(L, setlocale(cat[op], l)); return 1; } @@ -210,7 +211,7 @@ static int io_exit (lua_State *L) { return 0; /* to avoid warnings */ } -static const luaL_reg syslib[] = { +static const luaL_Reg syslib[] = { {"clock", io_clock}, {"date", io_date}, {"difftime", io_difftime}, @@ -230,7 +231,7 @@ static const luaL_reg syslib[] = { LUALIB_API int luaopen_os (lua_State *L) { - luaL_openlib(L, LUA_OSLIBNAME, syslib, 0); + luaL_register(L, LUA_OSLIBNAME, syslib); return 1; } diff --git a/src/lparser.c b/src/lparser.c index 54facfc4..91dc4fff 100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.27 2005/05/17 19:49:15 roberto Exp $ +** $Id: lparser.c,v 2.35 2005/08/29 20:49:21 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -239,35 +239,35 @@ static void markupval (FuncState *fs, int level) { } -static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) /* no more levels? */ +static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) { /* no more levels? */ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ + return VGLOBAL; + } else { int v = searchvar(fs, n); /* look up at current level */ if (v >= 0) { init_exp(var, VLOCAL, v); if (!base) markupval(fs, v); /* local will be used as an upval */ + return VLOCAL; } else { /* not found at current level; try upper one */ - singlevaraux(fs->prev, n, var, 0); - if (var->k == VGLOBAL) { - if (base) - var->info = luaK_stringK(fs, n); /* info points to global name */ - } - else { /* LOCAL or UPVAL */ - var->info = indexupvalue(fs, n, var); - var->k = VUPVAL; /* upvalue in this level */ - } + if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) + return VGLOBAL; + var->info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ + var->k = VUPVAL; /* upvalue in this level */ + return VUPVAL; } } } -static TString *singlevar (LexState *ls, expdesc *var, int base) { +static void singlevar (LexState *ls, expdesc *var) { TString *varname = str_checkname(ls); - singlevaraux(ls->fs, varname, var, base); - return varname; + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VGLOBAL) + var->info = luaK_stringK(fs, varname); /* info points to global name */ } @@ -300,7 +300,7 @@ static void enterlevel (LexState *ls) { #define leavelevel(ls) ((ls)->L->nCcalls--) -static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) { +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { bl->breaklist = NO_JUMP; bl->isbreakable = isbreakable; bl->nactvar = fs->nactvar; @@ -317,6 +317,7 @@ static void leaveblock (FuncState *fs) { removevars(fs->ls, bl->nactvar); if (bl->upval) luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + lua_assert(!bl->isbreakable || !bl->upval); /* loops have no body */ lua_assert(bl->nactvar == fs->nactvar); fs->freereg = fs->nactvar; /* free registers */ luaK_patchtohere(fs, bl->breaklist); @@ -374,7 +375,7 @@ static void close_func (LexState *ls) { FuncState *fs = ls->fs; Proto *f = fs->f; removevars(ls, 0); - luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ + luaK_ret(fs, 0, 0); /* final return */ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); f->sizecode = fs->pc; luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); @@ -402,7 +403,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { lexstate.buff = buff; luaX_setinput(L, &lexstate, z, luaS_new(L, name)); open_func(&lexstate, &funcstate); - funcstate.f->is_vararg = NEWSTYLEVARARG; + funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ next(&lexstate); /* read first token */ chunk(&lexstate); check(&lexstate, TK_EOS); @@ -525,7 +526,6 @@ static void constructor (LexState *ls, expdesc *t) { checknext(ls, '{'); do { lua_assert(cc.v.k == VVOID || cc.tostore > 0); - testnext(ls, ';'); /* compatibility only */ if (ls->t.token == '}') break; closelistfield(fs, &cc); switch(ls->t.token) { @@ -572,9 +572,12 @@ static void parlist (LexState *ls) { } case TK_DOTS: { /* param -> `...' */ next(ls); +#if defined(LUA_COMPAT_VARARG) /* use `arg' as default name */ new_localvarliteral(ls, "arg", nparams++); - f->is_vararg = 1; + f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; +#endif + f->is_vararg |= VARARG_ISVARARG; break; } default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); @@ -582,7 +585,7 @@ static void parlist (LexState *ls) { } while (!f->is_vararg && testnext(ls, ',')); } adjustlocalvars(ls, nparams); - f->numparams = fs->nactvar - f->is_vararg; + f->numparams = fs->nactvar - (f->is_vararg & VARARG_HASARG); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ } @@ -690,7 +693,7 @@ static void prefixexp (LexState *ls, expdesc *v) { return; } case TK_NAME: { - singlevar(ls, v, 1); + singlevar(ls, v); return; } default: { @@ -766,7 +769,7 @@ static void simpleexp (LexState *ls, expdesc *v) { FuncState *fs = ls->fs; check_condition(ls, fs->f->is_vararg, "cannot use " LUA_QL("...") " outside a vararg function"); - fs->f->is_vararg = NEWSTYLEVARARG; + fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); break; } @@ -792,7 +795,7 @@ static UnOpr getunopr (int op) { switch (op) { case TK_NOT: return OPR_NOT; case '-': return OPR_MINUS; - case '*': return OPR_SIZE; + case '#': return OPR_LEN; default: return OPR_NOUNOPR; } } @@ -979,78 +982,68 @@ static int cond (LexState *ls) { expr(ls, &v); /* read condition */ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ luaK_goiftrue(ls->fs, &v); - luaK_patchtohere(ls->fs, v.t); return v.f; } -/* -** The while statement optimizes its code by coding the condition -** after its body (and thus avoiding one jump in the loop). -*/ - +static void breakstat (LexState *ls) { + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + int upval = 0; + while (bl && !bl->isbreakable) { + upval |= bl->upval; + bl = bl->previous; + } + if (!bl) + luaX_syntaxerror(ls, "no loop to break"); + if (upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); +} -/* -** the call `luaK_goiffalse' may grow the size of an expression by -** at most this: -*/ -#define EXTRAEXP 5 static void whilestat (LexState *ls, int line) { /* whilestat -> WHILE cond DO block END */ - Instruction codeexp[LUAI_MAXEXPWHILE + EXTRAEXP]; - int lineexp; - int i; - int sizeexp; FuncState *fs = ls->fs; - int whileinit, blockinit, expinit; - expdesc v; + int whileinit; + int condexit; BlockCnt bl; next(ls); /* skip WHILE */ - whileinit = luaK_jump(fs); /* jump to condition (which will be moved) */ - expinit = luaK_getlabel(fs); - expr(ls, &v); /* parse condition */ - if (v.k == VK) v.k = VTRUE; /* `trues' are all equal here */ - lineexp = ls->linenumber; - luaK_goiffalse(fs, &v); - luaK_concat(fs, &v.f, fs->jpc); - fs->jpc = NO_JUMP; - sizeexp = fs->pc - expinit; /* size of expression code */ - if (sizeexp > LUAI_MAXEXPWHILE) - luaX_syntaxerror(ls, LUA_QL("while") " condition too complex"); - for (i = 0; i < sizeexp; i++) /* save `exp' code */ - codeexp[i] = fs->f->code[expinit + i]; - fs->pc = expinit; /* remove `exp' code */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); enterblock(fs, &bl, 1); checknext(ls, TK_DO); - blockinit = luaK_getlabel(fs); block(ls); - luaK_patchtohere(fs, whileinit); /* initial jump jumps to here */ - /* move `exp' back to code */ - if (v.t != NO_JUMP) v.t += fs->pc - expinit; - if (v.f != NO_JUMP) v.f += fs->pc - expinit; - for (i=0; i<sizeexp; i++) - luaK_code(fs, codeexp[i], lineexp); + luaK_patchlist(fs, luaK_jump(fs), whileinit); check_match(ls, TK_END, TK_WHILE, line); leaveblock(fs); - luaK_patchlist(fs, v.t, blockinit); /* true conditions go back to loop */ - luaK_patchtohere(fs, v.f); /* false conditions finish the loop */ + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ } static void repeatstat (LexState *ls, int line) { /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; FuncState *fs = ls->fs; int repeat_init = luaK_getlabel(fs); - int flist; - BlockCnt bl; - enterblock(fs, &bl, 1); - next(ls); - block(ls); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + next(ls); /* skip REPEAT */ + chunk(ls); check_match(ls, TK_UNTIL, TK_REPEAT, line); - flist = cond(ls); - luaK_patchlist(fs, flist, repeat_init); - leaveblock(fs); + condexit = cond(ls); /* read condition (inside scope block) */ + if (!bl2.upval) { /* no upvalues? */ + leaveblock(fs); /* finish scope */ + luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ + } + else { /* complete semantics when there are upvalues */ + breakstat(ls); /* if condition then break */ + luaK_patchtohere(ls->fs, condexit); /* else... */ + leaveblock(fs); /* finish scope... */ + luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ + } + leaveblock(fs); /* finish loop */ } @@ -1150,12 +1143,12 @@ static void forstat (LexState *ls, int line) { static int test_then_block (LexState *ls) { /* test_then_block -> [IF | ELSEIF] cond THEN block */ - int flist; + int condexit; next(ls); /* skip IF or ELSEIF */ - flist = cond(ls); + condexit = cond(ls); checknext(ls, TK_THEN); block(ls); /* `then' part */ - return flist; + return condexit; } @@ -1219,7 +1212,7 @@ static void localstat (LexState *ls) { static int funcname (LexState *ls, expdesc *v) { /* funcname -> NAME {field} [`:' NAME] */ int needself = 0; - singlevar(ls, v, 1); + singlevar(ls, v); while (ls->t.token == '.') field(ls, v); if (ls->t.token == ':') { @@ -1285,25 +1278,7 @@ static void retstat (LexState *ls) { } } } - luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); -} - - -static void breakstat (LexState *ls) { - /* stat -> BREAK */ - FuncState *fs = ls->fs; - BlockCnt *bl = fs->bl; - int upval = 0; - next(ls); /* skip BREAK */ - while (bl && !bl->isbreakable) { - upval |= bl->upval; - bl = bl->previous; - } - if (!bl) - luaX_syntaxerror(ls, "no loop to break"); - if (upval) - luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); - luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); + luaK_ret(fs, first, nret); } @@ -1349,6 +1324,7 @@ static int statement (LexState *ls) { return 1; /* must be last statement */ } case TK_BREAK: { /* stat -> breakstat */ + next(ls); /* skip BREAK */ breakstat(ls); return 1; /* must be last statement */ } diff --git a/src/lstate.c b/src/lstate.c index 41162dac..2a4ace12 100644 --- a/src/lstate.c +++ b/src/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.31 2005/05/05 15:34:03 roberto Exp $ +** $Id: lstate.c,v 2.33 2005/08/25 15:39:16 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -72,7 +72,6 @@ static void f_luaopen (lua_State *L, void *ud) { UNUSED(ud); stack_init(L, L); /* init stack */ sethvalue(L, gt(L), luaH_new(L, 0, 20)); /* table of globals */ - hvalue(gt(L))->metatable = luaH_new(L, 0, 0); /* globals metatable */ sethvalue(L, registry(L), luaH_new(L, 6, 20)); /* registry */ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ luaT_init(L); @@ -83,7 +82,7 @@ static void f_luaopen (lua_State *L, void *ud) { static void preinit_state (lua_State *L, global_State *g) { - L->l_G = g; + G(L) = g; L->stack = NULL; L->stacksize = 0; L->errorJmp = NULL; diff --git a/src/lstate.h b/src/lstate.h index 7dafa4d5..e8bc15ab 100644 --- a/src/lstate.h +++ b/src/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.21 2005/05/05 15:34:03 roberto Exp $ +** $Id: lstate.h,v 2.23 2005/07/09 13:22:34 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -19,10 +19,10 @@ struct lua_longjmp; /* defined in ldo.c */ /* table of globals */ -#define gt(L) (&L->_gt) +#define gt(L) (&L->l_gt) /* registry */ -#define registry(L) (&G(L)->_registry) +#define registry(L) (&G(L)->l_registry) /* extra stack space to handle TM calls and some other extras */ @@ -86,7 +86,7 @@ typedef struct global_State { int gcpause; /* size of pause between successive GCs */ int gcstepmul; /* GC `granularity' */ lua_CFunction panic; /* to be called in unprotected errors */ - TValue _registry; + TValue l_registry; struct lua_State *mainthread; UpVal uvhead; /* head of double-linked list of all open upvalues */ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ @@ -117,7 +117,7 @@ struct lua_State { int basehookcount; int hookcount; lua_Hook hook; - TValue _gt; /* table of globals */ + TValue l_gt; /* table of globals */ TValue env; /* temporary place for environments */ GCObject *openupval; /* list of open upvalues in this stack */ GCObject *gclist; diff --git a/src/lstrlib.c b/src/lstrlib.c index 4929a27c..4cf5836a 100644 --- a/src/lstrlib.c +++ b/src/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.115 2005/05/17 19:49:15 roberto Exp $ +** $Id: lstrlib.c,v 1.123 2005/08/26 17:36:32 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -58,7 +58,7 @@ static int str_reverse (lua_State *L) { luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); luaL_buffinit(L, &b); - while (l--) luaL_putchar(&b, s[l]); + while (l--) luaL_addchar(&b, s[l]); luaL_pushresult(&b); return 1; } @@ -71,7 +71,7 @@ static int str_lower (lua_State *L) { const char *s = luaL_checklstring(L, 1, &l); luaL_buffinit(L, &b); for (i=0; i<l; i++) - luaL_putchar(&b, tolower(uchar(s[i]))); + luaL_addchar(&b, tolower(uchar(s[i]))); luaL_pushresult(&b); return 1; } @@ -84,7 +84,7 @@ static int str_upper (lua_State *L) { const char *s = luaL_checklstring(L, 1, &l); luaL_buffinit(L, &b); for (i=0; i<l; i++) - luaL_putchar(&b, toupper(uchar(s[i]))); + luaL_addchar(&b, toupper(uchar(s[i]))); luaL_pushresult(&b); return 1; } @@ -127,7 +127,7 @@ static int str_char (lua_State *L) { for (i=1; i<=n; i++) { int c = luaL_checkint(L, i); luaL_argcheck(L, uchar(c) == c, i, "invalid value"); - luaL_putchar(&b, uchar(c)); + luaL_addchar(&b, uchar(c)); } luaL_pushresult(&b); return 1; @@ -461,7 +461,7 @@ static const char *lmemfind (const char *s1, size_t l1, static void push_onecapture (MatchState *ms, int i) { - int l = ms->capture[i].len; + ptrdiff_t l = ms->capture[i].len; if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); if (l == CAP_POSITION) lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); @@ -485,15 +485,15 @@ static int push_captures (MatchState *ms, const char *s, const char *e) { } -static int str_find (lua_State *L) { +static int str_find_aux (lua_State *L, int find) { size_t l1, l2; const char *s = luaL_checklstring(L, 1, &l1); const char *p = luaL_checklstring(L, 2, &l2); ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; if (init < 0) init = 0; else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; - if (lua_toboolean(L, 4) || /* explicit request? */ - strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ + if (find && (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ /* do a plain search */ const char *s2 = lmemfind(s+init, l1-init, p, l2); if (s2) { @@ -513,18 +513,37 @@ static int str_find (lua_State *L) { const char *res; ms.level = 0; if ((res=match(&ms, s1, p)) != NULL) { - lua_pushinteger(L, s1-s+1); /* start */ - lua_pushinteger(L, res-s); /* end */ - return push_captures(&ms, NULL, 0) + 2; + if (find) { + lua_pushinteger(L, s1-s+1); /* start */ + lua_pushinteger(L, res-s); /* end */ +#if defined(LUA_COMPAT_FIND) + return push_captures(&ms, NULL, 0) + 2; +#else + return 2; +#endif + + } + else + return push_captures(&ms, s1, res); } - } while (s1++<ms.src_end && !anchor); + } while (s1++ < ms.src_end && !anchor); } lua_pushnil(L); /* not found */ return 1; } -static int gfind_aux (lua_State *L) { +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +static int gmatch_aux (lua_State *L) { MatchState ms; size_t ls; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); @@ -539,7 +558,7 @@ static int gfind_aux (lua_State *L) { const char *e; ms.level = 0; if ((e = match(&ms, src, p)) != NULL) { - int newstart = e-s; + lua_Integer newstart = e-s; if (e == src) newstart++; /* empty match? go at least one position */ lua_pushinteger(L, newstart); lua_replace(L, lua_upvalueindex(3)); @@ -550,16 +569,22 @@ static int gfind_aux (lua_State *L) { } -static int gfind (lua_State *L) { +static int gmatch (lua_State *L) { luaL_checkstring(L, 1); luaL_checkstring(L, 2); lua_settop(L, 2); lua_pushinteger(L, 0); - lua_pushcclosure(L, gfind_aux, 3); + lua_pushcclosure(L, gmatch_aux, 3); return 1; } +static int gfind_nodef (lua_State *L) { + return luaL_error(L, LUA_QL("string.gfind") " was renamed to " + LUA_QL("string.gmatch")); +} + + static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { lua_State *L = ms->L; @@ -569,14 +594,18 @@ static void add_s (MatchState *ms, luaL_Buffer *b, size_t i; for (i=0; i<l; i++) { if (news[i] != L_ESC) - luaL_putchar(b, news[i]); + luaL_addchar(b, news[i]); else { i++; /* skip ESC */ if (!isdigit(uchar(news[i]))) - luaL_putchar(b, news[i]); + luaL_addchar(b, news[i]); else { - int level = check_capture(ms, news[i]); - push_onecapture(ms, level); + if (news[i] == '0') + lua_pushlstring(L, s, e - s); /* add whole match */ + else { + int level = check_capture(ms, news[i]); + push_onecapture(ms, level); + } luaL_addvalue(b); /* add capture to accumulated result */ } } @@ -622,7 +651,7 @@ static int str_gsub (lua_State *L) { if (e && e>src) /* non empty match? */ src = e; /* skip it */ else if (src < ms.src_end) - luaL_putchar(&b, *src++); + luaL_addchar(&b, *src++); else break; if (anchor) break; } @@ -644,12 +673,12 @@ static int str_gsub (lua_State *L) { static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { size_t l; const char *s = luaL_checklstring(L, arg, &l); - luaL_putchar(b, '"'); + luaL_addchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': case '\n': { - luaL_putchar(b, '\\'); - luaL_putchar(b, *s); + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); break; } case '\0': { @@ -657,13 +686,13 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { break; } default: { - luaL_putchar(b, *s); + luaL_addchar(b, *s); break; } } s++; } - luaL_putchar(b, '"'); + luaL_addchar(b, '"'); } @@ -699,9 +728,9 @@ static int str_format (lua_State *L) { luaL_buffinit(L, &b); while (strfrmt < strfrmt_end) { if (*strfrmt != L_ESC) - luaL_putchar(&b, *strfrmt++); + luaL_addchar(&b, *strfrmt++); else if (*++strfrmt == L_ESC) - luaL_putchar(&b, *strfrmt++); /* %% */ + luaL_addchar(&b, *strfrmt++); /* %% */ else { /* format item */ char form[MAX_FORMAT]; /* to store the format (`%...') */ char buff[MAX_ITEM]; /* to store the formatted item */ @@ -753,20 +782,22 @@ static int str_format (lua_State *L) { } -static const luaL_reg strlib[] = { - {"len", str_len}, - {"sub", str_sub}, - {"reverse", str_reverse}, - {"lower", str_lower}, - {"upper", str_upper}, - {"char", str_char}, - {"rep", str_rep}, +static const luaL_Reg strlib[] = { {"byte", str_byte}, - {"format", str_format}, + {"char", str_char}, {"dump", str_dump}, {"find", str_find}, - {"gfind", gfind}, + {"format", str_format}, + {"gfind", gfind_nodef}, + {"gmatch", gmatch}, {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, {NULL, NULL} }; @@ -779,8 +810,6 @@ static void createmetatable (lua_State *L) { lua_pop(L, 1); /* pop dummy string */ lua_pushvalue(L, -2); /* string library... */ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ - lua_getfield(L, -2, "len"); - lua_setfield(L, -2, "__siz"); lua_pop(L, 1); /* pop metatable */ } @@ -789,7 +818,11 @@ static void createmetatable (lua_State *L) { ** Open string library */ LUALIB_API int luaopen_string (lua_State *L) { - luaL_openlib(L, LUA_STRLIBNAME, strlib, 0); + luaL_register(L, LUA_STRLIBNAME, strlib); +#if defined(LUA_COMPAT_GFIND) + lua_getfield(L, -1, "gmatch"); + lua_setfield(L, -2, "gfind"); +#endif createmetatable(L); return 1; } diff --git a/src/ltable.c b/src/ltable.c index d0ba365b..979cc5ca 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.23 2005/05/17 19:49:15 roberto Exp $ +** $Id: ltable.c,v 2.26 2005/07/11 14:01:37 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -120,7 +120,7 @@ static int arrayindex (const TValue *key) { lua_Number n = nvalue(key); int k; lua_number2int(k, n); - if (luai_numeq(cast(lua_Number, k), nvalue(key))) + if (luai_numeq(L, cast(lua_Number, k), nvalue(key))) return k; } return -1; /* `key' did not match some condition */ @@ -145,7 +145,7 @@ static int findindex (lua_State *L, Table *t, StkId key) { if (luaO_rawequalObj(key2tval(n), key) || (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && gcvalue(gkey(n)) == gcvalue(key))) { - i = n - gnode(t, 0); /* key index in hash table */ + i = cast(int, n - gnode(t, 0)); /* key index in hash table */ /* hash elements are numbered after array ones */ return i + t->sizearray; } @@ -376,7 +376,7 @@ void luaH_free (lua_State *L, Table *t) { } -static Node *getfreepos (lua_State *L, Table *t) { +static Node *getfreepos (Table *t) { while (t->lastfree-- > t->node) { if (ttisnil(gkey(t->lastfree))) return t->lastfree; @@ -397,7 +397,7 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { Node *mp = luaH_mainposition(t, key); if (!ttisnil(gval(mp)) || mp == &luaH_dummynode) { Node *othern; - Node *n = getfreepos(L, t); /* get a free place */ + Node *n = getfreepos(t); /* get a free place */ if (n == NULL) { /* cannot find a free place? */ rehash(L, t, key); /* grow table */ return luaH_set(L, t, key); /* re-insert key into grown table */ @@ -437,7 +437,7 @@ const TValue *luaH_getnum (Table *t, int key) { lua_Number nk = cast(lua_Number, key); Node *n = hashnum(t, nk); do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + if (ttisnumber(gkey(n)) && luai_numeq(L, nvalue(gkey(n)), nk)) return gval(n); /* that's it */ else n = gnext(n); } while (n); @@ -471,7 +471,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { int k; lua_Number n = nvalue(key); lua_number2int(k, n); - if (luai_numeq(cast(lua_Number, k), nvalue(key))) /* index is integer? */ + if (luai_numeq(L, cast(lua_Number, k), nvalue(key))) /* index is int? */ return luaH_getnum(t, k); /* use specialized version */ /* else go through */ } @@ -495,7 +495,7 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { return cast(TValue *, p); else { if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && !luai_numeq(nvalue(key), nvalue(key))) + else if (ttisnumber(key) && !luai_numeq(L, nvalue(key), nvalue(key))) luaG_runerror(L, "table index is NaN"); return newkey(L, t, key); } diff --git a/src/ltable.h b/src/ltable.h index 1a798262..14a20448 100644 --- a/src/ltable.h +++ b/src/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.7 2005/04/25 19:24:10 roberto Exp $ +** $Id: ltable.h,v 2.8 2005/06/06 13:30:25 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -18,7 +18,7 @@ #define key2tval(n) (cast(const TValue *, gkey(n))) -extern const Node luaH_dummynode; +LUAI_DATA const Node luaH_dummynode; LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); diff --git a/src/ltablib.c b/src/ltablib.c index ab4d5db2..348b6ed5 100644 --- a/src/ltablib.c +++ b/src/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.31 2005/05/17 19:49:15 roberto Exp $ +** $Id: ltablib.c,v 1.35 2005/08/26 17:36:32 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -109,7 +109,7 @@ static int tremove (lua_State *L) { } -static int str_concat (lua_State *L) { +static int tconcat (lua_State *L) { luaL_Buffer b; size_t lsep; const char *sep = luaL_optlstring(L, 2, "", &lsep); @@ -236,21 +236,21 @@ static int sort (lua_State *L) { /* }====================================================== */ -static const luaL_reg tab_funcs[] = { - {"concat", str_concat}, +static const luaL_Reg tab_funcs[] = { + {"concat", tconcat}, {"foreach", foreach}, {"foreachi", foreachi}, {"getn", getn}, - {"setn", setn}, - {"sort", sort}, {"insert", tinsert}, {"remove", tremove}, + {"setn", setn}, + {"sort", sort}, {NULL, NULL} }; LUALIB_API int luaopen_table (lua_State *L) { - luaL_openlib(L, LUA_TABLIBNAME, tab_funcs, 0); + luaL_register(L, LUA_TABLIBNAME, tab_funcs); return 1; } @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.5 2005/05/05 15:34:03 roberto Exp $ +** $Id: ltm.c,v 2.6 2005/05/20 15:53:42 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -32,7 +32,7 @@ void luaT_init (lua_State *L) { "__index", "__newindex", "__gc", "__mode", "__eq", "__add", "__sub", "__mul", "__div", "__mod", - "__pow", "__unm", "__siz", "__lt", "__le", + "__pow", "__unm", "__len", "__lt", "__le", "__concat", "__call" }; int i; @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 2.4 2005/05/05 15:34:03 roberto Exp $ +** $Id: ltm.h,v 2.6 2005/06/06 13:30:25 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -28,7 +28,7 @@ typedef enum { TM_MOD, TM_POW, TM_UNM, - TM_SIZ, + TM_LEN, TM_LT, TM_LE, TM_CONCAT, @@ -43,7 +43,7 @@ typedef enum { #define fasttm(l,et,e) gfasttm(G(l), et, e) -extern const char *const luaT_typenames[]; +LUAI_DATA const char *const luaT_typenames[]; LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); @@ -1,5 +1,5 @@ /* -** $Id: lua.c,v 1.144 2005/05/17 19:49:15 roberto Exp $ +** $Id: lua.c,v 1.150 2005/09/06 17:19:33 roberto Exp $ ** Lua stand-alone interpreter ** See Copyright Notice in lua.h */ @@ -48,15 +48,16 @@ static void print_usage (void) { " -i enter interactive mode after executing " LUA_QL("script") "\n" " -l name require library " LUA_QL("name") "\n" " -v show version information\n" - " -w trap access to undefined globals\n" " -- stop handling options\n" , progname); + fflush(stderr); } static void l_message (const char *pname, const char *msg) { if (pname) fprintf(stderr, "%s: ", pname); fprintf(stderr, "%s\n", msg); + fflush(stderr); } @@ -72,14 +73,19 @@ static int report (lua_State *L, int status) { static int traceback (lua_State *L) { - luaL_getfield(L, LUA_GLOBALSINDEX, "debug.traceback"); - if (!lua_isfunction(L, -1)) + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { lua_pop(L, 1); - else { - lua_pushvalue(L, 1); /* pass error message */ - lua_pushinteger(L, 2); /* skip this function and traceback */ - lua_call(L, 2, 1); /* call debug.traceback */ + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; } + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ return 1; } @@ -138,8 +144,7 @@ static int dolibrary (lua_State *L, const char *name) { static const char *get_prompt (lua_State *L, int firstline) { const char *p; - lua_pushstring(L, firstline ? "_PROMPT" : "_PROMPT2"); - lua_rawget(L, LUA_GLOBALSINDEX); + lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); p = lua_tostring(L, -1); if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); lua_pop(L, 1); /* remove global */ @@ -148,13 +153,16 @@ static const char *get_prompt (lua_State *L, int firstline) { static int incomplete (lua_State *L, int status) { - if (status == LUA_ERRSYNTAX && - strstr(lua_tostring(L, -1), "<eof>") != NULL) { - lua_pop(L, 1); - return 1; + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1); + if (strstr(msg, LUA_QL("<eof>")) == tp) { + lua_pop(L, 1); + return 1; + } } - else - return 0; + return 0; /* else... */ } @@ -216,18 +224,11 @@ static void dotty (lua_State *L) { } lua_settop(L, 0); /* clear stack */ fputs("\n", stdout); + fflush(stdout); progname = oldprogname; } -static int checkvar (lua_State *L) { - const char *name = lua_tostring(L, 2); - if (name) - luaL_error(L, "attempt to access undefined variable " LUA_QS, name); - return 0; -} - - #define clearinteractive(i) (*i &= 2) static int handle_argv (lua_State *L, int argc, char **argv, int *interactive) { @@ -265,13 +266,6 @@ static int handle_argv (lua_State *L, int argc, char **argv, int *interactive) { print_version(); break; } - case 'w': { - if (lua_getmetatable(L, LUA_GLOBALSINDEX)) { - lua_pushcfunction(L, checkvar); - lua_setfield(L, -2, "__index"); - } - break; - } case 'e': { const char *chunk = argv[i] + 2; clearinteractive(interactive); @@ -1,8 +1,7 @@ /* -** $Id: lua.h,v 1.208 2005/05/17 19:49:15 roberto Exp $ +** $Id: lua.h,v 1.212 2005/08/25 20:02:08 roberto Exp $ ** Lua - An Extensible Extension Language -** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil -** http://www.lua.org +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file */ @@ -17,9 +16,9 @@ #include "luaconf.h" -#define LUA_VERSION "Lua 5.1 (work6)" +#define LUA_VERSION "Lua 5.1 (alpha)" #define LUA_VERSION_NUM 501 -#define LUA_COPYRIGHT "Copyright (C) 1994-2005 Tecgraf, PUC-Rio" +#define LUA_COPYRIGHT "Copyright (C) 1994-2005 Lua.org, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" @@ -39,7 +38,7 @@ #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) -/* return codes for `lua_pcall', `lua_resume', and `lua_status' */ +/* thread status; 0 is OK */ #define LUA_YIELD 1 #define LUA_ERRRUN 2 #define LUA_ERRSYNTAX 3 @@ -147,7 +146,7 @@ LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); LUA_API int (lua_toboolean) (lua_State *L, int idx); LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API size_t (lua_objsize) (lua_State *L, int idx); +LUA_API size_t (lua_objlen) (lua_State *L, int idx); LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); LUA_API void *(lua_touserdata) (lua_State *L, int idx); LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); @@ -257,7 +256,7 @@ LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) -#define lua_strlen(L,i) lua_objsize(L, (i)) +#define lua_strlen(L,i) lua_objlen(L, (i)) #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) @@ -357,7 +356,7 @@ struct lua_Debug { /****************************************************************************** -* Copyright (C) 1994-2005 Tecgraf, PUC-Rio. All rights reserved. +* Copyright (C) 1994-2005 Lua.org, PUC-Rio. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -1,5 +1,5 @@ /* -** $Id: luac.c,v 1.50 2005/05/12 00:26:50 lhf Exp $ +** $Id: luac.c,v 1.51 2005/06/02 13:39:23 lhf Exp $ ** Lua compiler (saves bytecodes to files; also list bytecodes) ** See Copyright Notice in lua.h */ @@ -53,7 +53,7 @@ static void cannot(const char* what) static void usage(const char* message) { if (*message=='-') - fprintf(stderr,"%s: unrecognized option `%s'\n",progname,message); + fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); else fprintf(stderr,"%s: %s\n",progname,message); fprintf(stderr, @@ -61,7 +61,7 @@ static void usage(const char* message) "Available options are:\n" " - process stdin\n" " -l list\n" - " -o name output to file `name' (default is \"%s\")\n" + " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" " -p parse only\n" " -s strip debug information\n" " -v show version information\n" @@ -92,7 +92,7 @@ static int doargs(int argc, char* argv[]) else if (IS("-o")) /* output file */ { output=argv[++i]; - if (output==NULL || *output==0) usage("`-o' needs argument"); + if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument"); if (IS("-")) output=NULL; } else if (IS("-p")) /* parse only */ diff --git a/src/luaconf.h b/src/luaconf.h index bc211cd3..d6d4a2a7 100644 --- a/src/luaconf.h +++ b/src/luaconf.h @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.49a 2005/05/17 19:49:15 roberto Exp $ +** $Id: luaconf.h,v 1.65 2005/09/09 18:24:42 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -22,6 +22,16 @@ /* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +#if defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +/* @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for @* Lua libraries. @@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for @@ -31,22 +41,27 @@ ** non-conventional directories. */ #if defined(_WIN32) -#define LUA_ROOT "C:\\Program Files\\Lua51" -#define LUA_LDIR LUA_ROOT "\\lua" -#define LUA_CDIR LUA_ROOT "\\dll" +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" #define LUA_PATH_DEFAULT \ - "?.lua;" LUA_LDIR"\\?.lua;" LUA_LDIR"\\?\\init.lua" -#define LUA_CPATH_DEFAULT \ - "?.dll;" "l?.dll;" LUA_CDIR"\\?.dll;" LUA_CDIR"\\l?.dll" + ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" +#define LUA_CPATH_DEFAULT \ + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" #else -#define LUA_ROOT "/usr/local" -#define LUA_LDIR LUA_ROOT "/share/lua/5.1" -#define LUA_CDIR LUA_ROOT "/lib/lua/5.1" +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/5.1/" +#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" #define LUA_PATH_DEFAULT \ - "./?.lua;" LUA_LDIR"/?.lua;" LUA_LDIR"/?/init.lua" -#define LUA_CPATH_DEFAULT \ - "./?.so;" "./l?.so;" LUA_CDIR"/?.so;" LUA_CDIR"/l?.so" + "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" +#define LUA_CPATH_DEFAULT \ + "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" #endif @@ -64,21 +79,20 @@ /* @@ LUA_PATHSEP is the character that separates templates in a path. -** CHANGE it if for some reason your system cannot use a -** semicolon. (E.g., if a semicolon is a common character in -** file/directory names.) Probably you do not need to change this. -*/ -#define LUA_PATHSEP ';' - - -/* @@ LUA_PATH_MARK is the string that marks the substitution points in a @* template. -** CHANGE it if for some reason your system cannot use an interrogation -** mark. (E.g., if an interogation mark is a common character in -** file/directory names.) Probably you do not need to change this. -*/ +@@ LUA_EXECDIR in a Windows path is replaced by the executable's +@* directory. +@@ LUA_IGMARK is a mark to ignore all before it when bulding the +@* luaopen_ function name. +** CHANGE them if for some reason your system cannot use those +** characters. (E.g., if one of those characters is a common character +** in file/directory names.) Probably you do not need to change them. +*/ +#define LUA_PATHSEP ";" #define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK ":" /* @@ -100,9 +114,9 @@ #if defined(LUA_BUILD_AS_DLL) #if defined(LUA_CORE) || defined(LUA_LIB) -#define LUA_API __declspec(__dllexport) +#define LUA_API __declspec(dllexport) #else -#define LUA_API __declspec(__dllimport) +#define LUA_API __declspec(dllimport) #endif #else @@ -118,19 +132,26 @@ /* @@ LUAI_FUNC is a mark for all extern functions that are not to be @* exported to outside modules. -** CHANGE it if you need to mark them in some special way. Gcc (versions -** 3.2 and later) mark them as "hidden" to optimize their call when Lua -** is compiled as a shared library. +@@ LUAI_DATA is a mark for all extern (const) variables that are not to +@* be exported to outside modules. +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. */ #if defined(luaall_c) #define LUAI_FUNC static -#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) -#define LUAI_FUNC __attribute__((visibility("hidden"))) +#define LUAI_DATA /* empty */ +#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DATA LUAI_FUNC #else #define LUAI_FUNC extern +#define LUAI_DATA extern #endif + /* @@ lua_assert describes the internal assertions in Lua. ** CHANGE that only if you need to debug Lua. @@ -149,7 +170,7 @@ /* @@ LUA_IDSIZE gives the maximum size for the description of the source @* of a function in debug information. -** CHANGE it if you a different size. +** CHANGE it if you want a different size. */ #define LUA_IDSIZE 60 @@ -168,10 +189,10 @@ ** CHANGE it if you have a better definition for non-POSIX/non-Windows ** systems. */ -#if !defined(__STRICT_ANSI__) && defined(_POSIX_C_SOURCE) +#if !defined(LUA_ANSI) && defined(_POSIX_C_SOURCE) #include <unistd.h> #define lua_stdin_is_tty() isatty(0) -#elif !defined(__STRICT_ANSI__) && defined(_WIN32) +#elif !defined(LUA_ANSI) && defined(_WIN32) #include <io.h> #include <stdio.h> #define lua_stdin_is_tty() _isatty(_fileno(stdin)) @@ -214,7 +235,7 @@ ** CHANGE them if you want to improve this functionality (e.g., by using ** GNU readline and history facilities). */ -#if !defined(__STRICT_ANSI__) && defined(LUA_USE_READLINE) +#if defined(LUA_USE_READLINE) #include <stdio.h> #include <readline/readline.h> #include <readline/history.h> @@ -239,49 +260,52 @@ /* @@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles @* as a percentage. -** CHANGE it if you want the GC to run faster or slower (higher -** values mean larger pauses which mean slower collection.) +** CHANGE it if you want the GC to run faster or slower (higher values +** mean larger pauses which mean slower collection.) You can also change +** this value dynamically. */ #define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ /* -@@ LUAI_GCMUL defines the speed of garbage collection relative to +@@ LUAI_GCMUL defines the default speed of garbage collection relative to @* memory allocation as a percentage. ** CHANGE it if you want to change the granularity of the garbage ** collection. (Higher values mean coarser collections. 0 represents -** infinity, where each step performs a full collection.) +** infinity, where each step performs a full collection.) You can also +** change this value dynamically. */ #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ + /* @@ LUA_COMPAT_GETN controls compatibility with old getn behavior. -** CHANGE it to 1 if you want exact compatibility with the behavior of -** setn/getn in Lua 5.0. +** CHANGE it (define it) if you want exact compatibility with the +** behavior of setn/getn in Lua 5.0. */ -#define LUA_COMPAT_GETN 0 +#undef LUA_COMPAT_GETN /* -@@ LUA_COMPAT_PATH controls compatibility about LUA_PATH. -** CHANGE it to 1 if you want 'require' to look for global LUA_PATH -** before checking package.path. +@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. +** CHANGE it to undefined as soon as you do not need a global 'loadlib' +** function (the function is still available as 'package.loadlib'). */ -#define LUA_COMPAT_PATH 0 +#undef LUA_COMPAT_LOADLIB /* -@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. -** CHANGE it to 1 if you want a global 'loadlib' function (otherwise -** the function is only available as 'package.loadlib'). +@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. +** CHANGE it to undefined as soon as your programs use only '...' to +** access vararg parameters (instead of the old 'arg' table). */ -#define LUA_COMPAT_LOADLIB 1 +#define LUA_COMPAT_VARARG /* -@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. -** CHANGE it to 1 if you want vararg functions that do not use '...' -** to get an 'arg' table with their extra arguments. +@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. +** CHANGE it to undefined as soon as your programs use 'math.fmod' or +** the new '%' operator instead of 'math.mod'. */ -#define LUA_COMPAT_VARARG 1 +#define LUA_COMPAT_MOD /* @@ LUA_COMPAT_LSTR controls compatibility with old long string nesting @@ -292,6 +316,31 @@ #define LUA_COMPAT_LSTR 1 /* +@@ LUA_COMPAT_FIND controls compatibility with old 'string.find' behavior. +** CHANGE it to undefined as soon as your programs use 'string.find' only +** to find patterns. +*/ +#define LUA_COMPAT_FIND + +/* +@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. +** CHANGE it to undefined as soon as you rename 'string.gfind' to +** 'string.gmatch'. +*/ +#define LUA_COMPAT_GFIND + + +/* +@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' +@* behavior. +** CHANGE it to undefined as soon as you replace to 'luaL_registry' +** your uses of 'luaL_openlib' +*/ +#define LUA_COMPAT_OPENLIB + + + +/* @@ luai_apicheck is the assert macro used by the Lua-C API. ** CHANGE luai_apicheck if you want Lua to perform some checks in the ** parameters it gets from API calls. This may slow down the interpreter @@ -407,13 +456,6 @@ /* -@@ LUAI_MAXEXPWHILE is the maximum size of code for expressions -@* controling a 'while' loop. -*/ -#define LUAI_MAXEXPWHILE 100 - - -/* @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. */ #define LUAL_BUFFERSIZE BUFSIZ @@ -424,47 +466,25 @@ /* @@ lua_number2int is a macro to convert lua_Number to int. -** CHANGE that if you know a faster way to convert a lua_Number to +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +** CHANGE them if you know a faster way to convert a lua_Number to ** int (with any rounding method and without throwing errors) in your ** system. In Pentium machines, a naive typecast from double to int ** in C is extremely slow, so any alternative is worth trying. */ -/* On a gcc/Pentium, resort to assembler */ -#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__i386) -#define lua_number2int(i,d) __asm__ ("fistpl %0":"=m"(i):"t"(d):"st") - -/* On Windows/Pentium, resort to assembler */ -#elif !defined(__STRICT_ANSI__) && defined(_MSC_VER) && defined(_M_IX86) -#define lua_number2int(i,d) \ - __asm fld d \ - __asm fistp i - - -/* on Pentium machines compliant with C99, you can try lrint */ -#elif defined (__i386) && defined(__STDC_VERSION__) && \ - (__STDC_VERSION__ >= 199900L) -#define lua_number2int(i,d) ((i)=lrint(d)) - -/* this option always works, but may be slow */ -#else -#define lua_number2int(i,d) ((i)=(int)(d)) - -#endif - - -/* -@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. -** CHANGE (see lua_number2int). -*/ -/* On a gcc or Windows/Pentium, resort to assembler */ -#if (defined(__GNUC__) && defined(__i386)) || \ - (defined(_MSC_VER) && defined(_M_IX86)) +/* On a Pentium, resort to a trick */ +#if !defined(LUA_ANSI) && !defined(__SSE2__) && \ + (defined(__i386) || defined (_M_IX86)) +union luai_Cast { double l_d; long l_l; }; +#define lua_number2int(i,d) \ + { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } #define lua_number2integer(i,n) lua_number2int(i, n) /* this option always works, but may be slow */ #else -#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) +#define lua_number2int(i,d) ((i)=(int)(d)) +#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) #endif @@ -479,13 +499,13 @@ ** =================================================================== */ +#define LUA_NUMBER double /* @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' @* over a number. */ -#define LUA_NUMBER double -#define LUAI_UACNUMBER LUA_NUMBER +#define LUAI_UACNUMBER double /* @@ -505,16 +525,16 @@ /* @@ The luai_num* macros define the primitive operations over numbers. */ -#define luai_numadd(a,b) ((a)+(b)) -#define luai_numsub(a,b) ((a)-(b)) -#define luai_nummul(a,b) ((a)*(b)) -#define luai_numdiv(a,b) ((a)/(b)) -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -#define luai_numpow(a,b) pow(a,b) -#define luai_numunm(a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numdiv(L,a,b) ((a)/(b)) +#define luai_nummod(L,a,b) ((a) - floor((a)/(b))*(b)) +#define luai_numpow(L,a,b) pow(a,b) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(L,a,b) ((a)==(b)) +#define luai_numlt(L,a,b) ((a)<(b)) +#define luai_numle(L,a,b) ((a)<=(b)) /* }================================================================== */ @@ -531,11 +551,11 @@ /* @@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. -** CHANGE them if you prefer to use longjmp/setjmp even with C++ or -** if want/don't want to use _longjmp/_setjmp instead of regular +** CHANGE them if you prefer to use longjmp/setjmp even with C++ +** or if want/don't to use _longjmp/_setjmp instead of regular ** longjmp/setjmp. By default, Lua handles errors with exceptions when -** compiling as C++ code, with _longjmp/_setjmp when compiling as C code -** in a Unix system, and with longjmp/setjmp otherwise. +** compiling as C++ code, with _longjmp/_setjmp when asked to use them, +** and with longjmp/setjmp otherwise. */ #if defined(__cplusplus) /* C++ exceptions */ @@ -544,8 +564,7 @@ { if ((c)->status == 0) (c)->status = -1; } #define luai_jmpbuf int /* dummy variable */ -#elif !defined(__STRICT_ANSI__) && (defined(unix) || defined(__unix) || \ - defined(__unix__)) +#elif defined(LUA_USE_ULONGJMP) /* in Unix, try _longjmp/_setjmp (more efficient) */ #define LUAI_THROW(L,c) _longjmp((c)->b, 1) #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } @@ -578,7 +597,7 @@ */ #if defined(loslib_c) || defined(luaall_c) -#if !defined(__STRICT_ANSI__) && defined(_POSIX_C_SOURCE) +#if !defined(LUA_ANSI) && defined(_POSIX_C_SOURCE) #include <unistd.h> #define LUA_TMPNAMBUFSIZE 32 #define lua_tmpnam(b,e) { \ @@ -593,6 +612,30 @@ #endif + +/* +@@ lua_popen spawns a new process connected to the current one through +@* the file streams. +** CHANGE it if you have a way to implement it in your system. +*/ +#if !defined(LUA_ANSI) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 2 + +#define lua_popen(L,c,m) popen(c,m) +#define lua_pclose(L,file) (pclose(file) != -1) + +#elif !defined(LUA_ANSI) && defined(_WIN32) + +#define lua_popen(L,c,m) _popen(c,m) +#define lua_pclose(L,file) (_pclose(file) != -1) + +#else + +#define lua_popen(L,c,m) \ + ((void)c, (void)m, luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)file, 0) + +#endif + /* @@ LUA_DL_* define which dynamic-library system Lua should use. ** CHANGE here if Lua has problems choosing the appropriate @@ -606,7 +649,7 @@ ** If you do not want any kind of dynamic library, undefine all these ** options (or just remove these definitions). */ -#if !defined(__STRICT_ANSI__) +#if !defined(LUA_ANSI) #if defined(_WIN32) #define LUA_DL_DLL #elif defined(__APPLE__) && defined(__MACH__) @@ -618,29 +661,6 @@ /* -@@ lua_lock/lua_unlock are macros for thread synchronization inside the -@* Lua core. This is an attempt to simplify the implementation of a -@* multithreaded version of Lua. -** CHANGE them only if you know what you are doing. All accesses to -** the global state and to global objects are synchronized. Because -** threads can read the stack of other threads (when running garbage -** collection), a thread must also synchronize any write-access to its -** own stack. Unsynchronized accesses are allowed only when reading its -** own stack, or when reading immutable fields from global objects (such -** as string values and udata values). -*/ -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) - - -/* -@@ lua_threadyield allows a thread switch in appropriate places in the core. -** CHANGE it only if you know what you are doing. (See lua_lock.) -*/ -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} - - -/* @@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State @* (the data goes just *before* the lua_State pointer). ** CHANGE (define) this if you really need that. This value must be @@ -650,11 +670,15 @@ /* -@@ luai_userstateopen allows user-specific initialization on new threads. -** CHANGE it if you defined LUAI_EXTRASPACE and need to initialize that -** data whenever a new lua_State is created. +@@ luai_userstate* allow user-specific actions on threads. +** CHANGE them if you defined LUAI_EXTRASPACE and need to do something +** extra when a thread is created/deleted/resumed/yielded. */ -#define luai_userstateopen(L) ((void)0) +#define luai_userstateopen(L) ((void)0) +#define luai_userstatefree(L) ((void)0) +#define luai_userstateresume(L,n) ((void)0) +#define luai_userstateyield(L,n) ((void)0) + @@ -668,3 +692,4 @@ #endif + diff --git a/src/lualib.h b/src/lualib.h index e1face32..f52bb888 100644 --- a/src/lualib.h +++ b/src/lualib.h @@ -1,5 +1,5 @@ /* -** $Id: lualib.h,v 1.34 2005/04/13 17:24:20 roberto Exp $ +** $Id: lualib.h,v 1.35 2005/08/10 18:06:58 roberto Exp $ ** Lua standard libraries ** See Copyright Notice in lua.h */ @@ -37,7 +37,7 @@ LUALIB_API int (luaopen_math) (lua_State *L); LUALIB_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" -LUALIB_API int (luaopen_loadlib) (lua_State *L); +LUALIB_API int (luaopen_package) (lua_State *L); /* open all previous libraries */ diff --git a/src/lundump.c b/src/lundump.c index 8ceb571b..726d021d 100644 --- a/src/lundump.c +++ b/src/lundump.c @@ -1,11 +1,10 @@ /* -** $Id: lundump.c,v 1.55 2005/05/12 00:26:50 lhf Exp $ +** $Id: lundump.c,v 1.58 2005/09/02 01:54:47 lhf Exp $ ** load pre-compiled Lua chunks ** See Copyright Notice in lua.h */ -#include <stdarg.h> -#include <stddef.h> +#include <string.h> #define lundump_c #define LUA_CORE @@ -21,113 +20,89 @@ #include "lundump.h" #include "lzio.h" -#define LoadByte (lu_byte) ezgetc +#ifdef LUAC_TRUST_BINARIES +#define IF(c,s) +#else +#define IF(c,s) if (c) error(S,s) +#endif typedef struct { lua_State* L; ZIO* Z; Mbuffer* b; - int swap; const char* name; +#ifdef LUAC_SWAP_ON_LOAD + int swap; +#endif } LoadState; -static void error (LoadState* S, const char* fmt, ...) -{ - const char *msg; - va_list argp; - va_start(argp,fmt); - msg=luaO_pushvfstring(S->L,fmt,argp); - va_end(argp); - luaO_pushfstring(S->L,"%s: %s",S->name,msg); - luaD_throw(S->L,LUA_ERRSYNTAX); -} +#ifdef LUAC_SWAP_ON_LOAD +static void LoadMem (LoadState* S, void* b, int n, size_t size); +#else +#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) +#endif -static int ezgetc (LoadState* S) -{ - int c=zgetc(S->Z); - if (c==EOZ) error(S,"unexpected end of file"); - return c; -} +#define LoadByte(S) (lu_byte)LoadChar(S) +#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) +#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) -static void ezread (LoadState* S, void* b, int n) +static void error(LoadState* S, const char* why) { - int r=luaZ_read(S->Z,b,n); - if (r!=0) error(S,"unexpected end of file"); + luaO_pushfstring(S->L,"%s: %s",S->name,why); + luaD_throw(S->L,LUA_ERRSYNTAX); } -static void LoadBlock (LoadState* S, void* b, size_t size) +static void LoadBlock(LoadState* S, void* b, size_t size) { - if (S->swap) - { - char* p=(char*) b+size-1; - int n=size; - while (n--) *p--=(char)ezgetc(S); - } - else - ezread(S,b,size); + size_t r=luaZ_read(S->Z,b,size); + IF (r!=0, "unexpected end"); } -static void LoadVector (LoadState* S, void* b, int m, size_t size) +static int LoadChar(LoadState* S) { - if (S->swap) - { - char* q=(char*) b; - while (m--) - { - char* p=q+size-1; - int n=size; - while (n--) *p--=(char)ezgetc(S); - q+=size; - } - } - else - ezread(S,b,m*size); -} - -static int LoadInt (LoadState* S) -{ - int x; - LoadBlock(S,&x,sizeof(x)); - if (x<0) error(S,"bad integer"); + char x; + LoadVar(S,x); return x; } -static size_t LoadSize (LoadState* S) +static int LoadInt(LoadState* S) { - size_t x; - LoadBlock(S,&x,sizeof(x)); + int x; + LoadVar(S,x); + IF (x<0, "bad integer"); return x; } -static lua_Number LoadNumber (LoadState* S) +static lua_Number LoadNumber(LoadState* S) { lua_Number x; - LoadBlock(S,&x,sizeof(x)); + LoadVar(S,x); return x; } -static TString* LoadString (LoadState* S) +static TString* LoadString(LoadState* S) { - size_t size=LoadSize(S); + size_t size; + LoadVar(S,size); if (size==0) return NULL; else { char* s=luaZ_openspace(S->L,S->b,size); - ezread(S,s,size); + LoadBlock(S,s,size); return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ } } -static void LoadCode (LoadState* S, Proto* f) +static void LoadCode(LoadState* S, Proto* f) { - int size=LoadInt(S); - f->code=luaM_newvector(S->L,size,Instruction); - f->sizecode=size; - LoadVector(S,f->code,size,sizeof(Instruction)); + int n=LoadInt(S); + f->code=luaM_newvector(S->L,n,Instruction); + f->sizecode=n; + LoadVector(S,f->code,n,sizeof(Instruction)); } -static void LoadLocals (LoadState* S, Proto* f) +static void LoadLocals(LoadState* S, Proto* f) { int i,n; n=LoadInt(S); @@ -142,29 +117,27 @@ static void LoadLocals (LoadState* S, Proto* f) } } -static void LoadLines (LoadState* S, Proto* f) +static void LoadLines(LoadState* S, Proto* f) { - int size=LoadInt(S); - f->lineinfo=luaM_newvector(S->L,size,int); - f->sizelineinfo=size; - LoadVector(S,f->lineinfo,size,sizeof(int)); + int n=LoadInt(S); + f->lineinfo=luaM_newvector(S->L,n,int); + f->sizelineinfo=n; + LoadVector(S,f->lineinfo,n,sizeof(int)); } -static void LoadUpvalues (LoadState* S, Proto* f) +static void LoadUpvalues(LoadState* S, Proto* f) { int i,n; n=LoadInt(S); - if (n!=0 && n!=f->nups) - error(S,"bad nupvalues (read %d; expected %d)",n,f->nups); f->upvalues=luaM_newvector(S->L,n,TString*); f->sizeupvalues=n; for (i=0; i<n; i++) f->upvalues[i]=NULL; for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); } -static Proto* LoadFunction (LoadState* S, TString* p); +static Proto* LoadFunction(LoadState* S, TString* p); -static void LoadConstants (LoadState* S, Proto* f) +static void LoadConstants(LoadState* S, Proto* f) { int i,n; n=LoadInt(S); @@ -174,14 +147,14 @@ static void LoadConstants (LoadState* S, Proto* f) for (i=0; i<n; i++) { TValue* o=&f->k[i]; - int t=LoadByte(S); + int t=LoadChar(S); switch (t) { case LUA_TNIL: setnilvalue(o); break; case LUA_TBOOLEAN: - setbvalue(o,LoadByte(S)); + setbvalue(o,LoadChar(S)); break; case LUA_TNUMBER: setnvalue(o,LoadNumber(S)); @@ -190,7 +163,7 @@ static void LoadConstants (LoadState* S, Proto* f) setsvalue2n(S->L,o,LoadString(S)); break; default: - error(S,"bad constant type (%d)",t); + IF (1, "bad constant"); break; } } @@ -201,7 +174,7 @@ static void LoadConstants (LoadState* S, Proto* f) for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); } -static Proto* LoadFunction (LoadState* S, TString* p) +static Proto* LoadFunction(LoadState* S, TString* p) { Proto* f=luaF_newproto(S->L); setptvalue2s(S->L,S->L->top,f); incr_top(S->L); @@ -217,46 +190,21 @@ static Proto* LoadFunction (LoadState* S, TString* p) LoadUpvalues(S,f); LoadConstants(S,f); LoadCode(S,f); -#ifndef TRUST_BINARIES - if (!luaG_checkcode(f)) error(S,"bad code"); -#endif + IF (!luaG_checkcode(f), "bad code"); S->L->top--; return f; } -static void LoadSignature (LoadState* S) -{ - const char* s=LUA_SIGNATURE; - while (*s!=0 && ezgetc(S)==*s) - ++s; - if (*s!=0) error(S,"bad signature"); -} - -static void TestSize (LoadState* S, int s, const char* what) -{ - int r=LoadByte(S); - if (r!=s) - error(S,"bad size of %s (read %d; expected %d)",what,r,s); -} - -#define V(v) v/16,v%16 - -static void LoadHeader (LoadState* S) +static void LoadHeader(LoadState* S) { - int version; - lua_Number x,tx=TEST_NUMBER; - LoadSignature(S); - version=LoadByte(S); - if (version!=VERSION) - error(S,"bad version (read %d.%d; expected %d.%d)",V(version),V(VERSION)); - S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */ - TestSize(S,sizeof(int),"int"); - TestSize(S,sizeof(size_t),"size_t"); - TestSize(S,sizeof(Instruction),"instruction"); - TestSize(S,sizeof(lua_Number),"number"); - x=LoadNumber(S); - if (x!=tx) - error(S,"unknown number format"); + char h[LUAC_HEADERSIZE]; + char s[LUAC_HEADERSIZE]; + luaU_header(h); + LoadBlock(S,s,LUAC_HEADERSIZE); +#ifdef LUAC_SWAP_ON_LOAD + S->swap=(s[6]!=h[6]); s[6]=h[6]; +#endif + IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); } /* @@ -279,10 +227,64 @@ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) } /* -** find byte order +* make header */ -int luaU_endianness (void) +void luaU_header (char* h) { int x=1; - return *(char*)&x; + memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); + h+=sizeof(LUA_SIGNATURE)-1; + *h++=(char)LUAC_VERSION; + *h++=(char)LUAC_FORMAT; + *h++=(char)*(char*)&x; + *h++=(char)sizeof(int); + *h++=(char)sizeof(size_t); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); + *h++=(char)(((lua_Number)0.5)==0); } + +#ifdef LUAC_SWAP_ON_LOAD +static void LoadMem (LoadState* S, void* b, int n, size_t size) +{ + LoadBlock(S,b,n*size); + if (S->swap) + { + char* p=(char*) b; + char c; + switch (size) + { + case 1: + break; + case 2: + while (n--) + { + c=p[0]; p[0]=p[1]; p[1]=c; + p+=2; + } + break; + case 4: + while (n--) + { + c=p[0]; p[0]=p[3]; p[3]=c; + c=p[1]; p[1]=p[2]; p[2]=c; + p+=4; + } + break; + case 8: + while (n--) + { + c=p[0]; p[0]=p[7]; p[7]=c; + c=p[1]; p[1]=p[6]; p[6]=c; + c=p[2]; p[2]=p[5]; p[5]=c; + c=p[3]; p[3]=p[4]; p[4]=c; + p+=8; + } + break; + default: + IF(1, "bad size"); + break; + } + } +} +#endif diff --git a/src/lundump.h b/src/lundump.h index 924cfb01..5de3c46e 100644 --- a/src/lundump.h +++ b/src/lundump.h @@ -1,5 +1,5 @@ /* -** $Id: lundump.h,v 1.35 2005/05/12 00:26:50 lhf Exp $ +** $Id: lundump.h,v 1.38 2005/09/02 01:54:47 lhf Exp $ ** load pre-compiled Lua chunks ** See Copyright Notice in lua.h */ @@ -10,22 +10,53 @@ #include "lobject.h" #include "lzio.h" +/* make it work with Lua 5.0 */ +#ifndef LUA_VERSION_NUM +#define LUAI_FUNC +#define lua_Writer lua_Chunkwriter +#endif + /* load one chunk; from lundump.c */ -LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char *name); +LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); -/* find byte order; from lundump.c */ -LUAI_FUNC int luaU_endianness (void); +/* make header; from lundump.c */ +LUAI_FUNC void luaU_header (char* h); /* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Chunkwriter w, void* data, int strip); +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); /* print one chunk; from print.c */ LUAI_FUNC void luaU_print (const Proto* f, int full); /* for header of binary files -- this is Lua 5.1 */ -#define VERSION 0x51 - -/* for testing native format of lua_Numbers */ -#define TEST_NUMBER ((lua_Number)31415926.0) +#define LUAC_VERSION 0x51 + +/* for header of binary files -- this is the official format */ +#define LUAC_FORMAT 0 + +/* size of header of binary files */ +#define LUAC_HEADERSIZE 12 + +/* make it work with Lua 5.0 */ +#ifndef LUA_VERSION_NUM +#define LUA_SIGNATURE "\033Lua" +#define TValue TObject +#define rawtsvalue tsvalue +#define linedefined lineDefined +#define lastlinedefined lineDefined +#define setptvalue2s(L,t,f) +#undef setsvalue2n +#define setsvalue2n(L,x,y) setsvalue(x,y) +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") +#undef LUAC_VERSION +#define LUAC_VERSION 0x50 +#ifdef lapi_c +#define luaU_dump(L,f,w,d) (luaU_dump)(L,f,w,d,0) +#endif +#ifdef ldo_c +#define luaU_undump(L,z,b) (luaU_undump)(L,z,b,z->name) +#endif +#endif #endif @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.44 2005/05/17 19:49:15 roberto Exp $ +** $Id: lvm.c,v 2.55 2005/09/09 18:23:35 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -226,7 +226,7 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { if (ttype(l) != ttype(r)) return luaG_ordererror(L, l, r); else if (ttisnumber(l)) - return luai_numlt(nvalue(l), nvalue(r)); + return luai_numlt(L, nvalue(l), nvalue(r)); else if (ttisstring(l)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) @@ -240,7 +240,7 @@ static int lessequal (lua_State *L, const TValue *l, const TValue *r) { if (ttype(l) != ttype(r)) return luaG_ordererror(L, l, r); else if (ttisnumber(l)) - return luai_numle(nvalue(l), nvalue(r)); + return luai_numle(L, nvalue(l), nvalue(r)); else if (ttisstring(l)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ @@ -256,7 +256,7 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { lua_assert(ttype(t1) == ttype(t2)); switch (ttype(t1)) { case LUA_TNIL: return 1; - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TNUMBER: return luai_numeq(L, nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); case LUA_TUSERDATA: { @@ -311,26 +311,26 @@ void luaV_concat (lua_State *L, int total, int last) { } -static StkId Arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { +static void Arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op) { TValue tempb, tempc; const TValue *b, *c; if ((b = luaV_tonumber(rb, &tempb)) != NULL && (c = luaV_tonumber(rc, &tempc)) != NULL) { lua_Number nb = nvalue(b), nc = nvalue(c); switch (op) { - case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; - case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; - case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; - case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; - case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; - case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; + case TM_ADD: setnvalue(ra, luai_numadd(L, nb, nc)); break; + case TM_SUB: setnvalue(ra, luai_numsub(L, nb, nc)); break; + case TM_MUL: setnvalue(ra, luai_nummul(L, nb, nc)); break; + case TM_DIV: setnvalue(ra, luai_numdiv(L, nb, nc)); break; + case TM_MOD: setnvalue(ra, luai_nummod(L, nb, nc)); break; + case TM_POW: setnvalue(ra, luai_numpow(L, nb, nc)); break; + case TM_UNM: setnvalue(ra, luai_numunm(L, nb)); break; default: lua_assert(0); break; } } else if (!call_binTM(L, rb, rc, ra, op)) luaG_aritherror(L, rb, rc); - return L->base; } @@ -358,15 +358,12 @@ static StkId Arith (lua_State *L, StkId ra, const TValue *rb, #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } -StkId luaV_execute (lua_State *L, int nexeccalls) { +void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; - callentry: /* entry point when calling new functions */ - if (L->hookmask & LUA_MASKCALL) - luaD_callhook(L, LUA_HOOKCALL, -1); - retentry: /* entry point when returning to old functions */ + reentry: /* entry point */ pc = L->savedpc; cl = &clvalue(L->ci->func)->l; base = L->base; @@ -380,7 +377,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { traceexec(L, pc); if (L->status == LUA_YIELD) { /* did hook yield? */ L->savedpc = pc - 1; - return NULL; + return; } base = L->base; } @@ -462,7 +459,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { lua_Number nb = nvalue(rb), nc = nvalue(rc); - setnvalue(ra, luai_numadd(nb, nc)); + setnvalue(ra, luai_numadd(L, nb, nc)); } else Protect(Arith(L, ra, rb, rc, TM_ADD)); @@ -473,7 +470,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { lua_Number nb = nvalue(rb), nc = nvalue(rc); - setnvalue(ra, luai_numsub(nb, nc)); + setnvalue(ra, luai_numsub(L, nb, nc)); } else Protect(Arith(L, ra, rb, rc, TM_SUB)); @@ -484,7 +481,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { lua_Number nb = nvalue(rb), nc = nvalue(rc); - setnvalue(ra, luai_nummul(nb, nc)); + setnvalue(ra, luai_nummul(L, nb, nc)); } else Protect(Arith(L, ra, rb, rc, TM_MUL)); @@ -495,7 +492,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { lua_Number nb = nvalue(rb), nc = nvalue(rc); - setnvalue(ra, luai_numdiv(nb, nc)); + setnvalue(ra, luai_numdiv(L, nb, nc)); } else Protect(Arith(L, ra, rb, rc, TM_DIV)); @@ -506,7 +503,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { lua_Number nb = nvalue(rb), nc = nvalue(rc); - setnvalue(ra, luai_nummod(nb, nc)); + setnvalue(ra, luai_nummod(L, nb, nc)); } else Protect(Arith(L, ra, rb, rc, TM_MOD)); @@ -517,25 +514,20 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { lua_Number nb = nvalue(rb), nc = nvalue(rc); - setnvalue(ra, luai_numpow(nb, nc)); + setnvalue(ra, luai_numpow(L, nb, nc)); } else Protect(Arith(L, ra, rb, rc, TM_POW)); continue; } case OP_UNM: { - const TValue *rb = RB(i); - TValue temp; - if (tonumber(rb, &temp)) { + TValue *rb = RB(i); + if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); - setnvalue(ra, luai_numunm(nb)); + setnvalue(ra, luai_numunm(L, nb)); } else { - rb = RB(i); /* `tonumber' erased `rb' */ - Protect( - if (!call_binTM(L, rb, &luaO_nilobject, ra, TM_UNM)) - luaG_aritherror(L, rb, &luaO_nilobject); - ) + Protect(Arith(L, ra, rb, rb, TM_UNM)); } continue; } @@ -544,16 +536,23 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { setbvalue(ra, res); continue; } - case OP_SIZ: { + case OP_LEN: { const TValue *rb = RB(i); - if (ttype(rb) == LUA_TTABLE) { - setnvalue(ra, cast(lua_Number, luaH_getn(hvalue(rb)))); - } - else { /* try metamethod */ - Protect( - if (!call_binTM(L, rb, &luaO_nilobject, ra, TM_SIZ)) - luaG_typeerror(L, rb, "get size of"); - ) + switch (ttype(rb)) { + case LUA_TTABLE: { + setnvalue(ra, cast(lua_Number, luaH_getn(hvalue(rb)))); + break; + } + case LUA_TSTRING: { + setnvalue(ra, cast(lua_Number, tsvalue(rb)->len)); + break; + } + default: { /* try metamethod */ + Protect( + if (!call_binTM(L, rb, &luaO_nilobject, ra, TM_LEN)) + luaG_typeerror(L, rb, "get length of"); + ) + } } continue; } @@ -569,8 +568,10 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { continue; } case OP_EQ: { + TValue *rb = RKB(i); + TValue *rc = RKC(i); Protect( - if (equalobj(L, RKB(i), RKC(i)) == GETARG_A(i)) + if (equalobj(L, rb, rc) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; @@ -593,6 +594,12 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { continue; } case OP_TEST: { + if (l_isfalse(ra) == GETARG_C(i)) pc++; + else + dojump(L, pc, GETARG_sBx(*pc) + 1); + continue; + } + case OP_TESTSET: { TValue *rb = RB(i); if (l_isfalse(rb) == GETARG_C(i)) pc++; else { @@ -609,7 +616,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { switch (luaD_precall(L, ra, nresults)) { case PCRLUA: { nexeccalls++; - goto callentry; /* restart luaV_execute over new Lua function */ + goto reentry; /* restart luaV_execute over new Lua function */ } case PCRC: { /* it was a C function (`precall' called it); adjust results */ @@ -618,7 +625,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { continue; } default: { - return NULL; + return; /* yield */ } } } @@ -643,15 +650,14 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { ci->savedpc = L->savedpc; ci->tailcalls++; /* one more call lost */ L->ci--; /* remove new frame */ - goto callentry; + goto reentry; } - case PCRC: { - /* it was a C function (`precall' called it) */ + case PCRC: { /* it was a C function (`precall' called it) */ base = L->base; continue; } default: { - return NULL; + return; /* yield */ } } } @@ -660,22 +666,21 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { if (b != 0) L->top = ra+b-1; if (L->openupval) luaF_close(L, base); L->savedpc = pc; + b = luaD_poscall(L, ra); if (--nexeccalls == 0) /* was previous function running `here'? */ - return ra; /* no: return */ + return; /* no: return */ else { /* yes: continue its execution */ - int nresults = L->ci->nresults; - lua_assert(isLua(L->ci - 1)); - lua_assert(GET_OPCODE(*((L->ci - 1)->savedpc - 1)) == OP_CALL); - luaD_poscall(L, nresults, ra); - if (nresults >= 0) L->top = L->ci->top; - goto retentry; + if (b) L->top = L->ci->top; + lua_assert(isLua(L->ci)); + lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); + goto reentry; } } case OP_FORLOOP: { lua_Number step = nvalue(ra+2); - lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ + lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ lua_Number limit = nvalue(ra+1); - if (step > 0 ? luai_numle(idx, limit) : luai_numle(limit, idx)) { + if (step > 0 ? luai_numle(L, idx, limit) : luai_numle(L, limit, idx)) { dojump(L, pc, GETARG_sBx(i)); /* jump back */ setnvalue(ra, idx); /* update internal index... */ setnvalue(ra+3, idx); /* ...and external index */ @@ -693,7 +698,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { luaG_runerror(L, LUA_QL("for") " limit must be a number"); else if (!tonumber(pstep, ra+2)) luaG_runerror(L, LUA_QL("for") " step must be a number"); - setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); + setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); dojump(L, pc, GETARG_sBx(i)); continue; } @@ -720,7 +725,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { int last; Table *h; if (n == 0) { - n = L->top - ra - 1; + n = cast(int, L->top - ra) - 1; L->top = L->ci->top; } if (c == 0) c = cast(int, *pc++); @@ -764,15 +769,21 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { int b = GETARG_B(i) - 1; int j; CallInfo *ci = L->ci; - int n = ci->base - ci->func - cl->p->numparams - 1; + int n = cast(int, ci->base - ci->func) - cl->p->numparams - 1; if (b == LUA_MULTRET) { + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ b = n; L->top = ra + n; } - for (j=0; j<b && j<n; j++) - setobjs2s(L, ra+j, ci->base - n + j); - for (; j<b; j++) - setnilvalue(ra+j); + for (j = 0; j < b; j++) { + if (j < n) { + setobjs2s(L, ra + j, ci->base - n + j); + } + else { + setnilvalue(ra + j); + } + } continue; } } @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.4 2005/04/25 19:24:10 roberto Exp $ +** $Id: lvm.h,v 2.5 2005/08/22 18:54:49 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -30,7 +30,7 @@ LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val); -LUAI_FUNC StkId luaV_execute (lua_State *L, int nexeccalls); +LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); #endif @@ -1,5 +1,5 @@ /* -** $Id: lzio.c,v 1.30 2005/05/17 19:49:15 roberto Exp $ +** $Id: lzio.c,v 1.31 2005/06/03 20:15:29 roberto Exp $ ** a generic input stream interface ** See Copyright Notice in lua.h */ @@ -34,10 +34,12 @@ int luaZ_fill (ZIO *z) { int luaZ_lookahead (ZIO *z) { if (z->n == 0) { - int c = luaZ_fill(z); - if (c == EOZ) return c; - z->n++; - z->p--; + if (luaZ_fill(z) == EOZ) + return EOZ; + else { + z->n++; /* luaZ_fill removed first byte; put back it */ + z->p--; + } } return char2int(*z->p); } @@ -56,14 +58,8 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { size_t luaZ_read (ZIO *z, void *b, size_t n) { while (n) { size_t m; - if (z->n == 0) { - if (luaZ_fill(z) == EOZ) - return n; /* return number of missing bytes */ - else { - ++z->n; /* filbuf removed first byte; put back it */ - --z->p; - } - } + if (luaZ_lookahead(z) == EOZ) + return n; /* return number of missing bytes */ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ memcpy(b, z->p, m); z->n -= m; diff --git a/src/print.c b/src/print.c index 85308705..8090a2d5 100644 --- a/src/print.c +++ b/src/print.c @@ -1,5 +1,5 @@ /* -** $Id: print.c,v 1.50 2005/05/12 00:26:50 lhf Exp $ +** $Id: print.c,v 1.52 2005/06/08 14:40:44 lhf Exp $ ** print bytecodes ** See Copyright Notice in lua.h */ @@ -135,6 +135,10 @@ static void PrintCode(const Proto* f) case OP_CLOSURE: printf("\t; %p",VOID(f->p[bx])); break; + case OP_SETLIST: + if (c==0) printf("\t; %d",(int)code[++pc]); + else printf("\t; %d",c); + break; default: break; } @@ -158,7 +162,7 @@ static void PrintHeader(const Proto* f) (f->linedefined==0)?"main":"function",s, f->linedefined,f->lastlinedefined, S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); - printf("%d%s param%s, %d stack%s, %d upvalue%s, ", + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", f->numparams,f->is_vararg?"+":"",SS(f->numparams), S(f->maxstacksize),S(f->nups)); printf("%d local%s, %d constant%s, %d function%s\n", |