diff options
author | Peter Drahoš <drahosp@gmail.com> | 2011-12-17 00:10:30 +0100 |
---|---|---|
committer | Peter Drahoš <drahosp@gmail.com> | 2011-12-17 00:10:30 +0100 |
commit | 0713c5ca0b7b60ab525019ee77200d19f7c4be03 (patch) | |
tree | 503047beba08224e011f877dc0d23ca455e6b2cf | |
parent | 9358cd648bc92ccdd4b3492375a53f2c8ca18bbc (diff) | |
download | lua-0713c5ca0b7b60ab525019ee77200d19f7c4be03.tar.gz |
Lua 5.2 release.
-rw-r--r--[-rwxr-xr-x] | Makefile | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | README | 2 | ||||
-rw-r--r-- | dist.info | 2 | ||||
-rwxr-xr-x | doc/alert.png | bin | 1411 -> 0 bytes | |||
-rw-r--r--[-rwxr-xr-x] | src/Makefile | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lapi.c | 129 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lapi.h | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lauxlib.c | 35 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lauxlib.h | 39 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lbaselib.c | 114 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lbitlib.c | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lcode.c | 22 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lcode.h | 3 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lcorolib.c | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lctype.c | 5 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lctype.h | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ldblib.c | 11 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ldebug.c | 204 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ldebug.h | 20 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ldo.c | 61 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ldo.h | 7 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ldump.c | 6 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lfunc.c | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lfunc.h | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lgc.c | 162 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lgc.h | 6 | ||||
-rw-r--r--[-rwxr-xr-x] | src/linit.c | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/liolib.c | 106 | ||||
-rw-r--r--[-rwxr-xr-x] | src/llex.c | 93 | ||||
-rw-r--r--[-rwxr-xr-x] | src/llex.h | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | src/llimits.h | 24 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lmathlib.c | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lmem.c | 7 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lmem.h | 10 | ||||
-rw-r--r--[-rwxr-xr-x] | src/loadlib.c | 129 | ||||
-rw-r--r-- | src/loadlib_rel.c | 131 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lobject.c | 13 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lobject.h | 68 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lopcodes.c | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lopcodes.h | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | src/loslib.c | 28 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lparser.c | 172 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lparser.h | 13 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lstate.c | 13 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lstate.h | 6 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lstring.c | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lstring.h | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lstrlib.c | 24 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ltable.c | 73 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ltable.h | 8 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ltablib.c | 7 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ltm.c | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/ltm.h | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lua.c | 42 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lua.h | 20 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lua.hpp | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/luac.c | 9 | ||||
-rw-r--r-- | src/luaconf.h.in | 38 | ||||
-rwxr-xr-x | src/luaconf.h.orig | 528 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lualib.h | 5 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lundump.c | 6 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lundump.h | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lvm.c | 58 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lvm.h | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lzio.c | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | src/lzio.h | 8 |
66 files changed, 1165 insertions, 1327 deletions
@@ -62,13 +62,13 @@ install: dummy cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) - #cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) + cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) uninstall: cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN) cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC) cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB) - #cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) + cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN) local: $(MAKE) install INSTALL_TOP=../install @@ -1,5 +1,5 @@ -This is Lua 5.2 (beta), released on 05 Jul 2011. +This is Lua 5.2, released on 12 Dec 2011. For installation instructions, license details, and further information about Lua, see doc/readme.html. @@ -1,7 +1,7 @@ --- This file is part of LuaDist project name = "lua" -version = "5.2-beta" +version = "5.2" desc = "Lua is a powerful, fast, light-weight, embeddable scripting language." author = "Roberto Ierusalimschy, Waldemar Celes, Luiz Henrique de Figueiredo" diff --git a/doc/alert.png b/doc/alert.png Binary files differdeleted file mode 100755 index 4938074..0000000 --- a/doc/alert.png +++ /dev/null diff --git a/src/Makefile b/src/Makefile index a77f35d..bba1693 100755..100644 --- a/src/Makefile +++ b/src/Makefile @@ -112,6 +112,7 @@ mingw: $(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe + $(MAKE) "LUAC_T=luac.exe" luac.exe posix: $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" diff --git a/src/lapi.c b/src/lapi.c index 7761419..e96ceb9 100755..100644 --- a/src/lapi.c +++ b/src/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.149 2011/06/13 14:13:06 roberto Exp $ +** $Id: lapi.c,v 2.159 2011/11/30 12:32:05 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -34,9 +34,13 @@ const char lua_ident[] = "$LuaAuthors: " LUA_AUTHORS " $"; +/* value at a non-valid index */ +#define NONVALIDVALUE cast(TValue *, luaO_nilobject) -#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject, \ - "invalid index") +/* corresponding test */ +#define isvalid(o) ((o) != luaO_nilobject) + +#define api_checkvalidindex(L, i) api_check(L, isvalid(i), "invalid index") static TValue *index2addr (lua_State *L, int idx) { @@ -44,7 +48,7 @@ static TValue *index2addr (lua_State *L, int idx) { if (idx > 0) { TValue *o = ci->func + idx; api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); - if (o >= L->top) return cast(TValue *, luaO_nilobject); + if (o >= L->top) return NONVALIDVALUE; else return o; } else if (idx > LUA_REGISTRYINDEX) { @@ -57,12 +61,10 @@ static TValue *index2addr (lua_State *L, int idx) { idx = LUA_REGISTRYINDEX - idx; api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); if (ttislcf(ci->func)) /* light C function? */ - return cast(TValue *, luaO_nilobject); /* it has no upvalues */ + return NONVALIDVALUE; /* it has no upvalues */ else { CClosure *func = clCvalue(ci->func); - return (idx <= func->nupvalues) - ? &func->upvalue[idx-1] - : cast(TValue *, luaO_nilobject); + return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; } } } @@ -237,7 +239,7 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { LUA_API int lua_type (lua_State *L, int idx) { StkId o = index2addr(L, idx); - return (o == luaO_nilobject) ? LUA_TNONE : ttypenv(o); + return (isvalid(o) ? ttypenv(o) : LUA_TNONE); } @@ -275,8 +277,7 @@ LUA_API int lua_isuserdata (lua_State *L, int idx) { LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { StkId o1 = index2addr(L, index1); StkId o2 = index2addr(L, index2); - return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 - : luaV_rawequalobj(o1, o2); + return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; } @@ -305,17 +306,17 @@ LUA_API void lua_arith (lua_State *L, int op) { LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { StkId o1, o2; - int i; + int i = 0; lua_lock(L); /* may call tag method */ o1 = index2addr(L, index1); o2 = index2addr(L, index2); - if (o1 == luaO_nilobject || o2 == luaO_nilobject) - i = 0; - else switch (op) { - case LUA_OPEQ: i = equalobj(L, o1, o2); break; - case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; - case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; - default: api_check(L, 0, "invalid option"); i = 0; + if (isvalid(o1) && isvalid(o2)) { + switch (op) { + case LUA_OPEQ: i = equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); + } } lua_unlock(L); return i; @@ -595,6 +596,17 @@ LUA_API int lua_pushthread (lua_State *L) { */ +LUA_API void lua_getglobal (lua_State *L, const char *var) { + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt; /* global table */ + lua_lock(L); + gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + setsvalue2s(L, L->top++, luaS_new(L, var)); + luaV_gettable(L, gt, L->top - 1, L->top - 1); + lua_unlock(L); +} + + LUA_API void lua_gettable (lua_State *L, int idx) { StkId t; lua_lock(L); @@ -628,11 +640,24 @@ LUA_API void lua_rawget (lua_State *L, int idx) { LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { - StkId o; + StkId t; lua_lock(L); - o = index2addr(L, idx); - api_check(L, ttistable(o), "table expected"); - setobj2s(L, L->top, luaH_getint(hvalue(o), n)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(t), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2s(L, L->top, luaH_get(hvalue(t), &k)); api_incr_top(L); lua_unlock(L); } @@ -700,6 +725,19 @@ LUA_API void lua_getuservalue (lua_State *L, int idx) { */ +LUA_API void lua_setglobal (lua_State *L, const char *var) { + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt; /* global table */ + lua_lock(L); + api_checknelems(L, 1); + gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + setsvalue2s(L, L->top++, luaS_new(L, var)); + luaV_settable(L, gt, L->top - 1, L->top - 2); + L->top -= 2; /* pop value and key */ + lua_unlock(L); +} + + LUA_API void lua_settable (lua_State *L, int idx) { StkId t; lua_lock(L); @@ -732,6 +770,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) { t = index2addr(L, idx); api_check(L, ttistable(t), "table expected"); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); + invalidateTMcache(hvalue(t)); luaC_barrierback(L, gcvalue(t), L->top-1); L->top -= 2; lua_unlock(L); @@ -739,13 +778,28 @@ LUA_API void lua_rawset (lua_State *L, int idx) { LUA_API void lua_rawseti (lua_State *L, int idx, int n) { - StkId o; + StkId t; lua_lock(L); api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttistable(o), "table expected"); - setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1); - luaC_barrierback(L, gcvalue(o), L->top-1); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + luaH_setint(L, hvalue(t), n, L->top - 1); + luaC_barrierback(L, gcvalue(t), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); + luaC_barrierback(L, gcvalue(t), L->top - 1); L->top--; lua_unlock(L); } @@ -914,13 +968,13 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname) { + const char *chunkname, const char *mode) { ZIO z; int status; lua_lock(L); if (!chunkname) chunkname = "?"; luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname); + status = luaD_protectedparser(L, &z, chunkname, mode); if (status == LUA_OK) { /* no errors? */ LClosure *f = clLvalue(L->top - 1); /* get newly created function */ if (f->nupvalues == 1) { /* does it have one upvalue? */ @@ -1128,7 +1182,6 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - static const char *aux_upvalue (StkId fi, int n, TValue **val, GCObject **owner) { switch (ttype(fi)) { @@ -1141,15 +1194,13 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, } case LUA_TLCL: { /* Lua closure */ LClosure *f = clLvalue(fi); - const char *name; + TString *name; Proto *p = f->p; if (!(1 <= n && n <= p->sizeupvalues)) return NULL; *val = f->upvals[n-1]->v; if (owner) *owner = obj2gco(f->upvals[n - 1]); - name = getstr(p->upvalues[n-1].name); - if (name == NULL) /* no debug information? */ - name = ""; - return name; + name = p->upvalues[n-1].name; + return (name == NULL) ? "" : getstr(name); } default: return NULL; /* not a closure */ } @@ -1158,7 +1209,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; - TValue *val; + TValue *val = NULL; /* to avoid warnings */ lua_lock(L); name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); if (name) { @@ -1172,8 +1223,8 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { const char *name; - TValue *val; - GCObject *owner; + TValue *val = NULL; /* to avoid warnings */ + GCObject *owner = NULL; /* to avoid warnings */ StkId fi; lua_lock(L); fi = index2addr(L, funcindex); diff --git a/src/lapi.h b/src/lapi.h index 0909a39..0909a39 100755..100644 --- a/src/lapi.h +++ b/src/lapi.h diff --git a/src/lauxlib.c b/src/lauxlib.c index b765cfd..0aa80fd 100755..100644 --- a/src/lauxlib.c +++ b/src/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.233 2011/06/16 14:11:04 roberto Exp $ +** $Id: lauxlib.c,v 1.240 2011/12/06 16:33:55 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -41,11 +41,10 @@ ** return 1 + string at top if find a good name. */ static int findfield (lua_State *L, int objidx, int level) { - int found = 0; if (level == 0 || !lua_istable(L, -1)) return 0; /* not found */ lua_pushnil(L); /* start 'next' loop */ - while (!found && lua_next(L, -2)) { /* for each pair in table */ + while (lua_next(L, -2)) { /* for each pair in table */ if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ if (lua_rawequal(L, objidx, -1)) { /* found object? */ lua_pop(L, 1); /* remove value (but keep name) */ @@ -86,7 +85,7 @@ static void pushfuncname (lua_State *L, lua_Debug *ar) { lua_pushfstring(L, "function " LUA_QS, ar->name); else if (*ar->what == 'm') /* main? */ lua_pushfstring(L, "main chunk"); - else if (*ar->what == 'C' || *ar->what == 't') { + else if (*ar->what == 'C') { if (pushglobalfuncname(L, ar)) { lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); lua_remove(L, -2); /* remove name */ @@ -270,7 +269,7 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) { */ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ + luaL_getmetatable(L, tname); /* try to get metatable */ if (!lua_isnil(L, -1)) /* name already in use? */ return 0; /* leave previous value on top, but return 0 */ lua_pop(L, 1); @@ -291,7 +290,7 @@ LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { void *p = lua_touserdata(L, ud); if (p != NULL) { /* value is a userdata? */ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ + luaL_getmetatable(L, tname); /* get correct metatable */ if (!lua_rawequal(L, -1, -2)) /* not the same? */ p = NULL; /* value is a userdata with wrong metatable */ lua_pop(L, 2); /* remove both metatables */ @@ -331,7 +330,9 @@ LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { - if (!lua_checkstack(L, space)) { + /* keep some extra space to run error routines, if needed */ + const int extra = LUA_MINSTACK; + if (!lua_checkstack(L, space + extra)) { if (msg) luaL_error(L, "stack overflow (%s)", msg); else @@ -566,7 +567,7 @@ typedef struct LoadF { static const char *getF (lua_State *L, void *ud, size_t *size) { LoadF *lf = (LoadF *)ud; - (void)L; + (void)L; /* not used */ if (lf->n > 0) { /* are there pre-read characters to be read? */ *size = lf->n; /* return them (chars already in buffer) */ lf->n = 0; /* no more pre-read characters */ @@ -623,7 +624,8 @@ static int skipcomment (LoadF *lf, int *cp) { } -LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { LoadF lf; int status, readstatus; int c; @@ -646,7 +648,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { } if (c != EOF) lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); readstatus = ferror(lf.f); if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (readstatus) { @@ -666,7 +668,7 @@ typedef struct LoadS { static const char *getS (lua_State *L, void *ud, size_t *size) { LoadS *ls = (LoadS *)ud; - (void)L; + (void)L; /* not used */ if (ls->size == 0) return NULL; *size = ls->size; ls->size = 0; @@ -674,12 +676,12 @@ static const char *getS (lua_State *L, void *ud, size_t *size) { } -LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name) { +LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, + const char *name, const char *mode) { LoadS ls; ls.s = buff; ls.size = size; - return lua_load(L, getS, &ls, name); + return lua_load(L, getS, &ls, name, mode); } @@ -913,8 +915,7 @@ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; - (void)osize; + (void)ud; (void)osize; /* not used */ if (nsize == 0) { free(ptr); return NULL; @@ -943,7 +944,7 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { if (v != lua_version(NULL)) luaL_error(L, "multiple Lua VMs detected"); else if (*v != ver) - luaL_error(L, "version mismatch: app. needs %d, Lua core provides %f", + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", ver, *v); /* check conversions number -> integer types */ lua_pushnumber(L, -(lua_Number)0x1234); diff --git a/src/lauxlib.h b/src/lauxlib.h index a7aa0d7..ac4d15f 100755..100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.117 2011/06/16 14:10:12 roberto Exp $ +** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -72,9 +72,13 @@ LUALIB_API int (luaL_execresult) (lua_State *L, int stat); LUALIB_API int (luaL_ref) (lua_State *L, int t); LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); -LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); -LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, - const char *name); +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); LUALIB_API lua_State *(luaL_newstate) (void); @@ -127,6 +131,8 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + /* ** {====================================================== @@ -163,6 +169,31 @@ LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); /* }====================================================== */ + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + /* compatibility with old module system */ #if defined(LUA_COMPAT_MODULE) diff --git a/src/lbaselib.c b/src/lbaselib.c index e4daf5d..1dfae30 100755..100644 --- a/src/lbaselib.c +++ b/src/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.264 2011/07/05 12:49:35 roberto Exp $ +** $Id: lbaselib.c,v 1.273 2011/11/30 13:03:24 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -46,20 +46,22 @@ static int luaB_print (lua_State *L) { #define SPACECHARS " \f\n\r\t\v" static int luaB_tonumber (lua_State *L) { - int base = luaL_optint(L, 2, 10); - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - if (base == 10) { /* standard conversion */ - luaL_checkany(L, 1); - if (lua_isnumber(L, 1)) { - lua_pushnumber(L, lua_tonumber(L, 1)); + if (lua_isnoneornil(L, 2)) { /* standard conversion */ + int isnum; + lua_Number n = lua_tonumberx(L, 1, &isnum); + if (isnum) { + lua_pushnumber(L, n); return 1; - } /* else not a number */ + } /* else not a number; must be something */ + luaL_checkany(L, 1); } else { size_t l; const char *s = luaL_checklstring(L, 1, &l); const char *e = s + l; /* end point for 's' */ + int base = luaL_checkint(L, 2); int neg = 0; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); s += strspn(s, SPACECHARS); /* skip initial spaces */ if (*s == '-') { s++; neg = 1; } /* handle signal */ else if (*s == '+') s++; @@ -158,7 +160,7 @@ static int luaB_rawset (lua_State *L) { static int luaB_collectgarbage (lua_State *L) { static const char *const opts[] = {"stop", "restart", "collect", "count", "step", "setpause", "setstepmul", - "setmajorinc", "isrunning", "gen", "inc", NULL}; + "setmajorinc", "isrunning", "generational", "incremental", NULL}; static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; @@ -253,7 +255,14 @@ static int load_aux (lua_State *L, int status) { static int luaB_loadfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); - return load_aux(L, luaL_loadfile(L, fname)); + const char *mode = luaL_optstring(L, 2, NULL); + int env = !lua_isnone(L, 3); /* 'env' parameter? */ + int status = luaL_loadfilex(L, fname, mode); + if (status == LUA_OK && env) { /* 'env' parameter? */ + lua_pushvalue(L, 3); + lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */ + } + return load_aux(L, status); } @@ -264,26 +273,6 @@ static int luaB_loadfile (lua_State *L) { */ -typedef struct { -char c; - const char *mode; -} loaddata; - - -/* -** check whether a chunk (prefix in 's') satisfies given 'mode' -** ('t' for text, 'b' for binary). Returns error message (also -** pushed on the stack) in case of errors. -*/ -static const char *checkrights (lua_State *L, const char *mode, const char *s) { - if (strchr(mode, 'b') == NULL && *s == LUA_SIGNATURE[0]) - return lua_pushstring(L, "attempt to load a binary chunk"); - if (strchr(mode, 't') == NULL && *s != LUA_SIGNATURE[0]) - return lua_pushstring(L, "attempt to load a text chunk"); - return NULL; /* chunk in allowed format */ -} - - /* ** reserved slot, above all arguments, to hold a copy of the returned ** string to avoid it being collected while parsed. 'load' has four @@ -299,8 +288,7 @@ static const char *checkrights (lua_State *L, const char *mode, const char *s) { ** reserved slot inside the stack. */ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - const char *s; - loaddata *ld = (loaddata *)ud; + (void)(ud); /* not used */ luaL_checkstack(L, 2, "too many nested functions"); lua_pushvalue(L, 1); /* get function */ lua_call(L, 0, 1); /* call it */ @@ -308,19 +296,10 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { *size = 0; return NULL; } - else if ((s = lua_tostring(L, -1)) != NULL) { - if (ld->mode != NULL) { /* first time? */ - s = checkrights(L, ld->mode, s); /* check mode */ - ld->mode = NULL; /* to avoid further checks */ - if (s) luaL_error(L, s); - } - lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ - return lua_tolstring(L, RESERVEDSLOT, size); - } - else { + else if (!lua_isstring(L, -1)) luaL_error(L, "reader function must return a string"); - return NULL; /* to avoid warnings */ - } + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); } @@ -332,16 +311,13 @@ static int luaB_load (lua_State *L) { const char *mode = luaL_optstring(L, 3, "bt"); if (s != NULL) { /* loading a string? */ const char *chunkname = luaL_optstring(L, 2, s); - status = (checkrights(L, mode, s) != NULL) - || luaL_loadbuffer(L, s, l, chunkname); + status = luaL_loadbufferx(L, s, l, chunkname, mode); } else { /* loading from a reader function */ const char *chunkname = luaL_optstring(L, 2, "=(load)"); - loaddata ld; - ld.mode = mode; luaL_checktype(L, 1, LUA_TFUNCTION); lua_settop(L, RESERVEDSLOT); /* create reserved slot */ - status = lua_load(L, generic_reader, &ld, chunkname); + status = lua_load(L, generic_reader, NULL, chunkname, mode); } if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */ lua_pushvalue(L, 4); /* environment for loaded function */ @@ -390,27 +366,32 @@ static int luaB_select (lua_State *L) { } -static int pcallcont (lua_State *L) { - int errfunc = 0; /* =0 to avoid warnings */ - int status = lua_getctx(L, &errfunc); - lua_assert(status != LUA_OK); - lua_pushboolean(L, (status == LUA_YIELD)); /* first result (status) */ - if (errfunc) /* came from xpcall? */ - lua_replace(L, 1); /* put first result in place of error function */ - else /* came from pcall */ - lua_insert(L, 1); /* open space for first result */ +static int finishpcall (lua_State *L, int status) { + if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ + lua_settop(L, 0); /* create space for return values */ + lua_pushboolean(L, 0); + lua_pushstring(L, "stack overflow"); + return 2; /* return false, msg */ + } + lua_pushboolean(L, status); /* first result (status) */ + lua_replace(L, 1); /* put first result in first slot */ return lua_gettop(L); } +static int pcallcont (lua_State *L) { + int status = lua_getctx(L, NULL); + return finishpcall(L, (status == LUA_YIELD)); +} + + static int luaB_pcall (lua_State *L) { int status; luaL_checkany(L, 1); - status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, pcallcont); - luaL_checkstack(L, 1, NULL); - lua_pushboolean(L, (status == LUA_OK)); - lua_insert(L, 1); - return lua_gettop(L); /* return status + all results */ + lua_pushnil(L); + lua_insert(L, 1); /* create space for status result */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); + return finishpcall(L, (status == LUA_OK)); } @@ -421,11 +402,8 @@ static int luaB_xpcall (lua_State *L) { lua_pushvalue(L, 1); /* exchange function... */ lua_copy(L, 2, 1); /* ...and error handler */ lua_replace(L, 2); - status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 1, pcallcont); - luaL_checkstack(L, 1, NULL); - lua_pushboolean(L, (status == LUA_OK)); - lua_replace(L, 1); - return lua_gettop(L); /* return status + all results */ + status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); + return finishpcall(L, (status == LUA_OK)); } diff --git a/src/lbitlib.c b/src/lbitlib.c index 7533b85..7533b85 100755..100644 --- a/src/lbitlib.c +++ b/src/lbitlib.c diff --git a/src/lcode.c b/src/lcode.c index 00966a1..614e452 100755..100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.56 2011/05/31 18:27:56 roberto Exp $ +** $Id: lcode.c,v 2.60 2011/08/30 16:26:41 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -44,8 +44,8 @@ void luaK_nil (FuncState *fs, int from, int n) { int pl = pfrom + GETARG_B(*previous); if ((pfrom <= from && from <= pl + 1) || (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ - if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ - if (pl > l) l = pl; /* l = max(l, pl) */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ SETARG_A(*previous, from); SETARG_B(*previous, l - from); return; @@ -213,11 +213,11 @@ static int luaK_code (FuncState *fs, Instruction i) { Proto *f = fs->f; dischargejpc(fs); /* `pc' will change */ /* put new instruction in code array */ - luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "opcodes"); f->code[fs->pc] = i; /* save corresponding line information */ - luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, MAX_INT, "opcodes"); f->lineinfo[fs->pc] = fs->ls->lastline; return fs->pc++; @@ -289,7 +289,7 @@ static void freeexp (FuncState *fs, expdesc *e) { static int addk (FuncState *fs, TValue *key, TValue *v) { - lua_State *L = fs->L; + lua_State *L = fs->ls->L; TValue *idx = luaH_set(L, fs->h, key); Proto *f = fs->f; int k, oldsize; @@ -304,6 +304,8 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { /* constant not found; create a new entry */ oldsize = f->sizek; k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ setnvalue(idx, cast_num(k)); luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); @@ -316,14 +318,14 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { int luaK_stringK (FuncState *fs, TString *s) { TValue o; - setsvalue(fs->L, &o, s); + setsvalue(fs->ls->L, &o, s); return addk(fs, &o, &o); } int luaK_numberK (FuncState *fs, lua_Number r) { int n; - lua_State *L = fs->L; + lua_State *L = fs->ls->L; TValue o; setnvalue(&o, r); if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ @@ -350,7 +352,7 @@ static int nilK (FuncState *fs) { TValue k, v; setnilvalue(&v); /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->L, &k, fs->h); + sethvalue(fs->ls->L, &k, fs->h); return addk(fs, &k, &v); } @@ -641,7 +643,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { } -static void luaK_goiffalse (FuncState *fs, expdesc *e) { +void luaK_goiffalse (FuncState *fs, expdesc *e) { int pc; /* pc of last jump */ luaK_dischargevars(fs, e); switch (e->k) { diff --git a/src/lcode.h b/src/lcode.h index 26a5daa..5a1fa9f 100755..100644 --- a/src/lcode.h +++ b/src/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.57 2011/04/07 18:14:12 roberto Exp $ +** $Id: lcode.h,v 1.58 2011/08/30 16:26:41 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -62,6 +62,7 @@ LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); 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); diff --git a/src/lcorolib.c b/src/lcorolib.c index 981ca38..0edde26 100755..100644 --- a/src/lcorolib.c +++ b/src/lcorolib.c @@ -1,5 +1,5 @@ /* -** $Id: lcorolib.c,v 1.2 2010/07/02 11:38:13 roberto Exp $ +** $Id: lcorolib.c,v 1.3 2011/08/23 17:24:34 roberto Exp $ ** Coroutine Library ** See Copyright Notice in lua.h */ @@ -28,7 +28,7 @@ static int auxresume (lua_State *L, lua_State *co, int narg) { return -1; /* error flag */ } lua_xmove(L, co, narg); - status = lua_resume(co, narg); + status = lua_resume(co, L, narg); if (status == LUA_OK || status == LUA_YIELD) { int nres = lua_gettop(co); if (!lua_checkstack(L, nres + 1)) { diff --git a/src/lctype.c b/src/lctype.c index 387c93a..55e433a 100755..100644 --- a/src/lctype.c +++ b/src/lctype.c @@ -1,9 +1,12 @@ /* -** $Id: lctype.c,v 1.10 2011/06/24 12:25:33 roberto Exp $ +** $Id: lctype.c,v 1.11 2011/10/03 16:19:23 roberto Exp $ ** 'ctype' functions for Lua ** See Copyright Notice in lua.h */ +#define lctype_c +#define LUA_CORE + #include "lctype.h" #if !LUA_USE_CTYPE /* { */ diff --git a/src/lctype.h b/src/lctype.h index b24d925..99c7d12 100755..100644 --- a/src/lctype.h +++ b/src/lctype.h @@ -1,5 +1,5 @@ /* -** $Id: lctype.h,v 1.11 2011/06/27 18:22:46 roberto Exp $ +** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $ ** 'ctype' functions for Lua ** See Copyright Notice in lua.h */ @@ -11,7 +11,7 @@ /* -** WARNING: the functions defined here do not necessarily correspond +** WARNING: the functions defined here do not necessarily correspond ** to the similar functions in the standard C ctype.h. They are ** optimized for the specific needs of Lua */ diff --git a/src/ldblib.c b/src/ldblib.c index 78f6cc0..3c2f159 100755..100644 --- a/src/ldblib.c +++ b/src/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.130 2011/04/08 19:17:36 roberto Exp $ +** $Id: ldblib.c,v 1.131 2011/10/24 14:54:05 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -260,8 +260,7 @@ static void hookf (lua_State *L, lua_Debug *ar) { static const char *const hooknames[] = {"call", "return", "line", "count", "tail call"}; gethooktable(L); - lua_pushlightuserdata(L, L); - lua_rawget(L, -2); + lua_rawgetp(L, -1, L); if (lua_isfunction(L, -1)) { lua_pushstring(L, hooknames[(int)ar->event]); if (ar->currentline >= 0) @@ -308,9 +307,8 @@ static int db_sethook (lua_State *L) { func = hookf; mask = makemask(smask, count); } gethooktable(L); - lua_pushlightuserdata(L, L1); lua_pushvalue(L, arg+1); - lua_rawset(L, -3); /* set new hook */ + lua_rawsetp(L, -2, L1); /* set new hook */ lua_pop(L, 1); /* remove hook table */ lua_sethook(L1, func, mask, count); /* set hooks */ return 0; @@ -327,8 +325,7 @@ static int db_gethook (lua_State *L) { lua_pushliteral(L, "external hook"); else { gethooktable(L); - lua_pushlightuserdata(L, L1); - lua_rawget(L, -2); /* get hook */ + lua_rawgetp(L, -1, L1); /* get hook */ lua_remove(L, -2); /* remove hook table */ } lua_pushstring(L, unmakemask(mask, buff)); diff --git a/src/ldebug.c b/src/ldebug.c index a2565cf..31b7ae4 100755..100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.82 2011/06/02 19:31:40 roberto Exp $ +** $Id: ldebug.c,v 2.88 2011/11/30 12:43:51 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -94,6 +94,13 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { } +static const char *upvalname (Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); +} + + static const char *findvararg (CallInfo *ci, int n, StkId *pos) { int nparams = clLvalue(ci->func)->p->numparams; if (n >= ci->u.l.base - ci->func - nparams) @@ -190,12 +197,14 @@ static void collectvalidlines (lua_State *L, Closure *f) { } else { int i; + TValue v; int *lineinfo = f->l.p->lineinfo; - Table *t = luaH_new(L); - sethvalue(L, L->top, t); + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue(L, L->top, t); /* push it on stack */ incr_top(L); - for (i=0; i<f->l.p->sizelineinfo; i++) - setbvalue(luaH_setint(L, t, lineinfo[i]), 1); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ + luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ } } @@ -230,7 +239,11 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 'n': { - ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; + /* calling function is a known Lua function? */ + if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + ar->namewhat = getfuncname(L, ci->previous, &ar->name); + else + ar->namewhat = NULL; if (ar->namewhat == NULL) { ar->namewhat = ""; /* not found */ ar->name = NULL; @@ -284,17 +297,16 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { ** ======================================================= */ -static const char *getobjname (lua_State *L, CallInfo *ci, int reg, +static const char *getobjname (Proto *p, int lastpc, int reg, const char **name); /* ** find a "name" for the RK value 'c' */ -static void kname (lua_State *L, CallInfo *ci, int c, int oreg, - const char *what, const char **name) { +static void kname (Proto *p, int pc, int c, const char **name) { if (ISK(c)) { /* is 'c' a constant? */ - TValue *kvalue = &ci_func(ci)->p->k[INDEXK(c)]; + TValue *kvalue = &p->k[INDEXK(c)]; if (ttisstring(kvalue)) { /* literal constant? */ *name = svalue(kvalue); /* it is its own name */ return; @@ -302,8 +314,7 @@ static void kname (lua_State *L, CallInfo *ci, int c, int oreg, /* else no reasonable name found */ } else { /* 'c' is a register */ - if (c != oreg) /* not the original register? */ - what = getobjname(L, ci, c, name); /* search for 'c' */ + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ if (what && *what == 'c') { /* found a constant name? */ return; /* 'name' already filled */ } @@ -313,85 +324,30 @@ static void kname (lua_State *L, CallInfo *ci, int c, int oreg, } -static const char *getobjname (lua_State *L, CallInfo *ci, int reg, - const char **name) { - Proto *p = ci_func(ci)->p; - const char *what = NULL; - int lastpc = currentpc(ci); +/* +** try to find last instruction before 'lastpc' that modified register 'reg' +*/ +static int findsetreg (Proto *p, int lastpc, int reg) { int pc; - *name = luaF_getlocalname(p, reg + 1, lastpc); - if (*name) /* is a local? */ - return "local"; - /* else try symbolic execution */ + int setreg = -1; /* keep last instruction that changed 'reg' */ for (pc = 0; pc < lastpc; pc++) { Instruction i = p->code[pc]; OpCode op = GET_OPCODE(i); int a = GETARG_A(i); switch (op) { - case OP_MOVE: { - if (reg == a) { - int b = GETARG_B(i); /* move from 'b' to 'a' */ - if (b < a) - what = getobjname(L, ci, b, name); /* get name for 'b' */ - else what = NULL; - } - break; - } - case OP_GETTABUP: - case OP_GETTABLE: { - if (reg == a) { - int k = GETARG_C(i); /* key index */ - int t = GETARG_B(i); - const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ - ? luaF_getlocalname(p, t + 1, pc) - : getstr(p->upvalues[t].name); - kname(L, ci, k, a, what, name); - what = (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; - } - break; - } - case OP_GETUPVAL: { - if (reg == a) { - int u = GETARG_B(i); /* upvalue index */ - TString *tn = p->upvalues[u].name; - *name = tn ? getstr(tn) : "?"; - what = "upvalue"; - } - break; - } - case OP_LOADK: - case OP_LOADKX: { - if (reg == a) { - int b = (op == OP_LOADK) ? GETARG_Bx(i) - : GETARG_Ax(p->code[pc + 1]); - if (ttisstring(&p->k[b])) { - what = "constant"; - *name = svalue(&p->k[b]); - } - } - break; - } case OP_LOADNIL: { int b = GETARG_B(i); if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ - what = NULL; - break; - } - case OP_SELF: { - if (reg == a) { - int k = GETARG_C(i); /* key index */ - kname(L, ci, k, a, what, name); - what = "method"; - } + setreg = pc; break; } case OP_TFORCALL: { - if (reg >= a + 2) what = NULL; /* affect all regs above its base */ + if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ break; } case OP_CALL: case OP_TAILCALL: { - if (reg >= a) what = NULL; /* affect all registers above base */ + if (reg >= a) setreg = pc; /* affect all registers above base */ break; } case OP_JMP: { @@ -403,35 +359,87 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg, break; } case OP_TEST: { - if (reg == a) what = NULL; /* jumped code can change 'a' */ + if (reg == a) setreg = pc; /* jumped code can change 'a' */ break; } default: - if (testAMode(op) && reg == a) what = NULL; + if (testAMode(op) && reg == a) /* any instruction that set A */ + setreg = pc; break; } } - return what; + return setreg; +} + + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name) { + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_MOVE: { + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ + break; + } + case OP_GETTABUP: + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + int t = GETARG_B(i); /* table index */ + const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ + ? luaF_getlocalname(p, t + 1, pc) + : upvalname(p, t); + kname(p, pc, k, name); + return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; + } + case OP_GETUPVAL: { + *name = upvalname(p, GETARG_B(i)); + return "upvalue"; + } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + kname(p, pc, k, name); + return "method"; + } + default: break; /* go through to return NULL */ + } + } + return NULL; /* could not find reasonable name */ } static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { TMS tm; - Instruction i; - if ((ci->callstatus & CIST_TAIL) || !isLua(ci->previous)) - return NULL; /* calling function is not Lua (or is unknown) */ - ci = ci->previous; /* calling function */ - i = ci_func(ci)->p->code[currentpc(ci)]; - if (GET_OPCODE(i) == OP_EXTRAARG) /* extra argument? */ - i = ci_func(ci)->p->code[currentpc(ci) - 1]; /* get 'real' instruction */ + Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ switch (GET_OPCODE(i)) { case OP_CALL: - case OP_TAILCALL: - return getobjname(L, ci, GETARG_A(i), name); - case OP_TFORCALL: { + case OP_TAILCALL: /* get function name */ + return getobjname(p, pc, GETARG_A(i), name); + case OP_TFORCALL: { /* for iterator */ *name = "for iterator"; return "for iterator"; } + /* all other instructions can call only through metamethods */ case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: tm = TM_INDEX; break; @@ -473,12 +481,12 @@ static int isinstack (CallInfo *ci, const TValue *o) { static const char *getupvalname (CallInfo *ci, const TValue *o, - const char **name) { + const char **name) { LClosure *c = ci_func(ci); int i; for (i = 0; i < c->nupvalues; i++) { if (c->upvals[i]->v == o) { - *name = getstr(c->p->upvalues[i].name); + *name = upvalname(c->p, i); return "upvalue"; } } @@ -486,7 +494,7 @@ static const char *getupvalname (CallInfo *ci, const TValue *o, } -void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { CallInfo *ci = L->ci; const char *name = NULL; const char *t = objtypename(o); @@ -494,7 +502,8 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { if (isLua(ci)) { kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(L, ci, cast_int(o - ci->u.l.base), &name); + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(o - ci->u.l.base), &name); } if (kind) luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", @@ -504,14 +513,14 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { } -void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { +l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; lua_assert(!ttisstring(p1) && !ttisnumber(p2)); luaG_typeerror(L, p1, "concatenate"); } -void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { +l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { TValue temp; if (luaV_tonumber(p1, &temp) == NULL) p2 = p1; /* first operand is wrong */ @@ -519,14 +528,13 @@ void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { } -int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { const char *t1 = objtypename(p1); const char *t2 = objtypename(p2); if (t1 == t2) luaG_runerror(L, "attempt to compare two %s values", t1); else luaG_runerror(L, "attempt to compare %s with %s", t1, t2); - return 0; } @@ -546,7 +554,7 @@ static void addinfo (lua_State *L, const char *msg) { } -void luaG_errormsg (lua_State *L) { +l_noret luaG_errormsg (lua_State *L) { if (L->errfunc != 0) { /* is there an error handling function? */ StkId errfunc = restorestack(L, L->errfunc); if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); @@ -559,7 +567,7 @@ void luaG_errormsg (lua_State *L) { } -void luaG_runerror (lua_State *L, const char *fmt, ...) { +l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); addinfo(L, luaO_pushvfstring(L, fmt, argp)); diff --git a/src/ldebug.h b/src/ldebug.h index 6590c56..fe39556 100755..100644 --- a/src/ldebug.h +++ b/src/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 2.6 2011/06/02 19:31:40 roberto Exp $ +** $Id: ldebug.h,v 2.7 2011/10/07 20:45:19 roberto Exp $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -21,14 +21,14 @@ #define ci_func(ci) (clLvalue((ci)->func)) -LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); -LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaG_errormsg (lua_State *L); +LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC l_noret luaG_errormsg (lua_State *L); #endif diff --git a/src/ldo.c b/src/ldo.c index a34b0d0..26f9a67 100755..100644 --- a/src/ldo.c +++ b/src/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.98 2011/06/28 15:42:04 roberto Exp $ +** $Id: ldo.c,v 2.102 2011/11/29 15:55:08 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -100,7 +100,7 @@ static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { } -void luaD_throw (lua_State *L, int errcode) { +l_noret luaD_throw (lua_State *L, int errcode) { if (L->errorJmp) { /* thread has an error handler? */ L->errorJmp->status = errcode; /* set status */ LUAI_THROW(L, L->errorJmp); /* jump to it */ @@ -123,7 +123,7 @@ void luaD_throw (lua_State *L, int errcode) { int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - unsigned short oldnCcalls = G(L)->nCcalls; + unsigned short oldnCcalls = L->nCcalls; struct lua_longjmp lj; lj.status = LUA_OK; lj.previous = L->errorJmp; /* chain new error handler */ @@ -132,7 +132,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { (*f)(L, ud); ); L->errorJmp = lj.previous; /* restore old error handler */ - G(L)->nCcalls = oldnCcalls; + L->nCcalls = oldnCcalls; return lj.status; } @@ -344,7 +344,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { } default: { /* not a function */ func = tryfuncTM(L, func); /* retry with 'function' tag method */ - return luaD_precall(L, func, nresults); + return luaD_precall(L, func, nresults); /* now it must be a function */ } } } @@ -382,18 +382,17 @@ int luaD_poscall (lua_State *L, StkId firstResult) { ** function position. */ void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { - global_State *g = G(L); - if (++g->nCcalls >= LUAI_MAXCCALLS) { - if (g->nCcalls == LUAI_MAXCCALLS) + if (++L->nCcalls >= LUAI_MAXCCALLS) { + if (L->nCcalls == LUAI_MAXCCALLS) luaG_runerror(L, "C stack overflow"); - else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ } if (!allowyield) L->nny++; if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ luaV_execute(L); /* call it */ if (!allowyield) L->nny--; - g->nCcalls--; + L->nCcalls--; luaC_checkGC(L); } @@ -404,7 +403,7 @@ static void finishCcall (lua_State *L) { lua_assert(ci->u.c.k != NULL); /* must have a continuation */ lua_assert(L->nny == 0); /* finish 'luaD_call' */ - G(L)->nCcalls--; + L->nCcalls--; /* finish 'lua_callk' */ adjustresults(L, ci->nresults); /* call continuation function */ @@ -473,7 +472,7 @@ static int recover (lua_State *L, int status) { ** coroutine itself. (Such errors should not be handled by any coroutine ** error handler and should not kill the coroutine.) */ -static void resume_error (lua_State *L, const char *msg, StkId firstArg) { +static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { L->top = firstArg; /* remove args from the stack */ setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ incr_top(L); @@ -487,7 +486,7 @@ static void resume_error (lua_State *L, const char *msg, StkId firstArg) { static void resume (lua_State *L, void *ud) { StkId firstArg = cast(StkId, ud); CallInfo *ci = L->ci; - if (G(L)->nCcalls >= LUAI_MAXCCALLS) + if (L->nCcalls >= LUAI_MAXCCALLS) resume_error(L, "C stack overflow", firstArg); if (L->status == LUA_OK) { /* may be starting a coroutine */ if (ci != &L->base_ci) /* not in base level? */ @@ -514,7 +513,7 @@ static void resume (lua_State *L, void *ud) { api_checknelems(L, n); firstArg = L->top - n; /* yield results come from continuation */ } - G(L)->nCcalls--; /* finish 'luaD_call' */ + L->nCcalls--; /* finish 'luaD_call' */ luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ } unroll(L, NULL); @@ -522,11 +521,11 @@ static void resume (lua_State *L, void *ud) { } -LUA_API int lua_resume (lua_State *L, int nargs) { +LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { int status; lua_lock(L); luai_userstateresume(L, nargs); - ++G(L)->nCcalls; /* count resume */ + L->nCcalls = (from) ? from->nCcalls + 1 : 1; L->nny = 0; /* allow yields */ api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); status = luaD_rawrunprotected(L, resume, L->top - nargs); @@ -546,7 +545,8 @@ LUA_API int lua_resume (lua_State *L, int nargs) { lua_assert(status == L->status); } L->nny = 1; /* do not allow yields */ - --G(L)->nCcalls; + L->nCcalls--; + lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); lua_unlock(L); return status; } @@ -611,18 +611,34 @@ struct SParser { /* data to `f_parser' */ ZIO *z; Mbuffer buff; /* dynamic structure used by the scanner */ Dyndata dyd; /* dynamic structures used by the parser */ + const char *mode; const char *name; }; + +static void checkmode (lua_State *L, const char *mode, const char *x) { + if (mode && strchr(mode, x[0]) == NULL) { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } +} + + static void f_parser (lua_State *L, void *ud) { int i; Proto *tf; Closure *cl; struct SParser *p = cast(struct SParser *, ud); int c = zgetc(p->z); /* read first character */ - tf = (c == LUA_SIGNATURE[0]) - ? luaU_undump(L, p->z, &p->buff, p->name) - : luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + if (c == LUA_SIGNATURE[0]) { + checkmode(L, p->mode, "binary"); + tf = luaU_undump(L, p->z, &p->buff, p->name); + } + else { + checkmode(L, p->mode, "text"); + tf = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } setptvalue2s(L, L->top, tf); incr_top(L); cl = luaF_newLclosure(L, tf); @@ -632,11 +648,12 @@ static void f_parser (lua_State *L, void *ud) { } -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { struct SParser p; int status; L->nny++; /* cannot yield during parsing */ - p.z = z; p.name = name; + p.z = z; p.name = name; p.mode = mode; p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; p.dyd.label.arr = NULL; p.dyd.label.size = 0; diff --git a/src/ldo.h b/src/ldo.h index 88962d9..27b837d 100755..100644 --- a/src/ldo.h +++ b/src/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.18 2009/12/17 12:28:57 roberto Exp $ +** $Id: ldo.h,v 2.20 2011/11/29 15:55:08 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -26,7 +26,8 @@ /* type of protected functions, to be ran by `runprotected' */ typedef void (*Pfunc) (lua_State *L, void *ud); -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode); LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, @@ -38,7 +39,7 @@ LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); LUAI_FUNC void luaD_growstack (lua_State *L, int n); LUAI_FUNC void luaD_shrinkstack (lua_State *L); -LUAI_FUNC void luaD_throw (lua_State *L, int errcode); +LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); #endif diff --git a/src/ldump.c b/src/ldump.c index 77b578d..699e1dc 100755..100644 --- a/src/ldump.c +++ b/src/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 1.18 2011/05/06 13:35:17 lhf Exp $ +** $Id: ldump.c,v 1.19 2011/11/23 17:48:18 lhf Exp $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -111,8 +111,8 @@ static void DumpUpvalues(const Proto* f, DumpState* D) DumpInt(n,D); for (i=0; i<n; i++) { - DumpChar(f->upvalues[i].instack, D); - DumpChar(f->upvalues[i].idx, D); + DumpChar(f->upvalues[i].instack,D); + DumpChar(f->upvalues[i].idx,D); } } diff --git a/src/lfunc.c b/src/lfunc.c index 1a1a8bb..1a1a8bb 100755..100644 --- a/src/lfunc.c +++ b/src/lfunc.c diff --git a/src/lfunc.h b/src/lfunc.h index da18923..da18923 100755..100644 --- a/src/lfunc.h +++ b/src/lfunc.h diff --git a/src/lgc.c b/src/lgc.c index 598cc71..cdd92e5 100755..100644 --- a/src/lgc.c +++ b/src/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.109 2011/05/05 19:42:25 roberto Exp $ +** $Id: lgc.c,v 2.116 2011/12/02 13:18:41 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -94,18 +94,25 @@ static void reallymarkobject (global_State *g, GCObject *o); /* +** one after last element in a hash array +*/ +#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) + + +/* ** link table 'h' into list pointed by 'p' */ #define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) /* -** mark a table entry as dead (therefore removing it from the table) +** if key is not marked, mark its entry as dead (therefore removing it +** from the table) */ static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); - if (iscollectable(gkey(n))) - setdeadvalue(gkey(n)); /* dead key; remove it */ + if (valiswhite(gkey(n))) + setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ } @@ -116,13 +123,13 @@ static void removeentry (Node *n) { ** other objects: if really collected, cannot keep them; for objects ** being finalized, keep them in keys, but not in values */ -static int iscleared (const TValue *o, int iskey) { +static int iscleared (const TValue *o) { if (!iscollectable(o)) return 0; else if (ttisstring(o)) { stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ return 0; } - else return iswhite(gcvalue(o)) || (!iskey && isfinalized(gcvalue(o))); + else return iswhite(gcvalue(o)); } @@ -152,7 +159,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { */ void luaC_barrierback_ (lua_State *L, GCObject *o) { global_State *g = G(L); - lua_assert(isblack(o) && !isdead(g, o)); + lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); black2gray(o); /* make object gray (again) */ gco2t(o)->gclist = g->grayagain; g->grayagain = o; @@ -284,7 +291,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { /* -** mark tag methods for basic types +** mark metamethods for basic types */ static void markmt (global_State *g) { int i; @@ -341,7 +348,10 @@ static void markroot (global_State *g) { */ static void traverseweakvalue (global_State *g, Table *h) { - Node *n, *limit = gnode(h, sizenode(h)); + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (do not + traverse it just to check) */ + int hasclears = (h->sizearray > 0); for (n = gnode(h, 0); n < limit; n++) { checkdeadkey(n); if (ttisnil(gval(n))) /* entry is empty? */ @@ -349,16 +359,22 @@ static void traverseweakvalue (global_State *g, Table *h) { else { lua_assert(!ttisnil(gkey(n))); markvalue(g, gkey(n)); /* mark key */ + if (!hasclears && iscleared(gval(n))) /* is there a white value? */ + hasclears = 1; /* table will have to be cleared */ } } - linktable(h, &g->weak); /* link into appropriate list */ + if (hasclears) + linktable(h, &g->weak); /* has to be cleared later */ + else /* no white values */ + linktable(h, &g->grayagain); /* no need to clean */ } static int traverseephemeron (global_State *g, Table *h) { int marked = 0; /* true if an object is marked in this traversal */ - int hasclears = 0; /* true if table has unmarked pairs */ - Node *n, *limit = gnode(h, sizenode(h)); + int hasclears = 0; /* true if table has white keys */ + int prop = 0; /* true if table has entry "white-key -> white-value" */ + Node *n, *limit = gnodelast(h); int i; /* traverse array part (numeric keys are 'strong') */ for (i = 0; i < h->sizearray; i++) { @@ -372,25 +388,28 @@ static int traverseephemeron (global_State *g, Table *h) { checkdeadkey(n); if (ttisnil(gval(n))) /* entry is empty? */ removeentry(n); /* remove it */ + else if (iscleared(gkey(n))) { /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + prop = 1; /* must propagate again */ + } else if (valiswhite(gval(n))) { /* value not marked yet? */ - if (iscleared(gkey(n), 1)) /* key is not marked (yet)? */ - hasclears = 1; /* may have to propagate mark from key to value */ - else { /* key is marked, so mark value */ - marked = 1; /* value was not marked */ - reallymarkobject(g, gcvalue(gval(n))); - } + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ } } - if (hasclears) /* does table have unmarked pairs? */ - linktable(h, &g->ephemeron); /* will have to propagate again */ - else /* nothing to propagate */ - linktable(h, &g->weak); /* avoid convergence phase */ + if (prop) + linktable(h, &g->ephemeron); /* have to propagate again */ + else if (hasclears) /* does table have white keys? */ + linktable(h, &g->allweak); /* may have to clean white keys */ + else /* no white keys */ + linktable(h, &g->grayagain); /* no need to clean */ return marked; } static void traversestrongtable (global_State *g, Table *h) { - Node *n, *limit = gnode(h, sizenode(h)); + Node *n, *limit = gnodelast(h); int i; for (i = 0; i < h->sizearray; i++) /* traverse array part */ markvalue(g, &h->array[i]); @@ -526,11 +545,26 @@ static void propagateall (global_State *g) { } -static void traverselistofgrays (global_State *g, GCObject **l) { +static void propagatelist (global_State *g, GCObject *l) { lua_assert(g->gray == NULL); /* no grays left */ - g->gray = *l; /* now 'l' is new gray list */ - *l = NULL; - propagateall(g); + g->gray = l; + propagateall(g); /* traverse all elements from 'l' */ +} + +/* +** retraverse all gray lists. Because tables may be reinserted in other +** lists when traversed, traverse the original lists to avoid traversing +** twice the same table (which is not wrong, but inefficient) +*/ +static void retraversegrays (global_State *g) { + GCObject *weak = g->weak; /* save original lists */ + GCObject *grayagain = g->grayagain; + GCObject *ephemeron = g->ephemeron; + g->weak = g->grayagain = g->ephemeron = NULL; + propagateall(g); /* traverse main gray list */ + propagatelist(g, grayagain); + propagatelist(g, weak); + propagatelist(g, ephemeron); } @@ -562,21 +596,39 @@ static void convergeephemerons (global_State *g) { /* -** clear collected entries from all weaktables in list 'l' +** clear entries with unmarked keys from all weaktables in list 'l' up +** to element 'f' */ -static void cleartable (GCObject *l) { - for (; l != NULL; l = gco2t(l)->gclist) { +static void clearkeys (GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { Table *h = gco2t(l); - Node *n, *limit = gnode(h, sizenode(h)); + Node *n, *limit = gnodelast(h); + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && (iscleared(gkey(n)))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } + } +} + + +/* +** clear entries with unmarked values from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearvalues (GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); int i; for (i = 0; i < h->sizearray; i++) { TValue *o = &h->array[i]; - if (iscleared(o, 0)) /* value was collected? */ + if (iscleared(o)) /* value was collected? */ setnilvalue(o); /* remove value */ } for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && /* non-empty entry? */ - (iscleared(gkey(n), 1) || iscleared(gval(n), 0))) { + if (!ttisnil(gval(n)) && iscleared(gval(n))) { setnilvalue(gval(n)); /* remove value ... */ removeentry(n); /* and remove entry from table */ } @@ -722,7 +774,7 @@ static void GCTM (lua_State *L, int propagateerrors) { int status; lu_byte oldah = L->allowhook; int running = g->gcrunning; - L->allowhook = 0; /* stop debug hooks during GC tag method */ + L->allowhook = 0; /* stop debug hooks during GC metamethod */ g->gcrunning = 0; /* avoid GC steps */ setobj2s(L, L->top, tm); /* push finalizer... */ setobj2s(L, L->top + 1, &v); /* ... and its argument */ @@ -732,7 +784,7 @@ static void GCTM (lua_State *L, int propagateerrors) { g->gcrunning = running; /* restore state */ if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ if (status == LUA_ERRRUN) { /* is there an error msg.? */ - luaO_pushfstring(L, "error in __gc tag method (%s)", + luaO_pushfstring(L, "error in __gc metamethod (%s)", lua_tostring(L, -1)); status = LUA_ERRGCMM; /* error in __gc metamethod */ } @@ -743,10 +795,10 @@ static void GCTM (lua_State *L, int propagateerrors) { /* -** move all unreachable objects that need finalization from list 'finobj' -** to list 'tobefnz' +** move all unreachable objects (or 'all' objects) that need +** finalization from list 'finobj' to list 'tobefnz' (to be finalized) */ -void luaC_separateudata (lua_State *L, int all) { +static void separatetobefnz (lua_State *L, int all) { global_State *g = G(L); GCObject **p = &g->finobj; GCObject *curr; @@ -842,14 +894,13 @@ static void callallpendingfinalizers (lua_State *L, int propagateerrors) { void luaC_freeallobjects (lua_State *L) { global_State *g = G(L); int i; + separatetobefnz(L, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); callallpendingfinalizers(L, 0); - /* following "white" makes all objects look dead */ - g->currentwhite = WHITEBITS; + g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ g->gckind = KGC_NORMAL; - sweepwholelist(L, &g->finobj); - lua_assert(g->finobj == NULL); + sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ sweepwholelist(L, &g->allgc); - lua_assert(g->allgc == NULL); for (i = 0; i < g->strt.size; i++) /* free all string lists */ sweepwholelist(L, &g->strt.hash[i]); lua_assert(g->strt.nuse == 0); @@ -858,6 +909,7 @@ void luaC_freeallobjects (lua_State *L) { static void atomic (lua_State *L) { global_State *g = G(L); + GCObject *origweak, *origall; lua_assert(!iswhite(obj2gco(g->mainthread))); markobject(g, L); /* mark running thread */ /* registry and global metatables may be changed by API */ @@ -866,20 +918,24 @@ static void atomic (lua_State *L) { /* remark occasional upvalues of (maybe) dead threads */ remarkupvals(g); /* traverse objects caught by write barrier and by 'remarkupvals' */ - propagateall(g); - traverselistofgrays(g, &g->weak); /* remark weak tables */ - traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */ - traverselistofgrays(g, &g->grayagain); /* remark gray again */ + retraversegrays(g); convergeephemerons(g); /* at this point, all strongly accessible objects are marked. */ - luaC_separateudata(L, 0); /* separate userdata to be finalized */ + /* clear values from weak tables, before checking finalizers */ + clearvalues(g->weak, NULL); + clearvalues(g->allweak, NULL); + origweak = g->weak; origall = g->allweak; + separatetobefnz(L, 0); /* separate objects to be finalized */ markbeingfnz(g); /* mark userdata that will be finalized */ propagateall(g); /* remark, to propagate `preserveness' */ convergeephemerons(g); - /* remove collected objects from weak tables */ - cleartable(g->weak); - cleartable(g->ephemeron); - cleartable(g->allweak); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearkeys(g->ephemeron, NULL); /* clear keys from all ephemeron tables */ + clearkeys(g->allweak, NULL); /* clear keys from all allweak tables */ + /* clear values from resurrected weak tables */ + clearvalues(g->weak, origweak); + clearvalues(g->allweak, origall); g->sweepstrgc = 0; /* prepare to sweep strings */ g->gcstate = GCSsweepstring; g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ diff --git a/src/lgc.h b/src/lgc.h index 0fae4dd..aa5dfce 100755..100644 --- a/src/lgc.h +++ b/src/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.50 2011/01/26 16:30:02 roberto Exp $ +** $Id: lgc.h,v 2.52 2011/10/03 17:54:25 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -63,9 +63,6 @@ #define l_setbit(x,b) setbits(x, bitmask(b)) #define resetbit(x,b) resetbits(x, bitmask(b)) #define testbit(x,b) testbits(x, bitmask(b)) -#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) -#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) - /* Layout for bit use in `marked' field: */ @@ -125,7 +122,6 @@ #define luaC_barrierproto(L,p,c) \ { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } -LUAI_FUNC void luaC_separateudata (lua_State *L, int all); LUAI_FUNC void luaC_freeallobjects (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); LUAI_FUNC void luaC_forcestep (lua_State *L); diff --git a/src/linit.c b/src/linit.c index 8d3aa65..8d3aa65 100755..100644 --- a/src/linit.c +++ b/src/linit.c diff --git a/src/liolib.c b/src/liolib.c index 41e7ec5..4814aa2 100755..100644 --- a/src/liolib.c +++ b/src/liolib.c @@ -1,10 +1,20 @@ /* -** $Id: liolib.c,v 2.101 2011/06/27 19:42:31 roberto Exp $ +** $Id: liolib.c,v 2.108 2011/11/25 12:50:03 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ +/* +** POSIX idiosyncrasy! +** This definition must come before the inclusion of 'stdio.h'; it +** should not affect non-POSIX systems +*/ +#if !defined(_FILE_OFFSET_BITS) +#define _FILE_OFFSET_BITS 64 +#endif + + #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -21,9 +31,12 @@ /* -** lua_popen spawns a new process connected to the current one through -** the file streams. +** {====================================================== +** lua_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= */ + #if !defined(lua_popen) /* { */ #if defined(LUA_USE_POPEN) /* { */ @@ -48,22 +61,50 @@ #endif /* } */ +/* }====================================================== */ + + +/* +** {====================================================== +** lua_fseek/lua_ftell: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(lua_fseek) /* { */ + +#if defined(LUA_USE_POSIX) + +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t + +#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) +/* Windows (but not DDK) and Visual C++ 2005 or higher */ + +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 + +#else + +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long + +#endif + +#endif /* } */ + +/* }====================================================== */ + #define IO_PREFIX "_IO_" #define IO_INPUT (IO_PREFIX "input") #define IO_OUTPUT (IO_PREFIX "output") -typedef struct LStream { - FILE *f; /* stream */ - lua_CFunction closef; /* to close stream (NULL for closed streams) */ -} LStream; - - -static void fileerror (lua_State *L, int arg, const char *filename) { - lua_pushfstring(L, "%s: %s", filename, strerror(errno)); - luaL_argerror(L, arg, lua_tostring(L, -1)); -} +typedef luaL_Stream LStream; #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) @@ -159,6 +200,14 @@ static LStream *newfile (lua_State *L) { } +static void opencheck (lua_State *L, const char *fname, const char *mode) { + LStream *p = newfile(L); + p->f = fopen(fname, mode); + if (p->f == NULL) + luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); +} + + static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); @@ -169,7 +218,7 @@ static int io_open (lua_State *L) { (mode[i] != '+' || ++i) && /* skip if char is '+' */ (mode[i] != 'b' || ++i) && /* skip if char is 'b' */ (mode[i] == '\0'))) - return luaL_error(L, "invalid mode " LUA_QL("%s") + return luaL_error(L, "invalid mode " LUA_QS " (should match " LUA_QL("[rwa]%%+?b?") ")", mode); p->f = fopen(filename, mode); return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; @@ -215,12 +264,8 @@ static FILE *getiofile (lua_State *L, const char *findex) { static int g_iofile (lua_State *L, const char *f, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); - if (filename) { - LStream *p = newfile(L); - p->f = fopen(filename, mode); - if (p->f == NULL) - fileerror(L, 1, filename); - } + if (filename) + opencheck(L, filename, mode); else { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); @@ -277,10 +322,7 @@ static int io_lines (lua_State *L) { } else { /* open a new file */ const char *filename = luaL_checkstring(L, 1); - LStream *p = newfile(L); - p->f = fopen(filename, "r"); - if (p->f == NULL) - fileerror(L, 1, filename); + opencheck(L, filename, "r"); lua_replace(L, 1); /* put file at index 1 */ toclose = 1; /* close it after iteration */ } @@ -444,9 +486,10 @@ static int io_readline (lua_State *L) { if (!lua_isnil(L, -n)) /* read at least one value? */ return n; /* return them */ else { /* first result is nil: EOF or error */ - if (!lua_isnil(L, -1)) /* is there error information? */ - return luaL_error(L, "%s", lua_tostring(L, -1)); /* error */ - /* else EOF */ + if (n > 1) { /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ lua_settop(L, 0); lua_pushvalue(L, lua_upvalueindex(1)); @@ -496,12 +539,15 @@ static int f_seek (lua_State *L) { static const char *const modenames[] = {"set", "cur", "end", NULL}; FILE *f = tofile(L); int op = luaL_checkoption(L, 2, "cur", modenames); - long offset = luaL_optlong(L, 3, 0); - op = fseek(f, offset, mode[op]); + lua_Number p3 = luaL_optnumber(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Number)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); if (op) return luaL_fileresult(L, 0, NULL); /* error */ else { - lua_pushinteger(L, ftell(f)); + lua_pushnumber(L, (lua_Number)l_ftell(f)); return 1; } } diff --git a/src/llex.c b/src/llex.c index 289abfd..74deebb 100755..100644 --- a/src/llex.c +++ b/src/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 2.53 2011/07/08 20:01:38 roberto Exp $ +** $Id: llex.c,v 2.59 2011/11/30 12:43:51 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -46,7 +46,7 @@ static const char *const luaX_tokens [] = { #define save_and_next(ls) (save(ls, ls->current), next(ls)) -static void lexerror (LexState *ls, const char *msg, int token); +static l_noret lexerror (LexState *ls, const char *msg, int token); static void save (LexState *ls, int c) { @@ -101,7 +101,7 @@ static const char *txtToken (LexState *ls, int token) { } -static void lexerror (LexState *ls, const char *msg, int token) { +static l_noret lexerror (LexState *ls, const char *msg, int token) { char buff[LUA_IDSIZE]; luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); @@ -111,7 +111,7 @@ static void lexerror (LexState *ls, const char *msg, int token) { } -void luaX_syntaxerror (LexState *ls, const char *msg) { +l_noret luaX_syntaxerror (LexState *ls, const char *msg) { lexerror(ls, msg, ls->t.token); } @@ -126,8 +126,10 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { TValue *o; /* entry for `str' */ TString *ts = luaS_newlstr(L, str, l); /* create new string */ setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ - o = luaH_setstr(L, ls->fs->h, ts); - if (ttisnil(o)) { + o = luaH_set(L, ls->fs->h, L->top - 1); + if (ttisnil(o)) { /* not in use yet? (see 'addK') */ + /* boolean value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ setbvalue(o, 1); /* t[string] = true */ luaC_checkGC(L); } @@ -297,39 +299,29 @@ static void escerror (LexState *ls, int *c, int n, const char *msg) { static int readhexaesc (LexState *ls) { - int c[3]; /* keep input for error message */ - int i = 2; /* at least 'x?' will go to error message */ - c[0] = 'x'; - c[1] = next(ls); /* first hexa digit */ - if (lisxdigit(c[1])) { - c[i++] = next(ls); /* second hexa digit */ - if (lisxdigit(c[2])) - return (luaO_hexavalue(c[1]) << 4) + luaO_hexavalue(c[2]); - /* else go through to error */ + int c[3], i; /* keep input for error message */ + int r = 0; /* result accumulator */ + c[0] = 'x'; /* for error message */ + for (i = 1; i < 3; i++) { /* read two hexa digits */ + c[i] = next(ls); + if (!lisxdigit(c[i])) + escerror(ls, c, i + 1, "hexadecimal digit expected"); + r = (r << 4) + luaO_hexavalue(c[i]); } - escerror(ls, c, i, "hexadecimal digit expected"); - return 0; /* to avoid warnings */ + return r; } static int readdecesc (LexState *ls) { - int c[3], r; - int i = 2; /* at least two chars will be read */ - c[0] = ls->current; /* first char must be a digit */ - c[1] = next(ls); /* read second char */ - r = c[0] - '0'; /* partial result */ - if (lisdigit(c[1])) { - c[i++] = next(ls); /* read third char */ - r = 10*r + c[1] - '0'; /* update result */ - if (lisdigit(c[2])) { - r = 10*r + c[2] - '0'; /* update result */ - if (r > UCHAR_MAX) - escerror(ls, c, i, "decimal escape too large"); - return r; - } + int c[3], i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + c[i] = ls->current; + r = 10*r + c[i] - '0'; + next(ls); } - /* else, has read one character that was not a digit */ - zungetc(ls->z); /* return it to input stream */ + if (r > UCHAR_MAX) + escerror(ls, c, i, "decimal escape too large"); return r; } @@ -349,37 +341,38 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) { int c; /* final character to be saved */ next(ls); /* do not save the `\' */ switch (ls->current) { - case 'a': c = '\a'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - case 'x': c = readhexaesc(ls); break; - case '\n': - case '\r': save(ls, '\n'); inclinenumber(ls); continue; - case '\\': case '\"': case '\'': c = ls->current; break; - case EOZ: continue; /* will raise an error next loop */ + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ case 'z': { /* zap following span of spaces */ next(ls); /* skip the 'z' */ while (lisspace(ls->current)) { if (currIsNewline(ls)) inclinenumber(ls); else next(ls); } - continue; /* do not save 'c' */ + goto no_save; } default: { if (!lisdigit(ls->current)) escerror(ls, &ls->current, 1, "invalid escape sequence"); /* digital escape \ddd */ c = readdecesc(ls); - break; + goto only_save; } } - next(ls); - save(ls, c); - break; + read_save: next(ls); /* read next character */ + only_save: save(ls, c); /* save 'c' */ + no_save: break; } default: save_and_next(ls); diff --git a/src/llex.h b/src/llex.h index ce0bad4..9ca8a29 100755..100644 --- a/src/llex.h +++ b/src/llex.h @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.71 2011/06/20 16:52:48 roberto Exp $ +** $Id: llex.h,v 1.72 2011/11/30 12:43:51 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -71,7 +71,7 @@ LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); LUAI_FUNC void luaX_next (LexState *ls); LUAI_FUNC int luaX_lookahead (LexState *ls); -LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); diff --git a/src/llimits.h b/src/llimits.h index b64c7b7..48dc81f 100755..100644 --- a/src/llimits.h +++ b/src/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.90 2011/07/02 15:57:25 roberto Exp $ +** $Id: llimits.h,v 1.95 2011/12/06 16:58:36 roberto Exp $ ** Limits, basic types, and some other `installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -30,7 +30,6 @@ typedef unsigned char lu_byte; #define MAX_SIZET ((size_t)(~(size_t)0)-2) #define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) -#define MIN_LMEM ((l_mem)~((~(lu_mem)0)>>1)) #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ @@ -62,9 +61,9 @@ typedef LUAI_UACNUMBER l_uacNumber; /* to avoid problems with conditions too long */ #define lua_longassert(c) { if (!(c)) lua_assert(0); } #else -#define lua_assert(c) /* empty */ +#define lua_assert(c) ((void)0) #define check_exp(c,e) (e) -#define lua_longassert(c) /* empty */ +#define lua_longassert(c) ((void)0) #endif /* @@ -98,6 +97,19 @@ typedef LUAI_UACNUMBER l_uacNumber; /* +** non-return type +*/ +#if defined(__GNUC__) +#define l_noret void __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define l_noret void __declspec(noreturn) +#else +#define l_noret void +#endif + + + +/* ** maximum depth for nested C calls and syntactical nested non-terminals ** in a program. (Value must fit in an unsigned short int.) */ @@ -216,7 +228,7 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; #define luai_hashnum(i,n) \ { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ - (i) = u.l_p[0] + u.l_p[1]; } /* add double bits for his hash */ + (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ #define lua_number2int(i,n) lua_number2int32(i, n, int) #define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) @@ -257,7 +269,7 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; -#if (defined(ltable_c) || defined(luaall_c)) && !defined(luai_hashnum) +#if defined(ltable_c) && !defined(luai_hashnum) #include <float.h> #include <math.h> diff --git a/src/lmathlib.c b/src/lmathlib.c index b17237f..b17237f 100755..100644 --- a/src/lmathlib.c +++ b/src/lmathlib.c diff --git a/src/lmem.c b/src/lmem.c index c3775df..792deb3 100755..100644 --- a/src/lmem.c +++ b/src/lmem.c @@ -1,5 +1,5 @@ /* -** $Id: lmem.c,v 1.81 2010/12/20 19:40:07 roberto Exp $ +** $Id: lmem.c,v 1.83 2011/11/30 12:42:49 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -63,9 +63,8 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, } -void *luaM_toobig (lua_State *L) { +l_noret luaM_toobig (lua_State *L) { luaG_runerror(L, "memory allocation error: block too big"); - return NULL; /* to avoid warnings */ } @@ -106,7 +105,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { if ((total % 200) == 0) { if (f == NULL) f = fopen(TRACEMEM, "w"); fprintf(f, "%lu %u %d %d\n", total, - g->totalbytes, g->GCdebt, g->gcstate * 1000); + gettotalbytes(g), g->GCdebt, g->gcstate * 10000); } } #endif diff --git a/src/lmem.h b/src/lmem.h index ff324f8..535dfe0 100755..100644 --- a/src/lmem.h +++ b/src/lmem.h @@ -1,5 +1,5 @@ /* -** $Id: lmem.h,v 1.36 2010/04/08 17:16:46 roberto Exp $ +** $Id: lmem.h,v 1.38 2011/12/02 13:26:54 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -15,9 +15,9 @@ #define luaM_reallocv(L,b,on,n,e) \ - ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ - luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ - luaM_toobig(L)) + ((cast(size_t, (n)+1) > MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ + (luaM_toobig(L), (void *)0) : \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e))) #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) @@ -37,7 +37,7 @@ #define luaM_reallocvector(L, v,oldn,n,t) \ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) -LUAI_FUNC void *luaM_toobig (lua_State *L); +LUAI_FUNC l_noret luaM_toobig (lua_State *L); /* not to be called directly */ LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, diff --git a/src/loadlib.c b/src/loadlib.c index 0313d8e..783bc12 100755..100644 --- a/src/loadlib.c +++ b/src/loadlib.c @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.100 2011/07/05 12:49:35 roberto Exp $ +** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** @@ -9,6 +9,14 @@ */ +/* +** if needed, includes windows header before everything else +*/ +#if defined(_WIN32) +#include <windows.h> +#endif + + #include <stdlib.h> #include <string.h> @@ -62,6 +70,20 @@ #endif +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + /* prefix for open functions in C libraries */ #define LUA_POF "luaopen_" @@ -110,7 +132,7 @@ static void ll_unloadlib (void *lib) { static void *ll_load (lua_State *L, const char *path, int seeglb) { - void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : 0)); + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); if (lib == NULL) lua_pushstring(L, dlerror()); return lib; } @@ -133,8 +155,6 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { ** ======================================================================= */ -#include <windows.h> - #undef setprogdir /* @@ -177,7 +197,7 @@ static void ll_unloadlib (void *lib) { static void *ll_load (lua_State *L, const char *path, int seeglb) { HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); - (void)(seeglb); /* symbols are 'global' by default */ + (void)(seeglb); /* not used: symbols are 'global' by default */ if (lib == NULL) pusherror(L); return lib; } @@ -207,19 +227,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { static void ll_unloadlib (void *lib) { - (void)(lib); /* to avoid warnings */ + (void)(lib); /* not used */ } static void *ll_load (lua_State *L, const char *path, int seeglb) { - (void)(path); (void)(seeglb); /* to avoid warnings */ + (void)(path); (void)(seeglb); /* not used */ lua_pushliteral(L, DLMSG); return NULL; } static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - (void)(lib); (void)(sym); /* to avoid warnings */ + (void)(lib); (void)(sym); /* not used */ lua_pushliteral(L, DLMSG); return NULL; } @@ -322,10 +342,12 @@ static const char *pushnexttemplate (lua_State *L, const char *path) { static const char *searchpath (lua_State *L, const char *name, const char *path, - const char *sep) { + const char *sep, + const char *dirsep) { + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); if (*sep != '\0') /* non-empty separator? */ - name = luaL_gsub(L, name, sep, LUA_DIRSEP); /* replace it by proper one */ - lua_pushliteral(L, ""); /* error accumulator */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ while ((path = pushnexttemplate(L, path)) != NULL) { const char *filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); @@ -334,8 +356,9 @@ static const char *searchpath (lua_State *L, const char *name, return filename; /* return that file name */ lua_pushfstring(L, "\n\tno file " LUA_QS, filename); lua_remove(L, -2); /* remove file name */ - lua_concat(L, 2); /* add entry to possible error message */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ } + luaL_pushresult(&msg); /* create error message */ return NULL; /* not found */ } @@ -343,7 +366,8 @@ static const char *searchpath (lua_State *L, const char *name, static int ll_searchpath (lua_State *L) { const char *f = searchpath(L, luaL_checkstring(L, 1), luaL_checkstring(L, 2), - luaL_optstring(L, 3, ".")); + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); if (f != NULL) return 1; else { /* error message is on top of the stack */ lua_pushnil(L); @@ -354,13 +378,14 @@ static int ll_searchpath (lua_State *L) { static const char *findfile (lua_State *L, const char *name, - const char *pname) { + const char *pname, + const char *dirsep) { const char *path; lua_getfield(L, lua_upvalueindex(1), pname); path = lua_tostring(L, -1); if (path == NULL) luaL_error(L, LUA_QL("package.%s") " must be a string", pname); - return searchpath(L, name, path, "."); + return searchpath(L, name, path, ".", dirsep); } @@ -379,7 +404,7 @@ static int checkload (lua_State *L, int stat, const char *filename) { static int searcher_Lua (lua_State *L) { const char *filename; const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path"); + filename = findfile(L, name, "path", LUA_LSUBSEP); if (filename == NULL) return 1; /* module not found in this path */ return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); } @@ -405,7 +430,7 @@ static int loadfunc (lua_State *L, const char *filename, const char *modname) { static int searcher_C (lua_State *L) { const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath"); + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); if (filename == NULL) return 1; /* module not found in this path */ return checkload(L, (loadfunc(L, filename, name) == 0), filename); } @@ -418,7 +443,7 @@ static int searcher_Croot (lua_State *L) { int stat; if (p == NULL) return 0; /* is root */ lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath"); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); if (filename == NULL) return 1; /* root not found */ if ((stat = loadfunc(L, filename, name)) != 0) { if (stat != ERRFUNC) @@ -444,35 +469,46 @@ static int searcher_preload (lua_State *L) { } -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); +static void findloader (lua_State *L, const char *name) { int i; - 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 */ - /* else must load it; iterate over available seachers to find a loader */ - lua_getfield(L, lua_upvalueindex(1), "searchers"); - if (!lua_istable(L, -1)) + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ + if (!lua_istable(L, 3)) luaL_error(L, LUA_QL("package.searchers") " must be a table"); - lua_pushliteral(L, ""); /* error message accumulator */ - for (i=1; ; i++) { - lua_rawgeti(L, -2, i); /* get a seacher */ - if (lua_isnil(L, -1)) /* no more searchers? */ + /* iterate over available seachers to find a loader */ + for (i = 1; ; i++) { + lua_rawgeti(L, 3, i); /* get a seacher */ + if (lua_isnil(L, -1)) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ luaL_error(L, "module " LUA_QS " not found:%s", - name, lua_tostring(L, -2)); + name, lua_tostring(L, -1)); + } lua_pushstring(L, name); lua_call(L, 1, 2); /* call it */ if (lua_isfunction(L, -2)) /* did it find a loader? */ - break; /* module loader found */ + return; /* module loader found */ else if (lua_isstring(L, -2)) { /* searcher returned error message? */ lua_pop(L, 1); /* remove extra return */ - lua_concat(L, 2); /* accumulate error message */ + luaL_addvalue(&msg); /* concatenate error message */ } else lua_pop(L, 2); /* remove both returns */ } +} + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_settop(L, 1); /* _LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); /* _LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); lua_pushstring(L, name); /* pass name as argument to module loader */ lua_insert(L, -2); /* name is 1st argument (before search data) */ lua_call(L, 2, 1); /* run loader to load module */ @@ -516,9 +552,11 @@ static void set_env (lua_State *L) { 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); + if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } } } @@ -577,12 +615,25 @@ static int ll_seeall (lua_State *L) { /* auxiliary mark (for internal use) */ #define AUXMARK "\1" + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + static void setpath (lua_State *L, const char *fieldname, const char *envname1, const char *envname2, const char *def) { const char *path = getenv(envname1); if (path == NULL) /* no environment variable? */ path = getenv(envname2); /* try alternative name */ - if (path == NULL) /* no environment variable? */ + if (path == NULL || noenv(L)) /* no environment variable? */ lua_pushstring(L, def); /* use default */ else { /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ diff --git a/src/loadlib_rel.c b/src/loadlib_rel.c index 9ebd8cc..13fce89 100644 --- a/src/loadlib_rel.c +++ b/src/loadlib_rel.c @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.100 2011/07/05 12:49:35 roberto Exp $ +** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** @@ -9,6 +9,14 @@ */ +/* +** if needed, includes windows header before everything else +*/ +#if defined(_WIN32) +#include <windows.h> +#endif + + #include <stdlib.h> #include <string.h> @@ -62,6 +70,20 @@ #endif +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + /* prefix for open functions in C libraries */ #define LUA_POF "luaopen_" @@ -91,6 +113,7 @@ static void setprogdir (lua_State *L); /* ** {========================================================================= ** This determines the location of the executable for relative module loading +** Modified by the LuaDist project for UNIX platforms ** ========================================================================== */ #if defined(_WIN32) || defined(__CYGWIN__) @@ -161,7 +184,6 @@ static void setprogdir (lua_State *L) { } } - #if defined(LUA_USE_DLOPEN) /* ** {======================================================================== @@ -180,7 +202,7 @@ static void ll_unloadlib (void *lib) { static void *ll_load (lua_State *L, const char *path, int seeglb) { - void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : 0)); + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); if (lib == NULL) lua_pushstring(L, dlerror()); return lib; } @@ -203,8 +225,6 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { ** ======================================================================= */ -#include <windows.h> - /* ** optional flags for LoadLibraryEx */ @@ -229,7 +249,7 @@ static void ll_unloadlib (void *lib) { static void *ll_load (lua_State *L, const char *path, int seeglb) { HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); - (void)(seeglb); /* symbols are 'global' by default */ + (void)(seeglb); /* not used: symbols are 'global' by default */ if (lib == NULL) pusherror(L); return lib; } @@ -259,19 +279,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { static void ll_unloadlib (void *lib) { - (void)(lib); /* to avoid warnings */ + (void)(lib); /* not used */ } static void *ll_load (lua_State *L, const char *path, int seeglb) { - (void)(path); (void)(seeglb); /* to avoid warnings */ + (void)(path); (void)(seeglb); /* not used */ lua_pushliteral(L, DLMSG); return NULL; } static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - (void)(lib); (void)(sym); /* to avoid warnings */ + (void)(lib); (void)(sym); /* not used */ lua_pushliteral(L, DLMSG); return NULL; } @@ -374,10 +394,12 @@ static const char *pushnexttemplate (lua_State *L, const char *path) { static const char *searchpath (lua_State *L, const char *name, const char *path, - const char *sep) { + const char *sep, + const char *dirsep) { + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); if (*sep != '\0') /* non-empty separator? */ - name = luaL_gsub(L, name, sep, LUA_DIRSEP); /* replace it by proper one */ - lua_pushliteral(L, ""); /* error accumulator */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ while ((path = pushnexttemplate(L, path)) != NULL) { const char *filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); @@ -386,8 +408,9 @@ static const char *searchpath (lua_State *L, const char *name, return filename; /* return that file name */ lua_pushfstring(L, "\n\tno file " LUA_QS, filename); lua_remove(L, -2); /* remove file name */ - lua_concat(L, 2); /* add entry to possible error message */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ } + luaL_pushresult(&msg); /* create error message */ return NULL; /* not found */ } @@ -395,7 +418,8 @@ static const char *searchpath (lua_State *L, const char *name, static int ll_searchpath (lua_State *L) { const char *f = searchpath(L, luaL_checkstring(L, 1), luaL_checkstring(L, 2), - luaL_optstring(L, 3, ".")); + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); if (f != NULL) return 1; else { /* error message is on top of the stack */ lua_pushnil(L); @@ -406,13 +430,14 @@ static int ll_searchpath (lua_State *L) { static const char *findfile (lua_State *L, const char *name, - const char *pname) { + const char *pname, + const char *dirsep) { const char *path; lua_getfield(L, lua_upvalueindex(1), pname); path = lua_tostring(L, -1); if (path == NULL) luaL_error(L, LUA_QL("package.%s") " must be a string", pname); - return searchpath(L, name, path, "."); + return searchpath(L, name, path, ".", dirsep); } @@ -431,7 +456,7 @@ static int checkload (lua_State *L, int stat, const char *filename) { static int searcher_Lua (lua_State *L) { const char *filename; const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path"); + filename = findfile(L, name, "path", LUA_LSUBSEP); if (filename == NULL) return 1; /* module not found in this path */ return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); } @@ -457,7 +482,7 @@ static int loadfunc (lua_State *L, const char *filename, const char *modname) { static int searcher_C (lua_State *L) { const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath"); + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); if (filename == NULL) return 1; /* module not found in this path */ return checkload(L, (loadfunc(L, filename, name) == 0), filename); } @@ -470,7 +495,7 @@ static int searcher_Croot (lua_State *L) { int stat; if (p == NULL) return 0; /* is root */ lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath"); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); if (filename == NULL) return 1; /* root not found */ if ((stat = loadfunc(L, filename, name)) != 0) { if (stat != ERRFUNC) @@ -496,35 +521,46 @@ static int searcher_preload (lua_State *L) { } -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); +static void findloader (lua_State *L, const char *name) { int i; - 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 */ - /* else must load it; iterate over available seachers to find a loader */ - lua_getfield(L, lua_upvalueindex(1), "searchers"); - if (!lua_istable(L, -1)) + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ + if (!lua_istable(L, 3)) luaL_error(L, LUA_QL("package.searchers") " must be a table"); - lua_pushliteral(L, ""); /* error message accumulator */ - for (i=1; ; i++) { - lua_rawgeti(L, -2, i); /* get a seacher */ - if (lua_isnil(L, -1)) /* no more searchers? */ + /* iterate over available seachers to find a loader */ + for (i = 1; ; i++) { + lua_rawgeti(L, 3, i); /* get a seacher */ + if (lua_isnil(L, -1)) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ luaL_error(L, "module " LUA_QS " not found:%s", - name, lua_tostring(L, -2)); + name, lua_tostring(L, -1)); + } lua_pushstring(L, name); lua_call(L, 1, 2); /* call it */ if (lua_isfunction(L, -2)) /* did it find a loader? */ - break; /* module loader found */ + return; /* module loader found */ else if (lua_isstring(L, -2)) { /* searcher returned error message? */ lua_pop(L, 1); /* remove extra return */ - lua_concat(L, 2); /* accumulate error message */ + luaL_addvalue(&msg); /* concatenate error message */ } else lua_pop(L, 2); /* remove both returns */ } +} + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_settop(L, 1); /* _LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); /* _LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); lua_pushstring(L, name); /* pass name as argument to module loader */ lua_insert(L, -2); /* name is 1st argument (before search data) */ lua_call(L, 2, 1); /* run loader to load module */ @@ -568,9 +604,11 @@ static void set_env (lua_State *L) { 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); + if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } } } @@ -629,12 +667,25 @@ static int ll_seeall (lua_State *L) { /* auxiliary mark (for internal use) */ #define AUXMARK "\1" + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + static void setpath (lua_State *L, const char *fieldname, const char *envname1, const char *envname2, const char *def) { const char *path = getenv(envname1); if (path == NULL) /* no environment variable? */ path = getenv(envname2); /* try alternative name */ - if (path == NULL) /* no environment variable? */ + if (path == NULL || noenv(L)) /* no environment variable? */ lua_pushstring(L, def); /* use default */ else { /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ diff --git a/src/lobject.c b/src/lobject.c index d8cc3ce..cf0f754 100755..100644 --- a/src/lobject.c +++ b/src/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.52 2011/06/24 12:25:02 roberto Exp $ +** $Id: lobject.c,v 2.55 2011/11/30 19:30:16 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -33,7 +33,7 @@ LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if ** eeeee != 0 and (xxx) otherwise. */ -int luaO_int2fb (lu_int32 x) { +int luaO_int2fb (unsigned int x) { int e = 0; /* exponent */ if (x < 8) return x; while (x >= 0x10) { @@ -103,8 +103,8 @@ static int isneg (const char **s) { static lua_Number readhexa (const char **s, lua_Number r, int *count) { - while (lisxdigit(cast_uchar(**s))) { /* read integer part */ - r = (r * 16.0) + cast_num(luaO_hexavalue(cast_uchar(*(*s)++))); + for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ + r = (r * 16.0) + cast_num(luaO_hexavalue(cast_uchar(**s))); (*count)++; } return r; @@ -157,7 +157,9 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { int luaO_str2d (const char *s, size_t len, lua_Number *result) { char *endptr; - if (strpbrk(s, "xX")) /* hexa? */ + if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ + return 0; + else if (strpbrk(s, "xX")) /* hexa? */ *result = lua_strx2number(s, &endptr); else *result = lua_str2number(s, &endptr); @@ -219,7 +221,6 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { luaG_runerror(L, "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), *(e + 1)); - break; } } n += 2; diff --git a/src/lobject.h b/src/lobject.h index d69d615..06246bf 100755..100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.61 2011/07/04 20:29:02 roberto Exp $ +** $Id: lobject.h,v 2.64 2011/10/31 17:48:22 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -132,7 +132,7 @@ typedef struct lua_TValue TValue; #define ttislcf(o) checktag((o), LUA_TLCF) #define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) #define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) -#define ttisdeadkey(o) checktag((o), ctb(LUA_TDEADKEY)) +#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) #define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) @@ -151,6 +151,8 @@ typedef struct lua_TValue TValue; #define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) #define bvalue(o) check_exp(ttisboolean(o), val_(o).b) #define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) +/* a dead value may get the 'gc' field, but cannot access its contents */ +#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) @@ -224,7 +226,7 @@ typedef struct lua_TValue TValue; val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TPROTO)); \ checkliveness(G(L),io); } -#define setdeadvalue(obj) settt_(obj, ctb(LUA_TDEADKEY)) +#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) @@ -262,51 +264,73 @@ typedef struct lua_TValue TValue; ** ======================================================= */ -#if defined(LUA_NANTRICKLE) || defined(LUA_NANTRICKBE) +#if defined(LUA_NANTRICK) \ + || defined(LUA_NANTRICK_LE) \ + || defined(LUA_NANTRICK_BE) /* ** numbers are represented in the 'd_' field. All other values have the -** value (NNMARK | tag) in 'tt_'. A number with such pattern would be +** value (NNMARK | tag) in 'tt__'. A number with such pattern would be ** a "signaled NaN", which is never generated by regular operations by ** the CPU (nor by 'strtod') */ #if !defined(NNMARK) #define NNMARK 0x7FF7A500 +#define NNMASK 0x7FFFFF00 #endif #undef TValuefields #undef NILCONSTANT -#if defined(LUA_NANTRICKLE) + +#if defined(LUA_NANTRICK_LE) + /* little endian */ #define TValuefields \ - union { struct { Value v_; int tt_; } i; double d_; } u + union { struct { Value v__; int tt__; } i; double d__; } u #define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} -#else +/* field-access macros */ +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) + +#elif defined(LUA_NANTRICK_BE) + /* big endian */ #define TValuefields \ - union { struct { int tt_; Value v_; } i; double d_; } u + union { struct { int tt__; Value v__; } i; double d__; } u #define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} +/* field-access macros */ +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) + +#elif !defined(TValuefields) +#error option 'LUA_NANTRICK' needs declaration for 'TValuefields' + #endif + +/* correspondence with standard representation */ +#undef val_ +#define val_(o) v_(o) +#undef num_ +#define num_(o) d_(o) + + #undef numfield #define numfield /* no such field; numbers are the entire struct */ /* basic check to distinguish numbers from non-numbers */ #undef ttisnumber -#define ttisnumber(o) (((o)->u.i.tt_ & 0x7fffff00) != NNMARK) +#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) #define tag2tt(t) (NNMARK | (t)) -#undef val_ -#define val_(o) ((o)->u.i.v_) -#undef num_ -#define num_(o) ((o)->u.d_) - #undef rttype -#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : (o)->u.i.tt_ & 0xff) +#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) #undef settt_ -#define settt_(o,t) ((o)->u.i.tt_=tag2tt(t)) +#define settt_(o,t) (tt_(o) = tag2tt(t)) #undef setnvalue #define setnvalue(obj,x) \ @@ -324,11 +348,11 @@ typedef struct lua_TValue TValue; */ #undef checktag -#define checktag(o,t) ((o)->u.i.tt_ == tag2tt(t)) +#define checktag(o,t) (tt_(o) == tag2tt(t)) #undef ttisequal #define ttisequal(o1,o2) \ - (ttisnumber(o1) ? ttisnumber(o2) : ((o1)->u.i.tt_ == (o2)->u.i.tt_)) + (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) @@ -435,11 +459,11 @@ typedef struct Proto { TValue *k; /* constants used by the function */ Instruction *code; struct Proto **p; /* functions defined inside the function */ - int *lineinfo; /* map from opcodes to source lines */ - LocVar *locvars; /* information about local variables */ + int *lineinfo; /* map from opcodes to source lines (debug information) */ + LocVar *locvars; /* information about local variables (debug information) */ Upvaldesc *upvalues; /* upvalue information */ union Closure *cache; /* last created closure with this prototype */ - TString *source; + TString *source; /* used for debug information */ int sizeupvalues; /* size of 'upvalues' */ int sizek; /* size of `k' */ int sizecode; diff --git a/src/lopcodes.c b/src/lopcodes.c index 2e34676..2e34676 100755..100644 --- a/src/lopcodes.c +++ b/src/lopcodes.c diff --git a/src/lopcodes.h b/src/lopcodes.h index 01c69bd..07d2b3f 100755..100644 --- a/src/lopcodes.h +++ b/src/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.141 2011/04/19 16:22:13 roberto Exp $ +** $Id: lopcodes.h,v 1.142 2011/07/15 12:50:29 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -196,7 +196,7 @@ OP_LEN,/* A B R(A) := length of R(B) */ OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ -OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */ +OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */ 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++ */ diff --git a/src/loslib.c b/src/loslib.c index 585ba78..881667d 100755..100644 --- a/src/loslib.c +++ b/src/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.35 2011/06/20 16:50:59 roberto Exp $ +** $Id: loslib.c,v 1.38 2011/11/30 12:35:05 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -58,6 +58,23 @@ #endif +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ +#if defined(LUA_USE_GMTIME_R) + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#elif !defined(l_gmtime) + +#define l_gmtime(t,r) ((void)r, gmtime(t)) +#define l_localtime(t,r) ((void)r, localtime(t)) + +#endif + + static int os_execute (lua_State *L) { const char *cmd = luaL_optstring(L, 1, NULL); @@ -177,13 +194,13 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) { static int os_date (lua_State *L) { const char *s = luaL_optstring(L, 1, "%c"); time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); - struct tm *stm; + struct tm tmr, *stm; if (*s == '!') { /* UTC? */ - stm = gmtime(&t); + stm = l_gmtime(&t, &tmr); s++; /* skip `!' */ } else - stm = localtime(&t); + stm = l_localtime(&t, &tmr); if (stm == NULL) /* invalid date? */ lua_pushnil(L); else if (strcmp(s, "*t") == 0) { @@ -274,7 +291,8 @@ static int os_exit (lua_State *L) { status = luaL_optint(L, 1, EXIT_SUCCESS); if (lua_toboolean(L, 2)) lua_close(L); - exit(status); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; } diff --git a/src/lparser.c b/src/lparser.c index d9c4173..4d68936 100755..100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.113 2011/07/02 15:58:14 roberto Exp $ +** $Id: lparser.c,v 2.124 2011/12/02 13:23:56 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -41,8 +41,8 @@ */ typedef struct BlockCnt { struct BlockCnt *previous; /* chain */ - int firstlabel; /* index of first label in this block */ - int firstgoto; /* index of first pending goto in this block */ + short firstlabel; /* index of first label in this block */ + short firstgoto; /* index of first pending goto in this block */ lu_byte nactvar; /* # active locals outside the block */ lu_byte upval; /* true if some variable in the block is an upvalue */ lu_byte isloop; /* true if `block' is a loop */ @@ -68,26 +68,27 @@ static void anchor_token (LexState *ls) { /* semantic error */ -static void semerror (LexState *ls, const char *msg) { +static l_noret semerror (LexState *ls, const char *msg) { ls->t.token = 0; /* remove 'near to' from final message */ luaX_syntaxerror(ls, msg); } -static void error_expected (LexState *ls, int token) { +static l_noret error_expected (LexState *ls, int token) { luaX_syntaxerror(ls, luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); } -static void errorlimit (FuncState *fs, int limit, const char *what) { +static l_noret errorlimit (FuncState *fs, int limit, const char *what) { + lua_State *L = fs->ls->L; const char *msg; int line = fs->f->linedefined; const char *where = (line == 0) ? "main function" - : luaO_pushfstring(fs->L, "function at line %d", line); - msg = luaO_pushfstring(fs->L, "too many %s (limit is %d) in %s", - what, limit, where); + : luaO_pushfstring(L, "function at line %d", line); + msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", + what, limit, where); luaX_syntaxerror(fs->ls, msg); } @@ -182,7 +183,7 @@ static void new_localvar (LexState *ls, TString *name) { MAXVARS, "local variables"); luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, dyd->actvar.size, Vardesc, MAX_INT, "local variables"); - dyd->actvar.arr[dyd->actvar.n++].idx = cast(unsigned short, reg); + dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); } @@ -231,13 +232,13 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { Proto *f = fs->f; int oldsize = f->sizeupvalues; checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); - luaM_growvector(fs->L, f->upvalues, fs->nups, f->sizeupvalues, + luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, Upvaldesc, MAXUPVAL, "upvalues"); while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; f->upvalues[fs->nups].instack = (v->k == VLOCAL); f->upvalues[fs->nups].idx = cast_byte(v->u.info); f->upvalues[fs->nups].name = name; - luaC_objbarrier(fs->L, f, name); + luaC_objbarrier(fs->ls->L, f, name); return fs->nups++; } @@ -327,13 +328,13 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { static void enterlevel (LexState *ls) { - global_State *g = G(ls->L); - ++g->nCcalls; - checklimit(ls->fs, g->nCcalls, LUAI_MAXCCALLS, "syntax levels"); + lua_State *L = ls->L; + ++L->nCcalls; + checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); } -#define leavelevel(ls) (G((ls)->L)->nCcalls--) +#define leavelevel(ls) ((ls)->L->nCcalls--) static void closegoto (LexState *ls, int g, Labeldesc *label) { @@ -343,9 +344,10 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) { Labeldesc *gt = &gl->arr[g]; lua_assert(eqstr(gt->name, label->name)); if (gt->nactvar < label->nactvar) { + TString *vname = getlocvar(fs, gt->nactvar)->varname; const char *msg = luaO_pushfstring(ls->L, "<goto %s> at line %d jumps into the scope of local " LUA_QS, - getstr(gt->name), gt->line, getstr(getlocvar(fs, gt->nactvar)->varname)); + getstr(gt->name), gt->line, getstr(vname)); semerror(ls, msg); } luaK_patchlist(fs, gt->pc, label->pc); @@ -382,7 +384,8 @@ static int findlabel (LexState *ls, int g) { static int newlabelentry (LexState *ls, Labellist *l, TString *name, int line, int pc) { int n = l->n; - luaM_growvector(ls->L, l->arr, n, l->size, Labeldesc, MAX_INT, "labels"); + luaM_growvector(ls->L, l->arr, n, l->size, + Labeldesc, SHRT_MAX, "labels/gotos"); l->arr[n].name = name; l->arr[n].line = line; l->arr[n].nactvar = ls->fs->nactvar; @@ -418,7 +421,7 @@ static void movegotosout (FuncState *fs, BlockCnt *bl) { int i = bl->firstgoto; Labellist *gl = &fs->ls->dyd->gt; /* correct pending gotos to current block and try to close it - with visible labels */ + with visible labels */ while (i < gl->n) { Labeldesc *gt = &gl->arr[i]; if (gt->nactvar > bl->nactvar) { @@ -457,7 +460,7 @@ static void breaklabel (LexState *ls) { ** generates an error for an undefined 'goto'; choose appropriate ** message when label name is a reserved word (which can only be 'break') */ -static void undefgoto (LexState *ls, Labeldesc *gt) { +static l_noret undefgoto (LexState *ls, Labeldesc *gt) { const char *msg = (gt->name->tsv.reserved > 0) ? "<%s> at line %d not inside a loop" : "no visible label " LUA_QS " for <goto> at line %d"; @@ -514,7 +517,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { Proto *f; fs->prev = ls->fs; /* linked list of funcstates */ fs->ls = ls; - fs->L = L; ls->fs = fs; fs->pc = 0; fs->lasttarget = 0; @@ -850,7 +852,6 @@ static void funcargs (LexState *ls, expdesc *f, int line) { } default: { luaX_syntaxerror(ls, "function arguments expected"); - return; } } lua_assert(f->k == VNONRELOC); @@ -895,7 +896,6 @@ static void prefixexp (LexState *ls, expdesc *v) { } default: { luaX_syntaxerror(ls, "unexpected symbol"); - return; } } } @@ -1039,7 +1039,7 @@ static const struct { ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } ** where `binop' is any binary operator with a priority higher than `limit' */ -static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { BinOpr op; UnOpr uop; enterlevel(ls); @@ -1105,31 +1105,34 @@ struct LHS_assign { /* -** check whether, in an assignment to a local variable, the local variable -** is needed in a previous assignment (to a table). If so, save original -** local value in a safe place and use this safe copy in the previous -** assignment. +** check whether, in an assignment to an upvalue/local variable, the +** upvalue/local variable is begin used in a previous assignment to a +** table. If so, save original upvalue/local value in a safe place and +** use this safe copy in the previous assignment. */ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { FuncState *fs = ls->fs; int extra = fs->freereg; /* eventual position to save local variable */ int conflict = 0; - for (; lh; lh = lh->prev) { - /* conflict in table 't'? */ - if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { - conflict = 1; - lh->v.u.ind.vt = VLOCAL; - lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ - } - /* conflict in index 'idx'? */ - if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { - conflict = 1; - lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + for (; lh; lh = lh->prev) { /* check all previous assignments */ + if (lh->v.k == VINDEXED) { /* assigning to a table? */ + /* table is the upvalue/local being assigned now? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { + conflict = 1; + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ + } + /* index is the local being assigned? (index cannot be upvalue) */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + } } } if (conflict) { + /* copy upvalue/local value to a temporary (in position 'extra') */ OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; - luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */ + luaK_codeABC(fs, op, extra, v->u.info, 0); luaK_reserveregs(fs, 1); } } @@ -1144,8 +1147,8 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { primaryexp(ls, &nv.v); if (nv.v.k != VINDEXED) check_conflict(ls, lh, &nv.v); - checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls, - "variable names"); + checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, + "C levels"); assignment(ls, &nv, nvars+1); } else { /* assignment -> `=' explist */ @@ -1178,10 +1181,18 @@ static int cond (LexState *ls) { } -static void gotostat (LexState *ls, TString *label, int line) { - /* create new entry for this goto */ - int g = newlabelentry(ls, &ls->dyd->gt, label, line, luaK_jump(ls->fs)); - findlabel(ls, g); +static void gotostat (LexState *ls, int pc) { + int line = ls->linenumber; + TString *label; + int g; + if (testnext(ls, TK_GOTO)) + label = str_checkname(ls); + else { + luaX_next(ls); /* skip break */ + label = luaS_new(ls->L, "break"); + } + g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); + findlabel(ls, g); /* close it if label already defined */ } @@ -1190,7 +1201,7 @@ static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { int i; for (i = fs->bl->firstlabel; i < ll->n; i++) { if (eqstr(label, ll->arr[i].name)) { - const char *msg = luaO_pushfstring(fs->ls->L, + const char *msg = luaO_pushfstring(fs->ls->L, "label " LUA_QS " already defined on line %d", getstr(label), ll->arr[i].line); semerror(fs->ls, msg); @@ -1360,38 +1371,51 @@ static void forstat (LexState *ls, int line) { } -static int test_then_block (LexState *ls) { +static void test_then_block (LexState *ls, int *escapelist) { /* test_then_block -> [IF | ELSEIF] cond THEN block */ - int condexit; + BlockCnt bl; + FuncState *fs = ls->fs; + expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ luaX_next(ls); /* skip IF or ELSEIF */ - condexit = cond(ls); + expr(ls, &v); /* read condition */ checknext(ls, TK_THEN); - block(ls); /* `then' part */ - return condexit; + if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ + if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ + leaveblock(fs); + return; /* and that is it */ + } + else /* must skip over 'then' part if condition is false */ + jf = luaK_jump(fs); + } + else { /* regular case (not goto/break) */ + luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* `then' part */ + leaveblock(fs); + if (ls->t.token == TK_ELSE || + ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ + luaK_patchtohere(fs, jf); } static void ifstat (LexState *ls, int line) { /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ FuncState *fs = ls->fs; - int flist; - int escapelist = NO_JUMP; - flist = test_then_block(ls); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchtohere(fs, flist); - flist = test_then_block(ls); /* ELSEIF cond THEN block */ - } - if (ls->t.token == TK_ELSE) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchtohere(fs, flist); - luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ + int escapelist = NO_JUMP; /* exit list for finished parts */ + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) block(ls); /* `else' part */ - } - else - luaK_concat(fs, &escapelist, flist); - luaK_patchtohere(fs, escapelist); check_match(ls, TK_END, TK_IF, line); + luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ } @@ -1551,15 +1575,9 @@ static void statement (LexState *ls) { retstat(ls); break; } - case TK_BREAK: { /* stat -> breakstat */ - luaX_next(ls); /* skip BREAK */ - /* code it as "goto 'break'" */ - gotostat(ls, luaS_new(ls->L, "break"), line); - break; - } + case TK_BREAK: /* stat -> breakstat */ case TK_GOTO: { /* stat -> 'goto' NAME */ - luaX_next(ls); /* skip GOTO */ - gotostat(ls, str_checkname(ls), line); + gotostat(ls, luaK_jump(ls->fs)); break; } default: { /* stat -> func | assignment */ @@ -1595,8 +1613,8 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, close_func(&lexstate); L->top--; /* pop name */ lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); - return funcstate.f; /* all scopes should be correctly finished */ lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); + return funcstate.f; } diff --git a/src/lparser.h b/src/lparser.h index 4e7e06f..caabf46 100755..100644 --- a/src/lparser.h +++ b/src/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.68 2011/02/23 13:13:10 roberto Exp $ +** $Id: lparser.h,v 1.69 2011/07/27 18:09:01 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -55,7 +55,7 @@ typedef struct expdesc { /* description of active local variable */ typedef struct Vardesc { - unsigned short idx; /* variable index in stack */ + short idx; /* variable index in stack */ } Vardesc; @@ -98,18 +98,17 @@ typedef struct FuncState { Table *h; /* table to find (and reuse) elements in `k' */ struct FuncState *prev; /* enclosing function */ struct LexState *ls; /* lexical state */ - struct lua_State *L; /* copy of the Lua state */ struct BlockCnt *bl; /* chain of current blocks */ int pc; /* next position to code (equivalent to `ncode') */ - int lasttarget; /* `pc' of last `jump target' */ + int lasttarget; /* 'label' of last 'jump label' */ int jpc; /* list of pending jumps to `pc' */ - int freereg; /* first free register */ int nk; /* number of elements in `k' */ int np; /* number of elements in `p' */ - int firstlocal; /* index of first local var of this function */ - short nlocvars; /* number of elements in `locvars' */ + int firstlocal; /* index of first local var (in Dyndata array) */ + short nlocvars; /* number of elements in 'f->locvars' */ lu_byte nactvar; /* number of active local variables */ lu_byte nups; /* number of upvalues */ + lu_byte freereg; /* first free register */ } FuncState; diff --git a/src/lstate.c b/src/lstate.c index 45dac3c..6e2801c 100755..100644 --- a/src/lstate.c +++ b/src/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.89 2010/12/20 19:40:07 roberto Exp $ +** $Id: lstate.c,v 2.92 2011/10/03 17:54:25 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -136,10 +136,10 @@ static void init_registry (lua_State *L, global_State *g) { luaH_resize(L, registry, LUA_RIDX_LAST, 0); /* registry[LUA_RIDX_MAINTHREAD] = L */ setthvalue(L, &mt, L); - setobj2t(L, luaH_setint(L, registry, LUA_RIDX_MAINTHREAD), &mt); + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); /* registry[LUA_RIDX_GLOBALS] = table of globals */ sethvalue(L, &mt, luaH_new(L)); - setobj2t(L, luaH_setint(L, registry, LUA_RIDX_GLOBALS), &mt); + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); } @@ -171,6 +171,7 @@ static void preinit_state (lua_State *L, global_State *g) { L->ci = NULL; L->stacksize = 0; L->errorJmp = NULL; + L->nCcalls = 0; L->hook = NULL; L->hookmask = 0; L->basehookcount = 0; @@ -191,7 +192,7 @@ static void close_state (lua_State *L) { luaZ_freebuffer(L, &g->buff); freestack(L); lua_assert(gettotalbytes(g) == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); + (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ } @@ -237,7 +238,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); L->marked = luaC_white(g); g->gckind = KGC_NORMAL; - g->nCcalls = 0; preinit_state(L, g); g->frealloc = f; g->ud = ud; @@ -279,9 +279,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { LUA_API void lua_close (lua_State *L) { L = G(L)->mainthread; /* only the main thread can be closed */ lua_lock(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_separateudata(L, 1); /* separate all udata with GC metamethods */ - lua_assert(L->next == NULL); luai_userstateclose(L); close_state(L); } diff --git a/src/lstate.h b/src/lstate.h index 9d21e7e..4743d74 100755..100644 --- a/src/lstate.h +++ b/src/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.72 2011/06/02 19:31:40 roberto Exp $ +** $Id: lstate.h,v 2.74 2011/09/30 12:45:07 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -47,8 +47,6 @@ struct lua_longjmp; /* defined in ldo.c */ #define EXTRA_STACK 5 -#define BASIC_CI_SIZE 8 - #define BASIC_STACK_SIZE (2*LUA_MINSTACK) @@ -118,7 +116,6 @@ typedef struct global_State { lu_mem lastmajormem; /* memory in use after last major collection */ stringtable strt; /* hash table for strings */ TValue l_registry; - unsigned short nCcalls; /* number of nested C calls */ lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ lu_byte gckind; /* kind of GC running */ @@ -161,6 +158,7 @@ struct lua_State { StkId stack; /* stack base */ int stacksize; unsigned short nny; /* number of non-yieldable calls in stack */ + unsigned short nCcalls; /* number of nested C calls */ lu_byte hookmask; lu_byte allowhook; int basehookcount; diff --git a/src/lstring.c b/src/lstring.c index adec415..adec415 100755..100644 --- a/src/lstring.c +++ b/src/lstring.c diff --git a/src/lstring.h b/src/lstring.h index d708a1b..d708a1b 100755..100644 --- a/src/lstring.h +++ b/src/lstring.h diff --git a/src/lstrlib.c b/src/lstrlib.c index 5e200f1..f5d61fd 100755..100644 --- a/src/lstrlib.c +++ b/src/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.170 2011/06/28 17:13:52 roberto Exp $ +** $Id: lstrlib.c,v 1.173 2011/11/30 18:24:56 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -138,7 +138,7 @@ static int str_byte (lua_State *L) { if (pose > l) pose = l; if (posi > pose) return 0; /* empty interval; return no values */ n = (int)(pose - posi + 1); - if (posi + n <= pose) /* overflow? */ + if (posi + n <= pose) /* (size_t -> int) overflow? */ return luaL_error(L, "string slice too long"); luaL_checkstack(L, n, "string slice too long"); for (i=0; i<n; i++) @@ -154,7 +154,7 @@ static int str_char (lua_State *L) { char *p = luaL_buffinitsize(L, &b, n); for (i=1; i<=n; i++) { int c = luaL_checkint(L, i); - luaL_argcheck(L, uchar(c) == c, i, "invalid value"); + luaL_argcheck(L, uchar(c) == c, i, "value out of range"); p[i - 1] = uchar(c); } luaL_pushresultsize(&b, n); @@ -756,6 +756,9 @@ static int str_gsub (lua_State *L) { #endif #endif /* } */ +#define MAX_UINTFRM ((lua_Number)(~(unsigned LUA_INTFRM_T)0)) +#define MAX_INTFRM ((lua_Number)((~(unsigned LUA_INTFRM_T)0)/2)) +#define MIN_INTFRM (-(lua_Number)((~(unsigned LUA_INTFRM_T)0)/2) - 1) /* ** LUA_FLTFRMLEN is the length modifier for float conversions in @@ -865,13 +868,20 @@ static int str_format (lua_State *L) { nb = sprintf(buff, form, luaL_checkint(L, arg)); break; } - case 'd': case 'i': + case 'd': case 'i': { + lua_Number n = luaL_checknumber(L, arg); + luaL_argcheck(L, (MIN_INTFRM - 1) < n && n < (MAX_INTFRM + 1), arg, + "not a number in proper range"); + addlenmod(form, LUA_INTFRMLEN); + nb = sprintf(buff, form, (LUA_INTFRM_T)n); + break; + } case 'o': case 'u': case 'x': case 'X': { lua_Number n = luaL_checknumber(L, arg); - LUA_INTFRM_T r = (n < 0) ? (LUA_INTFRM_T)n : - (LUA_INTFRM_T)(unsigned LUA_INTFRM_T)n; + luaL_argcheck(L, 0 <= n && n < (MAX_UINTFRM + 1), arg, + "not a non-negative number in proper range"); addlenmod(form, LUA_INTFRMLEN); - nb = sprintf(buff, form, r); + nb = sprintf(buff, form, (unsigned LUA_INTFRM_T)n); break; } case 'e': case 'E': case 'f': diff --git a/src/ltable.c b/src/ltable.c index a937959..9581add 100755..100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.60 2011/06/16 14:14:31 roberto Exp $ +** $Id: ltable.c,v 2.67 2011/11/30 12:41:45 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -64,13 +64,6 @@ #define hashpointer(t,p) hashmod(t, IntPoint(p)) -/* -** number of ints inside a lua_Number -*/ -#define numints cast_int(sizeof(lua_Number)/sizeof(int)) - - - #define dummynode (&dummynode_) #define isdummy(n) ((n) == dummynode) @@ -148,19 +141,19 @@ static int findindex (lua_State *L, Table *t, StkId key) { return i-1; /* yes; that's the index (corrected to C) */ else { Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ + for (;;) { /* check whether `key' is somewhere in the chain */ /* key may be dead already, but it is ok to use it in `next' */ if (luaV_rawequalobj(gkey(n), key) || (ttisdeadkey(gkey(n)) && iscollectable(key) && - gcvalue(gkey(n)) == gcvalue(key))) { + deadvalue(gkey(n)) == gcvalue(key))) { i = cast_int(n - gnode(t, 0)); /* key index in hash table */ /* hash elements are numbered after array ones */ return i + t->sizearray; } else n = gnext(n); - } while (n); - luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ - return 0; /* to avoid warnings */ + if (n == NULL) + luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ + } } } @@ -314,7 +307,7 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { /* re-insert elements from vanishing slice */ for (i=nasize; i<oldasize; i++) { if (!ttisnil(&t->array[i])) - setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]); + luaH_setint(L, t, i + 1, &t->array[i]); } /* shrink array */ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); @@ -322,11 +315,14 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { /* re-insert elements from hash part */ for (i = twoto(oldhsize) - 1; i >= 0; i--) { Node *old = nold+i; - if (!ttisnil(gval(old))) + if (!ttisnil(gval(old))) { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); + } } if (!isdummy(nold)) - luaM_freearray(L, nold, twoto(oldhsize)); /* free old array */ + luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */ } @@ -374,7 +370,7 @@ Table *luaH_new (lua_State *L) { void luaH_free (lua_State *L, Table *t) { if (!isdummy(t->node)) - luaM_freearray(L, t->node, sizenode(t)); + luaM_freearray(L, t->node, cast(size_t, sizenode(t))); luaM_freearray(L, t->array, t->sizearray); luaM_free(L, t); } @@ -398,14 +394,19 @@ static Node *getfreepos (Table *t) { ** put new key in its main position; otherwise (colliding node is in its main ** position), new key goes to an empty position. */ -static TValue *newkey (lua_State *L, Table *t, const TValue *key) { - Node *mp = mainposition(t, key); +TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp; + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) + luaG_runerror(L, "table index is NaN"); + mp = mainposition(t, key); if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ Node *othern; 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 */ + /* whatever called 'newkey' take care of TM cache and GC barrier */ + return luaH_set(L, t, key); /* insert key into grown table */ } lua_assert(!isdummy(n)); othern = mainposition(t, gkey(mp)); @@ -493,41 +494,29 @@ const TValue *luaH_get (Table *t, const TValue *key) { } +/* +** beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { const TValue *p = luaH_get(t, key); - t->flags = 0; if (p != luaO_nilobject) return cast(TValue *, p); - else { - if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) - luaG_runerror(L, "table index is NaN"); - return newkey(L, t, key); - } + else return luaH_newkey(L, t, key); } -TValue *luaH_setint (lua_State *L, Table *t, int key) { +void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { const TValue *p = luaH_getint(t, key); + TValue *cell; if (p != luaO_nilobject) - return cast(TValue *, p); + cell = cast(TValue *, p); else { TValue k; setnvalue(&k, cast_num(key)); - return newkey(L, t, &k); - } -} - - -TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { - const TValue *p = luaH_getstr(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else { - TValue k; - setsvalue(L, &k, key); - return newkey(L, t, &k); + cell = luaH_newkey(L, t, &k); } + setobj2t(L, cell, value); } diff --git a/src/ltable.h b/src/ltable.h index c14b028..2f6f5c2 100755..100644 --- a/src/ltable.h +++ b/src/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.14 2010/06/25 12:18:10 roberto Exp $ +** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -15,12 +15,14 @@ #define gval(n) (&(n)->i_val) #define gnext(n) ((n)->i_key.nk.next) +#define invalidateTMcache(t) ((t)->flags = 0) + LUAI_FUNC const TValue *luaH_getint (Table *t, int key); -LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, int key); +LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); LUAI_FUNC Table *luaH_new (lua_State *L); LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); diff --git a/src/ltablib.c b/src/ltablib.c index 06353c7..a52add0 100755..100644 --- a/src/ltablib.c +++ b/src/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.61 2011/07/05 12:49:35 roberto Exp $ +** $Id: ltablib.c,v 1.63 2011/11/28 17:26:30 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -86,7 +86,7 @@ static void addfield (lua_State *L, luaL_Buffer *b, int i) { if (!lua_isstring(L, -1)) luaL_error(L, "invalid value (%s) at index %d in table for " LUA_QL("concat"), luaL_typename(L, -1), i); - luaL_addvalue(b); + luaL_addvalue(b); } @@ -129,8 +129,7 @@ static int pack (lua_State *L) { for (i = n; i >= 2; i--) /* assign other elements */ lua_rawseti(L, 1, i); } - lua_pushinteger(L, n); - return 2; /* return table and number of elements */ + return 1; /* return table */ } diff --git a/src/ltm.c b/src/ltm.c index e70006d..e70006d 100755..100644 --- a/src/ltm.c +++ b/src/ltm.c diff --git a/src/ltm.h b/src/ltm.h index 89bdc19..89bdc19 100755..100644 --- a/src/ltm.h +++ b/src/ltm.h diff --git a/src/lua.c b/src/lua.c index 8b317c6..e20ab86 100755..100644 --- a/src/lua.c +++ b/src/lua.c @@ -1,5 +1,5 @@ /* -** $Id: lua.c,v 1.200 2011/06/16 14:30:58 roberto Exp $ +** $Id: lua.c,v 1.203 2011/12/12 16:34:03 roberto Exp $ ** Lua stand-alone interpreter ** See Copyright Notice in lua.h */ @@ -118,6 +118,7 @@ static void print_usage (const char *badoption) { " -i enter interactive mode after executing " LUA_QL("script") "\n" " -l name require library " LUA_QL("name") "\n" " -v show version information\n" + " -E ignore environment variables\n" " -- stop handling options\n" " - stop handling options and execute stdin\n" , @@ -348,7 +349,16 @@ static int handle_script (lua_State *L, char **argv, int n) { #define noextrachars(x) {if ((x)[2] != '\0') return -1;} -static int collectargs (char **argv, int *pi, int *pv, int *pe) { +/* indices of various argument indicators in array args */ +#define has_i 0 /* -i */ +#define has_v 1 /* -v */ +#define has_e 2 /* -e */ +#define has_E 3 /* -E */ + +#define num_has 4 /* number of 'has_*' */ + + +static int collectargs (char **argv, int *args) { int i; for (i = 1; argv[i] != NULL; i++) { if (argv[i][0] != '-') /* not an option? */ @@ -359,15 +369,18 @@ static int collectargs (char **argv, int *pi, int *pv, int *pe) { return (argv[i+1] != NULL ? i+1 : 0); case '\0': return i; + case 'E': + args[has_E] = 1; + break; case 'i': noextrachars(argv[i]); - *pi = 1; /* go through */ + args[has_i] = 1; /* go through */ case 'v': noextrachars(argv[i]); - *pv = 1; + args[has_v] = 1; break; case 'e': - *pe = 1; /* go through */ + args[has_e] = 1; /* go through */ case 'l': /* both options need an argument */ if (argv[i][2] == '\0') { /* no concatenated argument? */ i++; /* try next 'argv' */ @@ -430,28 +443,33 @@ static int pmain (lua_State *L) { int argc = (int)lua_tointeger(L, 1); char **argv = (char **)lua_touserdata(L, 2); int script; - int has_i = 0, has_v = 0, has_e = 0; + int args[num_has]; + args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0; if (argv[0] && argv[0][0]) progname = argv[0]; - script = collectargs(argv, &has_i, &has_v, &has_e); + script = collectargs(argv, args); if (script < 0) { /* invalid arg? */ print_usage(argv[-script]); return 0; } - if (has_v) print_version(); + if (args[has_v]) print_version(); + if (args[has_E]) { /* option '-E'? */ + lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } /* open standard libraries */ luaL_checkversion(L); lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ luaL_openlibs(L); /* open libraries */ lua_gc(L, LUA_GCRESTART, 0); - /* run LUA_INIT */ - if (handle_luainit(L) != LUA_OK) return 0; + if (!args[has_E] && handle_luainit(L) != LUA_OK) + return 0; /* error running LUA_INIT */ /* execute arguments -e and -l */ if (!runargs(L, argv, (script > 0) ? script : argc)) return 0; /* execute main script (if there is one) */ if (script && handle_script(L, argv, script) != LUA_OK) return 0; - if (has_i) /* -i option? */ + if (args[has_i]) /* -i option? */ dotty(L); - else if (script == 0 && !has_e && !has_v) { /* no arguments? */ + else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */ if (lua_stdin_is_tty()) { print_version(); dotty(L); diff --git a/src/lua.h b/src/lua.h index 518d44c..1fafa45 100755..100644 --- a/src/lua.h +++ b/src/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.278 2011/07/02 16:00:15 roberto Exp $ +** $Id: lua.h,v 1.282 2011/11/29 15:55:08 roberto Exp $ ** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -19,7 +19,7 @@ #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "2" #define LUA_VERSION_NUM 502 -#define LUA_VERSION_RELEASE "0" " (beta)" +#define LUA_VERSION_RELEASE "0" #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE @@ -215,10 +215,12 @@ LUA_API int (lua_pushthread) (lua_State *L); /* ** get functions (Lua -> stack) */ +LUA_API void (lua_getglobal) (lua_State *L, const char *var); LUA_API void (lua_gettable) (lua_State *L, int idx); LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); LUA_API void (lua_rawget) (lua_State *L, int idx); LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); LUA_API int (lua_getmetatable) (lua_State *L, int objindex); @@ -228,10 +230,12 @@ LUA_API void (lua_getuservalue) (lua_State *L, int idx); /* ** set functions (stack -> Lua) */ +LUA_API void (lua_setglobal) (lua_State *L, const char *var); LUA_API void (lua_settable) (lua_State *L, int idx); LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); LUA_API void (lua_rawset) (lua_State *L, int idx); LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); LUA_API int (lua_setmetatable) (lua_State *L, int objindex); LUA_API void (lua_setuservalue) (lua_State *L, int idx); @@ -250,7 +254,8 @@ LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, #define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname); + const char *chunkname, + const char *mode); LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); @@ -261,7 +266,7 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, lua_CFunction k); #define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) -LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); LUA_API int (lua_status) (lua_State *L); /* @@ -314,13 +319,6 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); #define lua_newtable(L) lua_createtable(L, 0, 0) -#define lua_setglobal(L,s) \ - (lua_pushglobaltable(L), lua_pushvalue(L, -2), \ - lua_setfield(L, -2, (s)), lua_pop(L, 2)) - -#define lua_getglobal(L,s) \ - (lua_pushglobaltable(L), lua_getfield(L, -1, (s)), lua_remove(L, -2)) - #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) diff --git a/src/lua.hpp b/src/lua.hpp index ec417f5..ec417f5 100755..100644 --- a/src/lua.hpp +++ b/src/lua.hpp diff --git a/src/luac.c b/src/luac.c index 62ff9cc..5081836 100755..100644 --- a/src/luac.c +++ b/src/luac.c @@ -1,5 +1,5 @@ /* -** $Id: luac.c,v 1.67 2011/06/21 12:29:00 lhf Exp $ +** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $ ** Lua compiler (saves bytecodes to files; also list bytecodes) ** See Copyright Notice in lua.h */ @@ -53,7 +53,7 @@ static void usage(const char* message) fprintf(stderr, "usage: %s [options] [filenames]\n" "Available options are:\n" - " -l list\n" + " -l list (use -l -l for full listing)\n" " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" " -p parse only\n" " -s strip debug information\n" @@ -141,7 +141,7 @@ static const Proto* combine(lua_State* L, int n) { Proto* f; int i=n; - if (lua_load(L,reader,&i,"=(" PROGNAME ")")!=LUA_OK) fatal(lua_tostring(L,-1)); + if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); f=toproto(L,-1); for (i=0; i<n; i++) { @@ -203,7 +203,7 @@ int main(int argc, char* argv[]) } /* -** $Id: print.c,v 1.67 2011/05/06 13:37:15 lhf Exp $ +** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $ ** print bytecodes ** See Copyright Notice in lua.h */ @@ -218,7 +218,6 @@ int main(int argc, char* argv[]) #include "lobject.h" #include "lopcodes.h" -#define Sizeof(x) ((int)sizeof(x)) #define VOID(p) ((const void*)(p)) static void PrintString(const TString* ts) diff --git a/src/luaconf.h.in b/src/luaconf.h.in index e4916f0..2bae837 100644 --- a/src/luaconf.h.in +++ b/src/luaconf.h.in @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.161 2011/07/08 20:07:11 roberto Exp $ +** $Id: luaconf.h,v 1.170 2011/12/06 16:58:36 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -28,7 +28,6 @@ #cmakedefine LUA_WIN #if defined(LUA_WIN) -#undef LUA_ANSI #define LUA_DL_DLL #define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ #endif @@ -44,6 +43,7 @@ #cmakedefine LUA_USE_POPEN #cmakedefine LUA_USE_ULONGJMP + /* @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for @* Lua libraries. @@ -52,8 +52,6 @@ ** CHANGE them if your machine has a non-conventional directory ** hierarchy or if you want to install your libraries in ** non-conventional directories. -** Any exclamation mark ('!') in the path is replaced by the -** path of the directory of the executable file of the current process. */ #cmakedefine LUA_MODULE_SUFFIX "@LUA_MODULE_SUFFIX@" #cmakedefine LUA_DIR "@LUA_DIR@" @@ -121,13 +119,8 @@ ** give a warning about it. To avoid these warnings, change to the ** default definition. */ -#if defined(luaall_c) /* { */ -#define LUAI_FUNC static -#define LUAI_DDEC static -#define LUAI_DDEF static - -#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ #define LUAI_FUNC __attribute__((visibility("hidden"))) extern #define LUAI_DDEC LUAI_FUNC #define LUAI_DDEF /* empty */ @@ -158,10 +151,14 @@ /* @@ luai_writestring/luai_writeline define how 'print' prints its results. +** They are only used in libraries and the stand-alone program. (The #if +** avoids including 'stdio.h' everywhere.) */ +#if defined(LUA_LIB) || defined(lua_c) #include <stdio.h> #define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) #define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) +#endif /* @@ luai_writestringerror defines how to print error messages. @@ -367,7 +364,7 @@ */ /* the following operations need the math library */ -#if defined(lobject_c) || defined(lvm_c) || defined(luaall_c) +#if defined(lobject_c) || defined(lvm_c) #include <math.h> #define luai_nummod(L,a,b) ((a) - floor((a)/(b))*(b)) #define luai_numpow(L,a,b) (pow(a,b)) @@ -408,7 +405,7 @@ /* On a Microsoft compiler on a Pentium, use assembler to avoid clashes with a DirectX idiosyncrasy */ -#if defined(_MSC_VER) && defined(M_IX86) /* { */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ #define MS_ASMTRICK @@ -441,12 +438,13 @@ /* -@@ LUA_NANTRICKLE/LUA_NANTRICKBE controls the use of a trick to pack all -** types into a single double value, using NaN values to represent -** non-number values. The trick only works on 32-bit machines (ints and -** pointers are 32-bit values) with numbers represented as IEEE 754-2008 -** doubles with conventional endianess (12345678 or 87654321), in CPUs -** that do not produce signaling NaN values (all NaNs are quiet). +@@ LUA_NANTRICK_LE/LUA_NANTRICK_BE controls the use of a trick to +** pack all types into a single double value, using NaN values to +** represent non-number values. The trick only works on 32-bit machines +** (ints and pointers are 32-bit values) with numbers represented as +** IEEE 754-2008 doubles with conventional endianess (12345678 or +** 87654321), in CPUs that do not produce signaling NaN values (all NaNs +** are quiet). */ #if defined(LUA_CORE) && \ defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ @@ -455,7 +453,7 @@ #if defined(__i386__) || defined(__i386) || defined(__X86__) || \ defined(_M_IX86) -#define LUA_NANTRICKLE +#define LUA_NANTRICK_LE #endif diff --git a/src/luaconf.h.orig b/src/luaconf.h.orig deleted file mode 100755 index 1135e50..0000000 --- a/src/luaconf.h.orig +++ /dev/null @@ -1,528 +0,0 @@ -/* -** $Id: luaconf.h,v 1.161 2011/07/08 20:07:11 roberto Exp $ -** Configuration file for Lua -** See Copyright Notice in lua.h -*/ - - -#ifndef lconfig_h -#define lconfig_h - -#include <limits.h> -#include <stddef.h> - - -/* -** ================================================================== -** Search for "@@" to find all configurable definitions. -** =================================================================== -*/ - - -/* -@@ 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(LUA_ANSI) && defined(__STRICT_ANSI__) -#define LUA_ANSI -#endif - - -#if !defined(LUA_ANSI) && defined(_WIN32) -#define LUA_WIN -#endif - -#if defined(LUA_WIN) -#define LUA_DL_DLL -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#endif - - - -#if defined(LUA_USE_LINUX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#define LUA_USE_READLINE /* needs some extra libraries */ -#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */ -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#define LUA_USE_LONGLONG /* assume support for long long */ -#endif - -#if defined(LUA_USE_MACOSX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* does not need -ldl */ -#define LUA_USE_READLINE /* needs an extra library: -lreadline */ -#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */ -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#define LUA_USE_LONGLONG /* assume support for long long */ -#endif - - - -/* -@@ LUA_USE_POSIX includes all functionality listed as X/Open System -@* Interfaces Extension (XSI). -** CHANGE it (define it) if your system is XSI compatible. -*/ -#if defined(LUA_USE_POSIX) -#define LUA_USE_MKSTEMP -#define LUA_USE_ISATTY -#define LUA_USE_POPEN -#define LUA_USE_ULONGJMP -#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 -@* C libraries. -** CHANGE them if your machine has a non-conventional directory -** hierarchy or if you want to install your libraries in -** non-conventional directories. -*/ -#if defined(_WIN32) /* { */ -/* -** 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_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" - -#else /* }{ */ - -#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR -#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" -#endif /* } */ - - -/* -@@ LUA_DIRSEP is the directory separator (for submodules). -** CHANGE it if your machine does not use "/" as the directory separator -** and is not Windows. (On Windows Lua automatically uses "\".) -*/ -#if defined(_WIN32) -#define LUA_DIRSEP "\\" -#else -#define LUA_DIRSEP "/" -#endif - - -/* -@@ LUA_ENV is the name of the variable that holds the current -@@ environment, used to access global names. -** CHANGE it if you do not like this name. -*/ -#define LUA_ENV "_ENV" - - -/* -@@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all auxiliary library functions. -@@ LUAMOD_API is a mark for all standard library opening functions. -** CHANGE them if you need to define those functions in some special way. -** For instance, if you want to create one Windows DLL with the core and -** the libraries, you may want to use the following definition (define -** LUA_BUILD_AS_DLL to get it). -*/ -#if defined(LUA_BUILD_AS_DLL) /* { */ - -#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ -#define LUA_API __declspec(dllexport) -#else /* }{ */ -#define LUA_API __declspec(dllimport) -#endif /* } */ - -#else /* }{ */ - -#define LUA_API extern - -#endif /* } */ - - -/* more often than not the libs go together with the core */ -#define LUALIB_API LUA_API -#define LUAMOD_API LUALIB_API - - -/* -@@ LUAI_FUNC is a mark for all extern functions that are not to be -@* exported to outside modules. -@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables -@* that are not to be exported to outside modules (LUAI_DDEF for -@* definitions and LUAI_DDEC for declarations). -** 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. Not all elf targets support -** this attribute. Unfortunately, gcc does not offer a way to check -** whether the target offers that support, and those without support -** give a warning about it. To avoid these warnings, change to the -** default definition. -*/ -#if defined(luaall_c) /* { */ -#define LUAI_FUNC static -#define LUAI_DDEC static -#define LUAI_DDEF static - -#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DDEC LUAI_FUNC -#define LUAI_DDEF /* empty */ - -#else /* }{ */ -#define LUAI_FUNC extern -#define LUAI_DDEC extern -#define LUAI_DDEF /* empty */ -#endif /* } */ - - - -/* -@@ LUA_QL describes how error messages quote program elements. -** CHANGE it if you want a different appearance. -*/ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - - -/* -@@ LUA_IDSIZE gives the maximum size for the description of the source -@* of a function in debug information. -** CHANGE it if you want a different size. -*/ -#define LUA_IDSIZE 60 - - -/* -@@ luai_writestring/luai_writeline define how 'print' prints its results. -*/ -#include <stdio.h> -#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) - -/* -@@ luai_writestringerror defines how to print error messages. -** (A format string with one argument is enough for Lua...) -*/ -#define luai_writestringerror(s,p) \ - (fprintf(stderr, (s), (p)), fflush(stderr)) - - - - - -/* -** {================================================================== -** Compatibility with previous versions -** =================================================================== -*/ - -/* -@@ LUA_COMPAT_ALL controls all compatibility options. -** You can define it to get all options, or change specific options -** to fit your specific needs. -*/ -#if defined(LUA_COMPAT_ALL) /* { */ - -/* -@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. -** You can replace it with 'table.unpack'. -*/ -#define LUA_COMPAT_UNPACK - -/* -@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. -** You can replace it with 'package.searchers'. -*/ -#define LUA_COMPAT_LOADERS - -/* -@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. -** You can call your C function directly (with light C functions). -*/ -#define lua_cpcall(L,f,u) \ - (lua_pushcfunction(L, (f)), \ - lua_pushlightuserdata(L,(u)), \ - lua_pcall(L,1,0,0)) - - -/* -@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. -** You can rewrite 'log10(x)' as 'log(x, 10)'. -*/ -#define LUA_COMPAT_LOG10 - -/* -@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base -** library. You can rewrite 'loadstring(s)' as 'load(s)'. -*/ -#define LUA_COMPAT_LOADSTRING - -/* -@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. -*/ -#define LUA_COMPAT_MAXN - -/* -@@ The following macros supply trivial compatibility for some -** changes in the API. The macros themselves document how to -** change your code to avoid using them. -*/ -#define lua_strlen(L,i) lua_rawlen(L, (i)) - -#define lua_objlen(L,i) lua_rawlen(L, (i)) - -#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) -#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) - -/* -@@ LUA_COMPAT_MODULE controls compatibility with previous -** module functions 'module' (Lua) and 'luaL_register' (C). -*/ -#define LUA_COMPAT_MODULE - -#endif /* } */ - -/* }================================================================== */ - - - -/* -@@ LUAI_BITSINT defines the number of bits in an int. -** CHANGE here if Lua cannot automatically detect the number of bits of -** your machine. Probably you do not need to change this. -*/ -/* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 /* { */ -#define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L /* }{ */ -/* int has at least 32 bits */ -#define LUAI_BITSINT 32 -#else /* }{ */ -#error "you must define LUA_BITSINT with number of bits in an integer" -#endif /* } */ - - -/* -@@ LUA_INT32 is an signed integer with exactly 32 bits. -@@ LUAI_UMEM is an unsigned integer big enough to count the total -@* memory used by Lua. -@@ LUAI_MEM is a signed integer big enough to count the total memory -@* used by Lua. -** CHANGE here if for some weird reason the default definitions are not -** good enough for your machine. Probably you do not need to change -** this. -*/ -#if LUAI_BITSINT >= 32 /* { */ -#define LUA_INT32 int -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t -#else /* }{ */ -/* 16-bit ints */ -#define LUA_INT32 long -#define LUAI_UMEM unsigned long -#define LUAI_MEM long -#endif /* } */ - - -/* -@@ LUAI_MAXSTACK limits the size of the Lua stack. -** CHANGE it if you need a different limit. This limit is arbitrary; -** its only purpose is to stop Lua to consume unlimited stack -** space (and to reserve some numbers for pseudo-indices). -*/ -#if LUAI_BITSINT >= 32 -#define LUAI_MAXSTACK 1000000 -#else -#define LUAI_MAXSTACK 15000 -#endif - -/* reserve some space for error handling */ -#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) - - - - -/* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -** CHANGE it if it uses too much C-stack space. -*/ -#define LUAL_BUFFERSIZE BUFSIZ - - - - -/* -** {================================================================== -@@ LUA_NUMBER is the type of numbers in Lua. -** CHANGE the following definitions only if you want to build Lua -** with a number type different from double. You may also need to -** change lua_number2int & lua_number2integer. -** =================================================================== -*/ - -#define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double - -/* -@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -@* over a number. -*/ -#define LUAI_UACNUMBER double - - -/* -@@ LUA_NUMBER_SCAN is the format for reading numbers. -@@ LUA_NUMBER_FMT is the format for writing numbers. -@@ lua_number2str converts a number to a string. -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -*/ -#define LUA_NUMBER_SCAN "%lf" -#define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ - - -/* -@@ lua_str2number converts a decimal numeric string to a number. -@@ lua_strx2number converts an hexadecimal numeric string to a number. -** In C99, 'strtod' do both conversions. C89, however, has no function -** to convert floating hexadecimal strings to numbers. For these -** systems, you can leave 'lua_strx2number' undefined and Lua will -** provide its own implementation. -*/ -#define lua_str2number(s,p) strtod((s), (p)) - -#if defined(LUA_USE_STRTODHEX) -#define lua_strx2number(s,p) strtod((s), (p)) -#endif - - -/* -@@ The luai_num* macros define the primitive operations over numbers. -*/ - -/* the following operations need the math library */ -#if defined(lobject_c) || defined(lvm_c) || defined(luaall_c) -#include <math.h> -#define luai_nummod(L,a,b) ((a) - floor((a)/(b))*(b)) -#define luai_numpow(L,a,b) (pow(a,b)) -#endif - -/* these are quite standard operations */ -#if defined(LUA_CORE) -#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_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(L,a,b) ((a)<(b)) -#define luai_numle(L,a,b) ((a)<=(b)) -#define luai_numisnan(L,a) (!luai_numeq((a), (a))) -#endif - - - -/* -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -** machines, ptrdiff_t gives a good choice between int or long.) -*/ -#define LUA_INTEGER ptrdiff_t - -/* -@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. -** It must have at least 32 bits. -*/ -#define LUA_UNSIGNED unsigned LUA_INT32 - - -#if defined(LUA_CORE) /* { */ - -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ - -/* On a Microsoft compiler on a Pentium, use assembler to avoid clashes - with a DirectX idiosyncrasy */ -#if defined(_MSC_VER) && defined(M_IX86) /* { */ - -#define MS_ASMTRICK - -#else /* }{ */ -/* the next definition uses a trick that should work on any machine - using IEEE754 with a 32-bit integer type */ - -#define LUA_IEEE754TRICK - -/* -@@ LUA_IEEEENDIAN is the endianness of doubles in your machine -** (0 for little endian, 1 for big endian); if not defined, Lua will -** check it dynamically. -*/ -/* check for known architectures */ -#if defined(__i386__) || defined(__i386) || defined(__X86__) || \ - defined (__x86_64) -#define LUA_IEEEENDIAN 0 -#elif defined(__POWERPC__) || defined(__ppc__) -#define LUA_IEEEENDIAN 1 -#endif - -#endif /* } */ - -#endif /* } */ - -#endif /* } */ - -/* }================================================================== */ - - -/* -@@ LUA_NANTRICKLE/LUA_NANTRICKBE controls the use of a trick to pack all -** types into a single double value, using NaN values to represent -** non-number values. The trick only works on 32-bit machines (ints and -** pointers are 32-bit values) with numbers represented as IEEE 754-2008 -** doubles with conventional endianess (12345678 or 87654321), in CPUs -** that do not produce signaling NaN values (all NaNs are quiet). -*/ -#if defined(LUA_CORE) && \ - defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ - -/* little-endian architectures that satisfy those conditions */ -#if defined(__i386__) || defined(__i386) || defined(__X86__) || \ - defined(_M_IX86) - -#define LUA_NANTRICKLE - -#endif - -#endif /* } */ - - - - -/* =================================================================== */ - -/* -** Local configuration. You can use this space to add your redefinitions -** without modifying the main part of the file. -*/ - - - -#endif - diff --git a/src/lualib.h b/src/lualib.h index 8132da6..9fd126b 100755..100644 --- a/src/lualib.h +++ b/src/lualib.h @@ -1,5 +1,5 @@ /* -** $Id: lualib.h,v 1.42 2011/05/25 14:12:28 roberto Exp $ +** $Id: lualib.h,v 1.43 2011/12/08 12:11:37 roberto Exp $ ** Lua standard libraries ** See Copyright Notice in lua.h */ @@ -11,9 +11,6 @@ #include "lua.h" -/* Key to file-handle type */ -#define LUA_FILEHANDLE "FILE*" - LUAMOD_API int (luaopen_base) (lua_State *L); diff --git a/src/lundump.c b/src/lundump.c index d7b0ab3..80c7aa3 100755..100644 --- a/src/lundump.c +++ b/src/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 1.70 2011/06/21 12:29:00 lhf Exp $ +** $Id: lundump.c,v 1.71 2011/12/07 10:39:12 lhf Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -136,8 +136,8 @@ static void LoadUpvalues(LoadState* S, Proto* f) for (i=0; i<n; i++) f->upvalues[i].name=NULL; for (i=0; i<n; i++) { - f->upvalues[i].instack=LoadChar(S); - f->upvalues[i].idx=LoadChar(S); + f->upvalues[i].instack=LoadByte(S); + f->upvalues[i].idx=LoadByte(S); } } diff --git a/src/lundump.h b/src/lundump.h index b63993f..b63993f 100755..100644 --- a/src/lundump.h +++ b/src/lundump.h diff --git a/src/lvm.c b/src/lvm.c index e4f90af..694971b 100755..100644 --- a/src/lvm.c +++ b/src/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.141 2011/06/09 18:24:22 roberto Exp $ +** $Id: lvm.c,v 2.147 2011/12/07 14:43:55 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -127,29 +127,38 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { int loop; - TValue temp; for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ Table *h = hvalue(t); - TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ - if (!ttisnil(oldval) || /* result is not nil? */ - (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ - setobj2t(L, oldval, val); + TValue *oldval = cast(TValue *, luaH_get(h, key)); + /* if previous value is not nil, there must be a previous entry + in the table; moreover, a metamethod has no relevance */ + if (!ttisnil(oldval) || + /* previous value is nil; must check the metamethod */ + ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && + /* no metamethod; is there a previous entry in the table? */ + (oldval != luaO_nilobject || + /* no previous entry; must create one. (The next test is + always true; we only need the assignment.) */ + (oldval = luaH_newkey(L, h, key), 1)))) { + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, oldval, val); /* assign new value to that entry */ + invalidateTMcache(h); luaC_barrierback(L, obj2gco(h), val); return; } - /* else will try the tag method */ + /* else will try the metamethod */ } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); + else /* not a table; check metamethod */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + /* there is a metamethod */ if (ttisfunction(tm)) { callTM(L, tm, t, key, val, 0); return; } - /* else repeat with 'tm' */ - setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ - t = &temp; + t = tm; /* else repeat with 'tm' */ } luaG_runerror(L, "loop in settable"); } @@ -217,9 +226,9 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { return luai_numlt(L, nvalue(l), nvalue(r)); else if (ttisstring(l) && ttisstring(r)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; - else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) - return res; - return luaG_ordererror(L, l, r); + else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) + luaG_ordererror(L, l, r); + return res; } @@ -229,11 +238,11 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { return luai_numle(L, nvalue(l), nvalue(r)); else if (ttisstring(l) && ttisstring(r)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; - else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ return res; - else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ - return !res; - return luaG_ordererror(L, l, r); + else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ + luaG_ordererror(L, l, r); + return !res; } @@ -506,6 +515,7 @@ void luaV_finishOp (lua_State *L) { #define vmdispatch(o) switch(o) #define vmcase(l,b) case l: {b} break; +#define vmcasenb(l,b) case l: {b} /* nb = no break */ void luaV_execute (lua_State *L) { CallInfo *ci = L->ci; @@ -525,7 +535,7 @@ void luaV_execute (lua_State *L) { (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { Protect(traceexec(L)); } - /* warning!! several calls may realloc the stack and invalidate `ra' */ + /* WARNING: several calls may realloc the stack and invalidate `ra' */ ra = RA(i); lua_assert(base == ci->u.l.base); lua_assert(base <= L->top && L->top < L->stack + L->stacksize); @@ -652,7 +662,7 @@ void luaV_execute (lua_State *L) { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( - if (equalobj(L, rb, rc) != GETARG_A(i)) + if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) ci->u.l.savedpc++; else donextjump(ci); @@ -732,7 +742,7 @@ void luaV_execute (lua_State *L) { goto newframe; /* restart luaV_execute over new Lua function */ } ) - vmcase(OP_RETURN, + vmcasenb(OP_RETURN, int b = GETARG_B(i); if (b != 0) L->top = ra+b-1; if (cl->p->sizep > 0) luaF_close(L, base); @@ -771,7 +781,7 @@ void luaV_execute (lua_State *L) { setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); ci->u.l.savedpc += GETARG_sBx(i); ) - vmcase(OP_TFORCALL, + vmcasenb(OP_TFORCALL, StkId cb = ra + 3; /* call base */ setobjs2s(L, cb+2, ra+2); setobjs2s(L, cb+1, ra+1); @@ -808,7 +818,7 @@ void luaV_execute (lua_State *L) { luaH_resizearray(L, h, last); /* pre-allocate it at once */ for (; n > 0; n--) { TValue *val = ra+n; - setobj2t(L, luaH_setint(L, h, last--), val); + luaH_setint(L, h, last--, val); luaC_barrierback(L, obj2gco(h), val); } L->top = ci->top; /* correct top (in case of previous open call) */ diff --git a/src/lvm.h b/src/lvm.h index ec35822..ec35822 100755..100644 --- a/src/lvm.h +++ b/src/lvm.h diff --git a/src/lzio.c b/src/lzio.c index 7d2677b..354f94e 100755..100644 --- a/src/lzio.c +++ b/src/lzio.c @@ -1,5 +1,5 @@ /* -** $Id: lzio.c,v 1.33 2011/02/23 13:13:10 roberto Exp $ +** $Id: lzio.c,v 1.34 2011/07/15 12:35:32 roberto Exp $ ** a generic input stream interface ** See Copyright Notice in lua.h */ @@ -29,7 +29,7 @@ int luaZ_fill (ZIO *z) { return EOZ; z->n = size - 1; /* discount char being returned */ z->p = buff; - return char2int(*(z->p++)); + return cast_uchar(*(z->p++)); } diff --git a/src/lzio.h b/src/lzio.h index 4174986..0868230 100755..100644 --- a/src/lzio.h +++ b/src/lzio.h @@ -1,5 +1,5 @@ /* -** $Id: lzio.h,v 1.24 2011/02/23 13:13:10 roberto Exp $ +** $Id: lzio.h,v 1.26 2011/07/15 12:48:03 roberto Exp $ ** Buffered streams ** See Copyright Notice in lua.h */ @@ -17,11 +17,7 @@ typedef struct Zio ZIO; -#define char2int(c) cast(int, cast(unsigned char, (c))) - -#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) - -#define zungetc(z) ((z)->n++, (z)->p--) +#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) typedef struct Mbuffer { |