diff options
author | Lua Team <team@lua.org> | 2005-03-04 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 2005-03-04 12:00:00 +0000 |
commit | e6ddfd3b09c0a3727afc773029c323a3defe50fa (patch) | |
tree | 70e021a2b008f43064eeb04e002a31ba371b5108 | |
parent | e2493a40ee611d5a718fd2a81fe67e24c04c91a0 (diff) | |
download | lua-github-e6ddfd3b09c0a3727afc773029c323a3defe50fa.tar.gz |
Lua 5.1-work55.1-work5
-rw-r--r-- | COPYRIGHT | 2 | ||||
-rw-r--r-- | HISTORY | 19 | ||||
-rw-r--r-- | MANIFEST | 208 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/Makefile | 19 | ||||
-rw-r--r-- | src/lapi.c | 89 | ||||
-rw-r--r-- | src/lauxlib.c | 7 | ||||
-rw-r--r-- | src/lauxlib.h | 89 | ||||
-rw-r--r-- | src/lbaselib.c | 29 | ||||
-rw-r--r-- | src/lcode.c | 4 | ||||
-rw-r--r-- | src/ldblib.c | 51 | ||||
-rw-r--r-- | src/ldo.c | 4 | ||||
-rw-r--r-- | src/lfunc.c | 53 | ||||
-rw-r--r-- | src/lfunc.h | 7 | ||||
-rw-r--r-- | src/lgc.c | 198 | ||||
-rw-r--r-- | src/lgc.h | 23 | ||||
-rw-r--r-- | src/linit.c | 4 | ||||
-rw-r--r-- | src/liolib.c | 34 | ||||
-rw-r--r-- | src/llimits.h | 4 | ||||
-rw-r--r-- | src/lmathlib.c | 4 | ||||
-rw-r--r-- | src/lmem.c | 32 | ||||
-rw-r--r-- | src/loadlib.c | 82 | ||||
-rw-r--r-- | src/lobject.c | 4 | ||||
-rw-r--r-- | src/lobject.h | 19 | ||||
-rw-r--r-- | src/loslib.c | 8 | ||||
-rw-r--r-- | src/lparser.c | 4 | ||||
-rw-r--r-- | src/lstate.c | 43 | ||||
-rw-r--r-- | src/lstate.h | 19 | ||||
-rw-r--r-- | src/lstring.c | 11 | ||||
-rw-r--r-- | src/lstring.h | 6 | ||||
-rw-r--r-- | src/ltable.c | 221 | ||||
-rw-r--r-- | src/ltable.h | 6 | ||||
-rw-r--r-- | src/lua.c | 20 | ||||
-rw-r--r-- | src/lua.h | 156 | ||||
-rw-r--r-- | src/luaconf.h | 79 | ||||
-rw-r--r-- | src/lualib.h | 20 | ||||
-rw-r--r-- | src/lvm.c | 75 |
37 files changed, 938 insertions, 717 deletions
@@ -9,7 +9,7 @@ For details and rationale, see http://www.lua.org/license.html . =============================================================================== -Copyright (C) 2003-2004 Tecgraf, PUC-Rio. +Copyright (C) 1994-2005 Tecgraf, PUC-Rio. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1,5 +1,24 @@ This is Lua 5.1 (work). +* Changes from version 5.0 to 5.1 + ------------------------------- + Language: + + new module system. + + new semantics for control variables of fors. + + new semantics for setn/getn. + + new syntax/semantics for varargs. + + new long strings. + API: + + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer. + + user supplies memory allocator (lua_open becomes lua_newstate). + Implementation: + + incremental garbage collection. + + debug works over other threads. + + better handling of end-of-line in the lexer. + + fully reentrant parser (new Lua function `load') + + better support for 64-bit machines (special thanks to Mike Pall). + + native loadlib support for Mac OS X (thanks to Matthew Cox). + * Changes from version 4.0 to 5.0 ------------------------------- Language: @@ -1,105 +1,105 @@ -MANIFEST contents of Lua 5.1 (work4) distribution on Thu Dec 30 12:00:49 BRST 2004 -lua-5.1-work4 -lua-5.1-work4/COPYRIGHT -lua-5.1-work4/HISTORY -lua-5.1-work4/INSTALL -lua-5.1-work4/MANIFEST -lua-5.1-work4/Makefile -lua-5.1-work4/README -lua-5.1-work4/doc -lua-5.1-work4/doc/contents.html -lua-5.1-work4/doc/logo.gif -lua-5.1-work4/doc/lua.1 -lua-5.1-work4/doc/lua.html -lua-5.1-work4/doc/luac.1 -lua-5.1-work4/doc/luac.html -lua-5.1-work4/doc/readme.html -lua-5.1-work4/etc -lua-5.1-work4/etc/Makefile -lua-5.1-work4/etc/README -lua-5.1-work4/etc/all.c -lua-5.1-work4/etc/lua.hpp -lua-5.1-work4/etc/lua.ico -lua-5.1-work4/etc/min.c -lua-5.1-work4/etc/noparser.c -lua-5.1-work4/etc/saconfig.c -lua-5.1-work4/src -lua-5.1-work4/src/Makefile -lua-5.1-work4/src/lapi.c -lua-5.1-work4/src/lapi.h -lua-5.1-work4/src/lauxlib.c -lua-5.1-work4/src/lauxlib.h -lua-5.1-work4/src/lbaselib.c -lua-5.1-work4/src/lcode.c -lua-5.1-work4/src/lcode.h -lua-5.1-work4/src/ldblib.c -lua-5.1-work4/src/ldebug.c -lua-5.1-work4/src/ldebug.h -lua-5.1-work4/src/ldo.c -lua-5.1-work4/src/ldo.h -lua-5.1-work4/src/ldump.c -lua-5.1-work4/src/lfunc.c -lua-5.1-work4/src/lfunc.h -lua-5.1-work4/src/lgc.c -lua-5.1-work4/src/lgc.h -lua-5.1-work4/src/linit.c -lua-5.1-work4/src/liolib.c -lua-5.1-work4/src/llex.c -lua-5.1-work4/src/llex.h -lua-5.1-work4/src/llimits.h -lua-5.1-work4/src/lmathlib.c -lua-5.1-work4/src/lmem.c -lua-5.1-work4/src/lmem.h -lua-5.1-work4/src/loadlib.c -lua-5.1-work4/src/lobject.c -lua-5.1-work4/src/lobject.h -lua-5.1-work4/src/lopcodes.c -lua-5.1-work4/src/lopcodes.h -lua-5.1-work4/src/loslib.c -lua-5.1-work4/src/lparser.c -lua-5.1-work4/src/lparser.h -lua-5.1-work4/src/lstate.c -lua-5.1-work4/src/lstate.h -lua-5.1-work4/src/lstring.c -lua-5.1-work4/src/lstring.h -lua-5.1-work4/src/lstrlib.c -lua-5.1-work4/src/ltable.c -lua-5.1-work4/src/ltable.h -lua-5.1-work4/src/ltablib.c -lua-5.1-work4/src/ltm.c -lua-5.1-work4/src/ltm.h -lua-5.1-work4/src/lua.c -lua-5.1-work4/src/lua.h -lua-5.1-work4/src/luac.c -lua-5.1-work4/src/luaconf.h -lua-5.1-work4/src/lualib.h -lua-5.1-work4/src/lundump.c -lua-5.1-work4/src/lundump.h -lua-5.1-work4/src/lvm.c -lua-5.1-work4/src/lvm.h -lua-5.1-work4/src/lzio.c -lua-5.1-work4/src/lzio.h -lua-5.1-work4/src/print.c -lua-5.1-work4/test -lua-5.1-work4/test/README -lua-5.1-work4/test/bisect.lua -lua-5.1-work4/test/cf.lua -lua-5.1-work4/test/echo.lua -lua-5.1-work4/test/env.lua -lua-5.1-work4/test/factorial.lua -lua-5.1-work4/test/fib.lua -lua-5.1-work4/test/fibfor.lua -lua-5.1-work4/test/globals.lua -lua-5.1-work4/test/hello.lua -lua-5.1-work4/test/life.lua -lua-5.1-work4/test/luac.lua -lua-5.1-work4/test/printf.lua -lua-5.1-work4/test/readonly.lua -lua-5.1-work4/test/sieve.lua -lua-5.1-work4/test/sort.lua -lua-5.1-work4/test/table.lua -lua-5.1-work4/test/trace-calls.lua -lua-5.1-work4/test/trace-globals.lua -lua-5.1-work4/test/undefined.lua -lua-5.1-work4/test/xd.lua +MANIFEST contents of Lua 5.1 (work5) distribution on Fri Mar 4 13:32:55 BRST 2005 +lua-5.1-work5 +lua-5.1-work5/COPYRIGHT +lua-5.1-work5/HISTORY +lua-5.1-work5/INSTALL +lua-5.1-work5/MANIFEST +lua-5.1-work5/Makefile +lua-5.1-work5/README +lua-5.1-work5/doc +lua-5.1-work5/doc/contents.html +lua-5.1-work5/doc/logo.gif +lua-5.1-work5/doc/lua.1 +lua-5.1-work5/doc/lua.html +lua-5.1-work5/doc/luac.1 +lua-5.1-work5/doc/luac.html +lua-5.1-work5/doc/readme.html +lua-5.1-work5/etc +lua-5.1-work5/etc/Makefile +lua-5.1-work5/etc/README +lua-5.1-work5/etc/all.c +lua-5.1-work5/etc/lua.hpp +lua-5.1-work5/etc/lua.ico +lua-5.1-work5/etc/min.c +lua-5.1-work5/etc/noparser.c +lua-5.1-work5/etc/saconfig.c +lua-5.1-work5/src +lua-5.1-work5/src/Makefile +lua-5.1-work5/src/lapi.c +lua-5.1-work5/src/lapi.h +lua-5.1-work5/src/lauxlib.c +lua-5.1-work5/src/lauxlib.h +lua-5.1-work5/src/lbaselib.c +lua-5.1-work5/src/lcode.c +lua-5.1-work5/src/lcode.h +lua-5.1-work5/src/ldblib.c +lua-5.1-work5/src/ldebug.c +lua-5.1-work5/src/ldebug.h +lua-5.1-work5/src/ldo.c +lua-5.1-work5/src/ldo.h +lua-5.1-work5/src/ldump.c +lua-5.1-work5/src/lfunc.c +lua-5.1-work5/src/lfunc.h +lua-5.1-work5/src/lgc.c +lua-5.1-work5/src/lgc.h +lua-5.1-work5/src/linit.c +lua-5.1-work5/src/liolib.c +lua-5.1-work5/src/llex.c +lua-5.1-work5/src/llex.h +lua-5.1-work5/src/llimits.h +lua-5.1-work5/src/lmathlib.c +lua-5.1-work5/src/lmem.c +lua-5.1-work5/src/lmem.h +lua-5.1-work5/src/loadlib.c +lua-5.1-work5/src/lobject.c +lua-5.1-work5/src/lobject.h +lua-5.1-work5/src/lopcodes.c +lua-5.1-work5/src/lopcodes.h +lua-5.1-work5/src/loslib.c +lua-5.1-work5/src/lparser.c +lua-5.1-work5/src/lparser.h +lua-5.1-work5/src/lstate.c +lua-5.1-work5/src/lstate.h +lua-5.1-work5/src/lstring.c +lua-5.1-work5/src/lstring.h +lua-5.1-work5/src/lstrlib.c +lua-5.1-work5/src/ltable.c +lua-5.1-work5/src/ltable.h +lua-5.1-work5/src/ltablib.c +lua-5.1-work5/src/ltm.c +lua-5.1-work5/src/ltm.h +lua-5.1-work5/src/lua.c +lua-5.1-work5/src/lua.h +lua-5.1-work5/src/luac.c +lua-5.1-work5/src/luaconf.h +lua-5.1-work5/src/lualib.h +lua-5.1-work5/src/lundump.c +lua-5.1-work5/src/lundump.h +lua-5.1-work5/src/lvm.c +lua-5.1-work5/src/lvm.h +lua-5.1-work5/src/lzio.c +lua-5.1-work5/src/lzio.h +lua-5.1-work5/src/print.c +lua-5.1-work5/test +lua-5.1-work5/test/README +lua-5.1-work5/test/bisect.lua +lua-5.1-work5/test/cf.lua +lua-5.1-work5/test/echo.lua +lua-5.1-work5/test/env.lua +lua-5.1-work5/test/factorial.lua +lua-5.1-work5/test/fib.lua +lua-5.1-work5/test/fibfor.lua +lua-5.1-work5/test/globals.lua +lua-5.1-work5/test/hello.lua +lua-5.1-work5/test/life.lua +lua-5.1-work5/test/luac.lua +lua-5.1-work5/test/printf.lua +lua-5.1-work5/test/readonly.lua +lua-5.1-work5/test/sieve.lua +lua-5.1-work5/test/sort.lua +lua-5.1-work5/test/table.lua +lua-5.1-work5/test/trace-calls.lua +lua-5.1-work5/test/trace-globals.lua +lua-5.1-work5/test/undefined.lua +lua-5.1-work5/test/xd.lua END OF MANIFEST @@ -44,7 +44,7 @@ install: all cd doc; $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) local: - $(MAKE) install INSTALL_TOP=.. INSTALL_EXEC="cp -up" INSTALL_DATA="cp -up" + $(MAKE) install INSTALL_TOP=.. INSTALL_EXEC="cp -p" INSTALL_DATA="cp -p" # echo config parameters echo: diff --git a/src/Makefile b/src/Makefile index cf7ff181..9ec6d349 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,13 +6,15 @@ CC= gcc CFLAGS= -O2 -Wall $(MYCFLAGS) -MYCFLAGS= -MYLDFLAGS= -Wl,-E # enable dynamic loading in Linux -MYLIBS= -lm -ldl # enable dynamic loading in Linux AR= ar rcu RANLIB= ranlib RM= rm -f +MYCFLAGS= +MYLDFLAGS= +MYLIBS= -lm +DL= -ldl -Wl,-E # enable dynamic loading in Linux + # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= CORE_T= liblua.a @@ -49,10 +51,10 @@ $(LIB_T): $(LIB_O) $(RANLIB) $@ $(LUA_T): $(LUA_O) $(CORE_T) $(LIB_T) - $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) -L. -llua -llualib $(MYLIBS) + $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) -L. -llua -llualib $(MYLIBS) $(DL) $(LUAC_T): $(LUAC_O) $(CORE_T) - $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) -L. -llua + $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) -L. -llua $(MYLIBS) clean: $(RM) $(ALL_T) $(ALL_O) @@ -63,12 +65,13 @@ depend: echo: @echo "CC = $(CC)" @echo "CFLAGS = $(CFLAGS)" - @echo "MYCFLAGS = $(MYCFLAGS)" - @echo "MYLDFLAGS = $(MYLDFLAGS)" - @echo "MYLIBS = $(MYLIBS)" @echo "AR = $(AR)" @echo "RANLIB = $(RANLIB)" @echo "RM = $(RM)" + @echo "MYCFLAGS = $(MYCFLAGS)" + @echo "MYLDFLAGS = $(MYLDFLAGS)" + @echo "MYLIBS = $(MYLIBS)" + @echo "DL = $(DL)" # DO NOT DELETE @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.23 2004/12/13 12:15:11 roberto Exp $ +** $Id: lapi.c,v 2.28 2005/02/23 17:30:22 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -58,6 +58,11 @@ static TValue *index2adr (lua_State *L, int idx) { } else switch (idx) { /* pseudo-indices */ case LUA_REGISTRYINDEX: return registry(L); + case LUA_ENVIRONINDEX: { + Closure *func = curr_func(L); + sethvalue(L, &L->env, func->c.env); + return &L->env; + } case LUA_GLOBALSINDEX: return gt(L); default: { Closure *func = curr_func(L); @@ -70,6 +75,16 @@ static TValue *index2adr (lua_State *L, int idx) { } +static Table *getcurrenv (lua_State *L) { + if (L->ci == L->base_ci) /* no enclosing function? */ + return hvalue(gt(L)); /* use global table as environment */ + else { + Closure *func = curr_func(L); + return func->c.env; + } +} + + void luaA_pushobject (lua_State *L, const TValue *o) { setobj2s(L, L->top, o); incr_top(L); @@ -186,9 +201,17 @@ LUA_API void lua_replace (lua_State *L, int idx) { api_checknelems(L, 1); o = index2adr(L, idx); api_checkvalidindex(L, o); - setobj(L, o, L->top - 1); - if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ - luaC_barrier(L, curr_func(L), L->top - 1); + if (idx == LUA_ENVIRONINDEX) { + Closure *func = curr_func(L); + api_check(L, ttistable(L->top - 1)); + func->c.env = hvalue(L->top - 1); + luaC_barrier(L, func, L->top - 1); + } + else { + setobj(L, o, L->top - 1); + if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ + luaC_barrier(L, curr_func(L), L->top - 1); + } L->top--; lua_unlock(L); } @@ -452,7 +475,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); luaC_checkGC(L); api_checknelems(L, n); - cl = luaF_newCclosure(L, n); + cl = luaF_newCclosure(L, n, getcurrenv(L)); cl->c.f = fn; L->top -= n; while (n--) @@ -542,7 +565,7 @@ LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { lua_lock(L); luaC_checkGC(L); - sethvalue(L, L->top, luaH_new(L, narray, luaO_log2(nrec) + 1)); + sethvalue(L, L->top, luaH_new(L, narray, nrec)); api_incr_top(L); lua_unlock(L); } @@ -579,7 +602,17 @@ LUA_API void lua_getfenv (lua_State *L, int idx) { lua_lock(L); o = index2adr(L, idx); api_checkvalidindex(L, o); - setobj2s(L, L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L)); + switch (ttype(o)) { + case LUA_TFUNCTION: + sethvalue(L, L->top, clvalue(o)->c.env); + break; + case LUA_TUSERDATA: + sethvalue(L, L->top, uvalue(o)->env); + break; + default: + setnilvalue(L->top); + break; + } api_incr_top(L); lua_unlock(L); } @@ -682,17 +715,24 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { LUA_API int lua_setfenv (lua_State *L, int idx) { StkId o; - int res = 0; + int res = 1; lua_lock(L); api_checknelems(L, 1); o = index2adr(L, idx); api_checkvalidindex(L, o); api_check(L, ttistable(L->top - 1)); - if (isLfunction(o)) { - res = 1; - clvalue(o)->l.g = *(L->top - 1); - luaC_objbarrier(L, clvalue(o), hvalue(L->top - 1)); + switch (ttype(o)) { + case LUA_TFUNCTION: + clvalue(o)->c.env = hvalue(L->top - 1); + break; + case LUA_TUSERDATA: + uvalue(o)->env = hvalue(L->top - 1); + break; + default: + res = 0; + break; } + luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); L->top--; lua_unlock(L); return res; @@ -776,7 +816,7 @@ struct CCallS { /* data to `f_Ccall' */ static void f_Ccall (lua_State *L, void *ud) { struct CCallS *c = cast(struct CCallS *, ud); Closure *cl; - cl = luaF_newCclosure(L, 0); + cl = luaF_newCclosure(L, 0, getcurrenv(L)); cl->c.f = c->func; setclvalue(L, L->top, cl); /* push function */ incr_top(L); @@ -826,7 +866,7 @@ LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) { } -LUA_API int lua_threadstatus (lua_State *L) { +LUA_API int lua_status (lua_State *L) { return L->status; } @@ -872,9 +912,9 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { g->gcpace = data; break; } - case LUA_GCSETINCMODE: { - res = g->incgc; - g->incgc = data; + case LUA_GCSETSTEPMUL: { + res = g->gcstepmul; + g->gcstepmul = data; break; } default: res = -1; /* invalid option */ @@ -890,11 +930,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { */ -LUA_API const char *lua_version (void) { - return LUA_VERSION; -} - - LUA_API int lua_error (lua_State *L) { lua_lock(L); api_checknelems(L, 1); @@ -940,7 +975,7 @@ LUA_API void lua_concat (lua_State *L, int n) { LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { *ud = G(L)->ud; - return G(L)->realloc; + return G(L)->frealloc; } @@ -948,7 +983,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { Udata *u; lua_lock(L); luaC_checkGC(L); - u = luaS_newudata(L, size); + u = luaS_newudata(L, size, getcurrenv(L)); setuvalue(L, L->top, u); api_incr_top(L); lua_unlock(L); @@ -958,7 +993,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { -static const char *aux_upvalue (lua_State *L, StkId fi, int n, TValue **val) { +static const char *aux_upvalue (StkId fi, int n, TValue **val) { Closure *f; if (!ttisfunction(fi)) return NULL; f = clvalue(fi); @@ -980,7 +1015,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val; lua_lock(L); - name = aux_upvalue(L, index2adr(L, funcindex), n, &val); + name = aux_upvalue(index2adr(L, funcindex), n, &val); if (name) { setobj2s(L, L->top, val); api_incr_top(L); @@ -997,7 +1032,7 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { lua_lock(L); fi = index2adr(L, funcindex); api_checknelems(L, 1); - name = aux_upvalue(L, fi, n, &val); + name = aux_upvalue(fi, n, &val); if (name) { L->top--; setobj(L, val, L->top); diff --git a/src/lauxlib.c b/src/lauxlib.c index 5bbe918b..ac53db39 100644 --- a/src/lauxlib.c +++ b/src/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.127 2004/12/20 13:47:29 roberto Exp $ +** $Id: lauxlib.c,v 1.129 2005/02/23 17:30:22 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -350,8 +350,8 @@ LUALIB_API int luaL_getn (lua_State *L, int t) { static const char *pushnexttemplate (lua_State *L, const char *path) { const char *l; if (*path == '\0') return NULL; /* no more templates */ - if (*path == LUA_PATH_SEP) path++; /* skip separator */ - l = strchr(path, LUA_PATH_SEP); /* find next separator */ + if (*path == LUA_PATHSEP) path++; /* skip separator */ + l = strchr(path, LUA_PATHSEP); /* find next separator */ if (l == NULL) l = path+strlen(path); lua_pushlstring(L, path, l - path); /* template */ return l; @@ -704,6 +704,7 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { static int panic (lua_State *L) { + (void)L; /* to avoid warnings */ fprintf(stderr, "PANIC: unprotected error during Lua-API call\n"); return 0; } diff --git a/src/lauxlib.h b/src/lauxlib.h index b47663ce..82585cf4 100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.73 2004/10/18 12:51:44 roberto Exp $ +** $Id: lauxlib.h,v 1.74 2005/01/10 17:31:50 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -25,55 +25,58 @@ typedef struct luaL_reg { } luaL_reg; -LUALIB_API void luaL_openlib (lua_State *L, const char *libname, - const luaL_reg *l, int nup); -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e); -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e); -LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname); -LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg); -LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l); -LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg, - const char *def, size_t *l); -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int numArg); -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int nArg, lua_Number def); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_reg *l, int nup); +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int numArg); -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int nArg, - lua_Integer def); +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); -LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg); -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); -LUALIB_API void luaL_checkany (lua_State *L, int narg); +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname); -LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname); -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname); +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_getmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); -LUALIB_API void luaL_where (lua_State *L, int lvl); -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...); +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); -LUALIB_API int luaL_findstring (const char *st, const char *const lst[]); +LUALIB_API int (luaL_findstring) (const char *st, const char *const lst[]); -LUALIB_API const char *luaL_searchpath (lua_State *L, const char *name, - const char *path); +LUALIB_API const char *(luaL_searchpath) (lua_State *L, const char *name, + const char *path); -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_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); -LUALIB_API int luaL_getn (lua_State *L, int t); -LUALIB_API void luaL_setn (lua_State *L, int t, int n); +LUALIB_API int (luaL_getn) (lua_State *L, int t); +LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); -LUALIB_API int luaL_loadfile (lua_State *L, const char *filename); -LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz, - const char *name); +LUALIB_API int (luaL_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 lua_State *(luaL_newstate) (void); -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, - const char *r); -LUALIB_API const char *luaL_getfield (lua_State *L, int idx, const char *fname); -LUALIB_API const char *luaL_setfield (lua_State *L, int idx, const char *fname); +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); +LUALIB_API const char *(luaL_getfield) (lua_State *L, int idx, + const char *fname); +LUALIB_API const char *(luaL_setfield) (lua_State *L, int idx, + const char *fname); @@ -115,12 +118,12 @@ typedef struct luaL_Buffer { #define luaL_addsize(B,n) ((B)->p += (n)) -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B); -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B); -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s); -LUALIB_API void luaL_addvalue (luaL_Buffer *B); -LUALIB_API void luaL_pushresult (luaL_Buffer *B); +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); /* }====================================================== */ diff --git a/src/lbaselib.c b/src/lbaselib.c index 3b034bbc..9e1573cb 100644 --- a/src/lbaselib.c +++ b/src/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.163 2004/12/13 12:15:11 roberto Exp $ +** $Id: lbaselib.c,v 1.169 2005/02/28 17:24:41 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -131,7 +131,10 @@ static void getfunc (lua_State *L) { static int luaB_getfenv (lua_State *L) { getfunc(L); - lua_getfenv(L, -1); + if (lua_iscfunction(L, -1)) /* is a C function? */ + lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the global env. */ + else + lua_getfenv(L, -1); return 1; } @@ -144,8 +147,8 @@ static int luaB_setfenv (lua_State *L) { lua_replace(L, LUA_GLOBALSINDEX); return 0; } - else if (lua_setfenv(L, -2) == 0) - luaL_error(L, "`setfenv' cannot change environment of given function"); + else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) + luaL_error(L, "`setfenv' cannot change environment of given object"); return 1; } @@ -182,11 +185,11 @@ static int luaB_gcinfo (lua_State *L) { static int luaB_collectgarbage (lua_State *L) { static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpace", "setincmode", NULL}; + "count", "step", "setpace", "setstepmul", NULL}; static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPACE, LUA_GCSETINCMODE}; + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPACE, LUA_GCSETSTEPMUL}; int o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts); - int ex = luaL_optint(L, 2, 0); + int ex = luaL_optinteger(L, 2, 0); luaL_argcheck(L, o >= 0, 1, "invalid option"); lua_pushinteger(L, lua_gc(L, optsnum[o], ex)); return 1; @@ -280,6 +283,7 @@ static int luaB_loadfile (lua_State *L) { ** reserved slot inside the stack. */ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)ud; /* to avoid warnings */ luaL_checkstack(L, 2, "too many nested functions"); lua_pushvalue(L, 1); /* get function */ lua_call(L, 0, 1); /* call it */ @@ -469,7 +473,7 @@ static int auxresume (lua_State *L, lua_State *co, int narg) { int status; if (!lua_checkstack(co, narg)) luaL_error(L, "too many arguments to resume"); - if (lua_threadstatus(co) == 0 && lua_gettop(co) == 0) { + if (lua_status(co) == 0 && lua_gettop(co) == 0) { lua_pushliteral(L, "cannot resume dead coroutine"); return -1; /* error flag */ } @@ -549,7 +553,7 @@ static int luaB_costatus (lua_State *L) { luaL_argcheck(L, co, 1, "coroutine expected"); if (L == co) lua_pushliteral(L, "running"); else { - switch (lua_threadstatus(co)) { + switch (lua_status(co)) { case LUA_YIELD: lua_pushliteral(L, "suspended"); break; @@ -572,7 +576,7 @@ static int luaB_costatus (lua_State *L) { } -static int luaB_cocurrent (lua_State *L) { +static int luaB_corunning (lua_State *L) { if (lua_pushthread(L)) return 0; /* main thread is not a coroutine */ else @@ -586,7 +590,7 @@ static const luaL_reg co_funcs[] = { {"resume", luaB_coresume}, {"yield", luaB_yield}, {"status", luaB_costatus}, - {"current", luaB_cocurrent}, + {"running", luaB_corunning}, {NULL, NULL} }; @@ -620,9 +624,6 @@ static void base_open (lua_State *L) { /* create register._LOADED to track loaded modules */ lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED"); - /* create register._PRELOAD to allow pre-loaded modules */ - lua_newtable(L); - lua_setfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); /* set global _G */ lua_pushvalue(L, LUA_GLOBALSINDEX); lua_setglobal(L, "_G"); diff --git a/src/lcode.c b/src/lcode.c index f7f1182d..b40bc5a1 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.8 2004/12/03 20:35:33 roberto Exp $ +** $Id: lcode.c,v 2.9 2005/01/10 18:17:39 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -606,7 +606,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { if (op == OPR_MINUS) { luaK_exp2val(fs, e); if (e->k == VK && ttisnumber(&fs->f->k[e->info])) - e->info = luaK_numberK(fs, -nvalue(&fs->f->k[e->info])); + e->info = luaK_numberK(fs, num_unm(nvalue(&fs->f->k[e->info]))); else { luaK_exp2anyreg(fs, e); freeexp(fs, e); diff --git a/src/ldblib.c b/src/ldblib.c index 36d647aa..7f8bde1f 100644 --- a/src/ldblib.c +++ b/src/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.89 2004/11/17 12:02:41 roberto Exp $ +** $Id: ldblib.c,v 1.93 2005/02/18 12:40:02 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -19,6 +19,40 @@ +static int getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_pushboolean(L, lua_setmetatable(L, 1)); + return 1; +} + + +static int getfenv (lua_State *L) { + lua_getfenv(L, 1); + return 1; +} + + +static int setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + lua_settop(L, 2); + if (lua_setfenv(L, 1) == 0) + luaL_error(L, "`setfenv' cannot change environment of given object"); + return 1; +} + + static void settabss (lua_State *L, const char *i, const char *v) { lua_pushstring(L, v); lua_setfield(L, -2, i); @@ -275,12 +309,17 @@ static int debug (lua_State *L) { #define LEVELS2 10 /* size of the second part of the stack */ static int errorfb (lua_State *L) { - int level = 0; + int level; int firstpart = 1; /* still before eventual `...' */ int arg; lua_State *L1 = getthread(L, &arg); lua_Debug ar; - if (L == L1) level++; /* skip level 0 (it's this function) */ + if (lua_isnumber(L, arg+2)) { + level = lua_tointeger(L, arg+2); + lua_pop(L, 1); + } + else + level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ if (lua_gettop(L) == arg) lua_pushliteral(L, ""); else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ @@ -323,6 +362,10 @@ static int errorfb (lua_State *L) { static const luaL_reg dblib[] = { + {"getmetatable", getmetatable}, + {"setmetatable", setmetatable}, + {"getfenv", getfenv}, + {"setfenv", setfenv}, {"getlocal", getlocal}, {"getinfo", getinfo}, {"gethook", gethook}, @@ -338,8 +381,6 @@ static const luaL_reg dblib[] = { LUALIB_API int luaopen_debug (lua_State *L) { luaL_openlib(L, LUA_DBLIBNAME, dblib, 0); - lua_pushcfunction(L, errorfb); - lua_setglobal(L, "_TRACEBACK"); return 1; } @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.13 2004/12/03 20:35:33 roberto Exp $ +** $Id: ldo.c,v 2.14 2005/02/18 12:40:02 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -474,7 +474,7 @@ static void f_parser (lua_State *L, void *ud) { luaC_checkGC(L); tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, &p->buff, p->name); - cl = luaF_newLclosure(L, tf->nups, gt(L)); + cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); cl->l.p = tf; for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ cl->l.upvals[i] = luaF_newupval(L); diff --git a/src/lfunc.c b/src/lfunc.c index af431cc3..1c95e781 100644 --- a/src/lfunc.c +++ b/src/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 2.5 2004/11/24 19:20:21 roberto Exp $ +** $Id: lfunc.c,v 2.9 2005/02/18 12:40:02 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -20,20 +20,21 @@ -Closure *luaF_newCclosure (lua_State *L, int nelems) { +Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); luaC_link(L, obj2gco(c), LUA_TFUNCTION); c->c.isC = 1; + c->c.env = e; c->c.nupvalues = cast(lu_byte, nelems); return c; } -Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e) { +Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); luaC_link(L, obj2gco(c), LUA_TFUNCTION); c->l.isC = 0; - c->l.g = *e; + c->l.env = e; c->l.nupvalues = cast(lu_byte, nelems); while (nelems--) c->l.upvals[nelems] = NULL; return c; @@ -43,42 +44,72 @@ Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e) { UpVal *luaF_newupval (lua_State *L) { UpVal *uv = luaM_new(L, UpVal); luaC_link(L, obj2gco(uv), LUA_TUPVAL); - uv->v = &uv->value; + uv->v = &uv->u.value; setnilvalue(uv->v); return uv; } UpVal *luaF_findupval (lua_State *L, StkId level) { + global_State *g = G(L); GCObject **pp = &L->openupval; UpVal *p; UpVal *uv; while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { - if (p->v == level) return p; + lua_assert(p->v != &p->u.value); + if (p->v == level) { /* found a corresponding upvalue? */ + if (isdead(g, obj2gco(p))) /* is it dead? */ + changewhite(obj2gco(p)); /* ressurect it */ + return p; + } pp = &p->next; } uv = luaM_new(L, UpVal); /* not found: create a new one */ uv->tt = LUA_TUPVAL; - uv->marked = luaC_white(G(L)); + uv->marked = luaC_white(g); uv->v = level; /* current value lives in the stack */ uv->next = *pp; /* chain it in the proper position */ *pp = obj2gco(uv); + uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ + uv->u.l.next = g->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + g->uvhead.u.l.next = uv; + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); return uv; } +static void unlinkupval (UpVal *uv) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ + uv->u.l.prev->u.l.next = uv->u.l.next; +} + + +void luaF_freeupval (lua_State *L, UpVal *uv) { + if (uv->v != &uv->u.value) /* is it open? */ + unlinkupval(uv); /* remove from open list */ + luaM_free(L, uv); /* free upvalue */ +} + + void luaF_close (lua_State *L, StkId level) { UpVal *uv; global_State *g = G(L); while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) { GCObject *o = obj2gco(uv); - lua_assert(!isblack(o)); + lua_assert(!isblack(o) && uv->v != &uv->u.value); L->openupval = uv->next; /* remove from `open' list */ if (isdead(g, o)) - luaM_free(L, uv); /* free upvalue */ + luaF_freeupval(L, uv); /* free upvalue */ else { - setobj(L, &uv->value, uv->v); - uv->v = &uv->value; /* now current value lives here */ + unlinkupval(uv); + setobj(L, &uv->u.value, uv->v); + if (isgray(o)) { + gray2black(o); /* closed upvalues are never gray */ + luaC_barrier(L, uv, &uv->u.value); + } + uv->v = &uv->u.value; /* now current value lives here */ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ } } diff --git a/src/lfunc.h b/src/lfunc.h index 04437601..93f7b888 100644 --- a/src/lfunc.h +++ b/src/lfunc.h @@ -1,5 +1,5 @@ /* -** $Id: lfunc.h,v 2.1 2003/12/10 12:13:36 roberto Exp $ +** $Id: lfunc.h,v 2.3 2005/02/18 12:40:02 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -19,13 +19,14 @@ Proto *luaF_newproto (lua_State *L); -Closure *luaF_newCclosure (lua_State *L, int nelems); -Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e); +Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); +Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); UpVal *luaF_newupval (lua_State *L); UpVal *luaF_findupval (lua_State *L, StkId level); void luaF_close (lua_State *L, StkId level); void luaF_freeproto (lua_State *L, Proto *f); void luaF_freeclosure (lua_State *L, Closure *c); +void luaF_freeupval (lua_State *L, UpVal *uv); const char *luaF_getlocalname (const Proto *func, int local_number, int pc); @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.19 2004/12/13 12:15:11 roberto Exp $ +** $Id: lgc.c,v 2.27 2005/02/23 17:30:22 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -23,30 +23,26 @@ #include "ltm.h" -#define GCSTEPSIZE 1000 -#define GCSWEEPMAX 10 -#define GCSWEEPCOST 30 +#define GCSTEPSIZE 1024u +#define GCSWEEPMAX 40 +#define GCSWEEPCOST 10 #define GCFINALIZECOST 100 -#define GCSTEPMUL 8 -#define FIXEDMASK bitmask(FIXEDBIT) - #define maskmarks \ - cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT))) + cast(lu_byte, ~(bitmask(BLACKBIT)|WHITEBITS)) #define makewhite(g,x) \ - ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite) + ((x)->gch.marked = ((x)->gch.marked & maskmarks) | luaC_white(g)) #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define gray2black(x) setbit((x)->gch.marked, BLACKBIT) #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) #define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) -#define markfinalized(u) setbit((u)->marked, FINALIZEDBIT) +#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) #define KEYWEAK bitmask(KEYWEAKBIT) @@ -61,9 +57,11 @@ reallymarkobject(g, obj2gco(t)); } +#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpace) + static void removeentry (Node *n) { - setnilvalue(gval(n)); /* remove corresponding value ... */ + lua_assert(ttisnil(gval(n))); if (iscollectable(gkey(n))) setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ } @@ -80,14 +78,14 @@ static void reallymarkobject (global_State *g, GCObject *o) { Table *mt = gco2u(o)->metatable; gray2black(o); /* udata are never gray */ if (mt) markobject(g, mt); + markobject(g, gco2u(o)->env); return; } case LUA_TUPVAL: { UpVal *uv = gco2uv(o); - if (uv->v == &uv->value) { /* closed? */ - markvalue(g, uv->v); - gray2black(o); - } + markvalue(g, uv->v); + if (uv->v == &uv->u.value) /* closed? */ + gray2black(o); /* open upvalues are never black */ return; } case LUA_TFUNCTION: { @@ -116,22 +114,24 @@ static void reallymarkobject (global_State *g, GCObject *o) { static void marktmu (global_State *g) { - GCObject *u; - for (u = g->tmudata; u; u = u->gch.next) { - makewhite(g, u); /* may be marked, if left from previous GC */ - reallymarkobject(g, u); + GCObject *u = g->tmudata; + if (u) { + do { + u = u->gch.next; + makewhite(g, u); /* may be marked, if left from previous GC */ + reallymarkobject(g, u); + } while (u != g->tmudata); } } /* move `dead' udata that need finalization to list `tmudata' */ size_t luaC_separateudata (lua_State *L, int all) { + global_State *g = G(L); size_t deadmem = 0; - GCObject **p = &G(L)->firstudata; + GCObject **p = &g->mainthread->next; GCObject *curr; - GCObject *collected = NULL; /* to collect udata with gc event */ - GCObject **lastcollected = &collected; - while ((curr = *p)->gch.tt == LUA_TUSERDATA) { + while ((curr = *p) != NULL) { if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) p = &curr->gch.next; /* don't bother with them */ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { @@ -142,15 +142,16 @@ size_t luaC_separateudata (lua_State *L, int all) { deadmem += sizeudata(gco2u(curr)); markfinalized(gco2u(curr)); *p = curr->gch.next; - curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ - *lastcollected = curr; - lastcollected = &curr->gch.next; + /* link `curr' at the end of `tmudata' list */ + if (g->tmudata == NULL) /* list is empty? */ + g->tmudata = curr->gch.next = curr; /* creates a circular list */ + else { + curr->gch.next = g->tmudata->gch.next; + g->tmudata->gch.next = curr; + g->tmudata = curr; + } } } - lua_assert(curr == obj2gco(G(L)->mainthread)); - /* insert collected udata with gc event into `tmudata' list */ - *lastcollected = G(L)->tmudata; - G(L)->tmudata = collected; return deadmem; } @@ -162,7 +163,6 @@ static int traversetable (global_State *g, Table *h) { const TValue *mode; if (h->metatable) markobject(g, h->metatable); - lua_assert(h->lsizenode || h->node == g->dummynode); mode = gfasttm(g, h->metatable, TM_MODE); if (mode && ttisstring(mode)) { /* is there a weak mode? */ weakkey = (strchr(svalue(mode), 'k') != NULL); @@ -223,6 +223,7 @@ static void traverseproto (global_State *g, Proto *f) { static void traverseclosure (global_State *g, Closure *cl) { + markobject(g, cl->c.env); if (cl->c.isC) { int i; for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */ @@ -231,7 +232,6 @@ static void traverseclosure (global_State *g, Closure *cl) { else { int i; lua_assert(cl->l.nupvalues == cl->l.p->nups); - markobject(g, hvalue(&cl->l.g)); markobject(g, cl->l.p); for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ markobject(g, cl->l.upvals[i]); @@ -368,8 +368,10 @@ static void cleartable (GCObject *l) { while (i--) { Node *n = gnode(h, i); if (!ttisnil(gval(n)) && /* non-empty entry? */ - (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) + (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { + setnilvalue(gval(n)); /* remove value ... */ removeentry(n); /* remove entry from table */ + } } l = h->gclist; } @@ -380,7 +382,7 @@ static void freeobj (lua_State *L, GCObject *o) { switch (o->gch.tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; - case LUA_TUPVAL: luaM_free(L, gco2uv(o)); break; + case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TTABLE: luaH_free(L, gco2h(o)); break; case LUA_TTHREAD: { lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); @@ -402,26 +404,23 @@ static void freeobj (lua_State *L, GCObject *o) { -#define sweepwholelist(L,p) sweeplist(L,p,LUA_MAXINT32) +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) { +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { GCObject *curr; global_State *g = G(L); - int whitebit = otherwhite(g); - int deadmask = whitebit | FIXEDMASK; - int generational = g->gcgenerational; + int deadmask = otherwhite(g); while ((curr = *p) != NULL && count-- > 0) { - if ((curr->gch.marked ^ whitebit) & deadmask) { + if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ + sweepwholelist(L, &gco2th(curr)->openupval); + if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); - if (!generational || isdead(g, curr)) - makewhite(g, curr); - if (curr->gch.tt == LUA_TTHREAD) - sweepwholelist(L, &gco2th(curr)->openupval); + makewhite(g, curr); /* make it white (for next cycle) */ p = &curr->gch.next; } - else { - lua_assert(isdead(g, curr)); + else { /* must erase `curr' */ + lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); *p = curr->gch.next; if (curr == g->rootgc) /* is the first element of the list? */ g->rootgc = curr->gch.next; /* adjust first */ @@ -432,21 +431,10 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) { } - -static void freelist (lua_State *L, GCObject **p) { - while (*p) { - GCObject *curr = *p; - *p = (*p)->gch.next; - if (curr != obj2gco(L)) - freeobj(L, curr); - } -} - - static void checkSizes (lua_State *L) { global_State *g = G(L); /* check size of string hash */ - if (g->strt.nuse < cast(lu_int32, G(L)->strt.size/4) && + if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && g->strt.size > MINSTRTABSIZE*2) luaS_resize(L, g->strt.size/2); /* table is too big */ /* check size of buffer */ @@ -459,22 +447,29 @@ static void checkSizes (lua_State *L) { static void GCTM (lua_State *L) { global_State *g = G(L); - GCObject *o = g->tmudata; + GCObject *o = g->tmudata->gch.next; /* get first element */ Udata *udata = rawgco2u(o); const TValue *tm; - g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ - udata->uv.next = g->firstudata->uv.next; /* return it to `root' list */ - g->firstudata->uv.next = o; + /* remove udata from `tmudata' */ + if (o == g->tmudata) /* last element? */ + g->tmudata = NULL; + else + g->tmudata->gch.next = udata->uv.next; + udata->uv.next = g->mainthread->next; /* return it to `root' list */ + g->mainthread->next = o; makewhite(g, o); tm = fasttm(L, udata->uv.metatable, TM_GC); if (tm != NULL) { lu_byte oldah = L->allowhook; + lu_mem oldt = g->GCthreshold; L->allowhook = 0; /* stop debug hooks during GC tag method */ + g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ setobj2s(L, L->top, tm); setuvalue(L, L->top+1, udata); L->top += 2; luaD_call(L, L->top - 2, 0); L->allowhook = oldah; /* restore hooks */ + g->GCthreshold = oldt; /* restore threshold */ } } @@ -491,9 +486,10 @@ void luaC_callGCTM (lua_State *L) { void luaC_freeall (lua_State *L) { global_State *g = G(L); int i; - freelist(L, &g->rootgc); + g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ + sweepwholelist(L, &g->rootgc); for (i = 0; i < g->strt.size; i++) /* free all string lists */ - freelist(L, &G(L)->strt.hash[i]); + sweepwholelist(L, &g->strt.hash[i]); } @@ -512,18 +508,11 @@ static void markroot (lua_State *L) { static void remarkupvals (global_State *g) { - GCObject *o; - for (o = obj2gco(g->mainthread); o; o = o->gch.next) { - lua_assert(!isblack(o)); - if (iswhite(o)) { - GCObject *curr; - for (curr = gco2th(o)->openupval; curr != NULL; curr = curr->gch.next) { - if (isgray(curr)) { - UpVal *uv = gco2uv(curr); - markvalue(g, uv->v); - } - } - } + UpVal *uv; + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + if (isgray(obj2gco(uv))) + markvalue(g, uv->v); } } @@ -531,7 +520,6 @@ static void remarkupvals (global_State *g) { static void atomic (lua_State *L) { global_State *g = G(L); size_t udsize; /* total size of userdata to be finalized */ - int aux; /* remark objects cautch by write barrier */ propagateall(g); /* remark occasional upvalues of (maybe) dead threads */ @@ -555,10 +543,6 @@ static void atomic (lua_State *L) { g->sweepstrgc = 0; g->sweepgc = &g->rootgc; g->gcstate = GCSsweepstring; - aux = g->gcgenerational; - g->gcgenerational = g->incgc && (g->estimate/2 <= g->prevestimate); - if (!aux) /* last collection was full? */ - g->prevestimate = g->estimate; /* keep estimate of last full collection */ g->estimate = g->totalbytes - udsize; /* first estimate */ } @@ -568,11 +552,7 @@ static l_mem singlestep (lua_State *L) { /*lua_checkmemory(L);*/ switch (g->gcstate) { case GCSpause: { - /* start a new collection */ - if (g->gcgenerational) - atomic(L); - else - markroot(L); + markroot(L); /* start a new collection */ return 0; } case GCSpropagate: { @@ -605,13 +585,12 @@ static l_mem singlestep (lua_State *L) { } case GCSfinalize: { if (g->tmudata) { - g->GCthreshold += GCFINALIZECOST; /* avoid GC steps inside method */ GCTM(L); - g->GCthreshold -= GCFINALIZECOST; /* correct threshold */ return GCFINALIZECOST; } else { g->gcstate = GCSpause; /* end collection */ + g->gcdept = 0; return 0; } } @@ -622,25 +601,33 @@ static l_mem singlestep (lua_State *L) { void luaC_step (lua_State *L) { global_State *g = G(L); - l_mem lim = (g->totalbytes - (g->GCthreshold - GCSTEPSIZE)) * GCSTEPMUL; + l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; + if (lim == 0) + lim = (MAX_LUMEM-1)/2; /* no limit */ + g->gcdept += g->totalbytes - g->GCthreshold; do { lim -= singlestep(L); if (g->gcstate == GCSpause) break; - } while (lim > 0 || !g->incgc); - if (g->gcstate != GCSpause) - g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/STEPMUL; */ + } while (lim > 0); + if (g->gcstate != GCSpause) { + if (g->gcdept < GCSTEPSIZE) + g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ + else { + g->gcdept -= GCSTEPSIZE; + g->GCthreshold = g->totalbytes; + } + } else { lua_assert(g->totalbytes >= g->estimate); - g->GCthreshold = g->estimate + ((g->estimate/GCDIV) * g->gcpace); + setthreshold(g); } } void luaC_fullgc (lua_State *L) { global_State *g = G(L); - if (g->gcstate <= GCSpropagate || g->gcgenerational) { - g->gcgenerational = 0; + if (g->gcstate <= GCSpropagate) { /* reset sweep marks to sweep all elements (returning them to white) */ g->sweepstrgc = 0; g->sweepgc = &g->rootgc; @@ -650,40 +637,37 @@ void luaC_fullgc (lua_State *L) { g->weak = NULL; g->gcstate = GCSsweepstring; } + lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); /* finish any pending sweep phase */ while (g->gcstate != GCSfinalize) { lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); singlestep(L); } markroot(L); - lua_assert(!g->gcgenerational); while (g->gcstate != GCSpause) { singlestep(L); - g->gcgenerational = 0; /* keep it in this mode */ } - g->GCthreshold = 2*g->estimate; + setthreshold(g); } void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { global_State *g = G(L); lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(g->gcgenerational || - (g->gcstate != GCSfinalize && g->gcstate != GCSpause)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); lua_assert(ttype(&o->gch) != LUA_TTABLE); /* must keep invariant? */ - if (g->gcstate == GCSpropagate || g->gcgenerational) + if (g->gcstate == GCSpropagate) reallymarkobject(g, v); /* restore invariant */ else /* don't mind */ makewhite(g, o); /* mark as white just to avoid other barriers */ } -void luaC_barrierback (lua_State *L, GCObject *o, GCObject *v) { +void luaC_barrierback (lua_State *L, GCObject *o) { global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(g->gcgenerational || - (g->gcstate != GCSfinalize && g->gcstate != GCSpause)); + lua_assert(isblack(o) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); black2gray(o); /* make table gray (again) */ gco2h(o)->gclist = g->grayagain; g->grayagain = o; @@ -705,7 +689,7 @@ void luaC_linkupval (lua_State *L, UpVal *uv) { o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ g->rootgc = o; if (isgray(o)) { - if (g->gcstate == GCSpropagate || g->gcgenerational) { + if (g->gcstate == GCSpropagate) { gray2black(o); /* closed upvalues need barrier */ luaC_barrier(L, uv, uv->v); } @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.9 2004/09/15 20:38:15 roberto Exp $ +** $Id: lgc.h,v 2.12 2005/02/23 17:30:22 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -29,7 +29,7 @@ #define testbits(x,m) ((x) & (m)) #define bitmask(b) (1<<(b)) #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define setbit(x,b) setbits(x, bitmask(b)) +#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))) @@ -47,8 +47,10 @@ ** bit 3 - for tables: has weak keys ** bit 4 - for tables: has weak values ** bit 5 - object is fixed (should not be collected) +** bit 6 - object is "super" fixed (only the main thread) */ + #define WHITE0BIT 0 #define WHITE1BIT 1 #define BLACKBIT 2 @@ -56,20 +58,23 @@ #define KEYWEAKBIT 3 #define VALUEWEAKBIT 4 #define FIXEDBIT 5 +#define SFIXEDBIT 6 +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define isblack(x) testbit((x)->gch.marked, BLACKBIT) #define isgray(x) (!isblack(x) && !iswhite(x)) -#define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT)) -#define isdead(g,v) ((v)->gch.marked & otherwhite(g)) +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) -#define changewhite(x) ((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT)) +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) -#define luaC_white(g) cast(lu_byte, (g)->currentwhite) +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) #define luaC_checkGC(L) { if (G(L)->totalbytes >= G(L)->GCthreshold) \ @@ -80,7 +85,7 @@ luaC_barrierf(L,obj2gco(p),gcvalue(v)); } #define luaC_barriert(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierback(L,obj2gco(p),gcvalue(v)); } + luaC_barrierback(L,obj2gco(p)); } #define luaC_objbarrier(L,p,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ @@ -88,7 +93,7 @@ #define luaC_objbarriert(L,p,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrierback(L,obj2gco(p),obj2gco(o)); } + luaC_barrierback(L,obj2gco(p)); } size_t luaC_separateudata (lua_State *L, int all); void luaC_callGCTM (lua_State *L); @@ -98,7 +103,7 @@ void luaC_fullgc (lua_State *L); void luaC_link (lua_State *L, GCObject *o, lu_byte tt); void luaC_linkupval (lua_State *L, UpVal *uv); void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); -void luaC_barrierback (lua_State *L, GCObject *o, GCObject *v); +void luaC_barrierback (lua_State *L, GCObject *o); #endif diff --git a/src/linit.c b/src/linit.c index 0d5f9cd4..24f70edb 100644 --- a/src/linit.c +++ b/src/linit.c @@ -1,5 +1,5 @@ /* -** $Id: linit.c,v 1.8 2004/07/09 15:47:48 roberto Exp $ +** $Id: linit.c,v 1.9 2005/02/18 12:40:02 roberto Exp $ ** Initialization of libraries for lua.c ** See Copyright Notice in lua.h */ @@ -32,6 +32,8 @@ LUALIB_API int luaopen_stdlibs (lua_State *L) { for (; lib->func; lib++) { lib->func(L); /* open library */ lua_settop(L, 0); /* discard any results */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_replace(L, LUA_ENVIRONINDEX); /* restore environment */ } return 0; } diff --git a/src/liolib.c b/src/liolib.c index ca9b8025..854ba3ba 100644 --- a/src/liolib.c +++ b/src/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.57 2004/08/13 19:52:13 roberto Exp $ +** $Id: liolib.c,v 2.58 2005/02/18 12:40:02 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -105,8 +105,8 @@ static int aux_close (lua_State *L) { static int io_close (lua_State *L) { - if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) - lua_rawgeti(L, lua_upvalueindex(1), IO_OUTPUT); + if (lua_isnone(L, 1)) + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); return pushresult(L, aux_close(L), NULL); } @@ -147,7 +147,7 @@ static int io_tmpfile (lua_State *L) { static FILE *getiofile (lua_State *L, int findex) { FILE *f; - lua_rawgeti(L, lua_upvalueindex(1), findex); + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE)); f = *(FILE **)lua_touserdata(L, -1); if (f == NULL) @@ -170,10 +170,10 @@ static int g_iofile (lua_State *L, int f, const char *mode) { lua_pushvalue(L, 1); } lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE)); - lua_rawseti(L, lua_upvalueindex(1), f); + lua_rawseti(L, LUA_ENVIRONINDEX, f); } /* return current value */ - lua_rawgeti(L, lua_upvalueindex(1), f); + lua_rawgeti(L, LUA_ENVIRONINDEX, f); return 1; } @@ -192,10 +192,9 @@ static int io_readline (lua_State *L); static void aux_lines (lua_State *L, int idx, int close) { - lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); lua_pushvalue(L, idx); lua_pushboolean(L, close); /* close/not close file when finished */ - lua_pushcclosure(L, io_readline, 3); + lua_pushcclosure(L, io_readline, 2); } @@ -209,7 +208,7 @@ static int f_lines (lua_State *L) { static int io_lines (lua_State *L) { if (lua_isnoneornil(L, 1)) { /* no arguments? */ /* will iterate over default input */ - lua_rawgeti(L, lua_upvalueindex(1), IO_INPUT); + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); return f_lines(L); } else { @@ -349,7 +348,7 @@ static int f_read (lua_State *L) { static int io_readline (lua_State *L) { - FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2)); + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); int sucess; if (f == NULL) /* file is already closed? */ luaL_error(L, "file is already closed"); @@ -358,9 +357,9 @@ static int io_readline (lua_State *L) { luaL_error(L, "%s", strerror(errno)); if (sucess) return 1; else { /* EOF */ - if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ + if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(2)); + lua_pushvalue(L, lua_upvalueindex(1)); aux_close(L); /* close it */ } return 0; @@ -489,12 +488,13 @@ LUALIB_API int luaopen_io (lua_State *L) { createmeta(L); createupval(L); lua_pushvalue(L, -1); - luaL_openlib(L, LUA_IOLIBNAME, iolib, 1); + lua_replace(L, LUA_ENVIRONINDEX); + luaL_openlib(L, LUA_IOLIBNAME, iolib, 0); /* put predefined file handles into `io' table */ - lua_rawgeti(L, -2, IO_INPUT); /* get current input from metatable */ - lua_setfield(L, -2, "stdin"); /* io.stdin = metatable[IO_INPUT] */ - lua_rawgeti(L, -2, IO_OUTPUT); /* get current output from metatable */ - lua_setfield(L, -2, "stdout"); /* io.stdout = metatable[IO_OUTPUT] */ + lua_rawgeti(L, -2, IO_INPUT); /* get current input from upval */ + lua_setfield(L, -2, "stdin"); /* io.stdin = upval[IO_INPUT] */ + lua_rawgeti(L, -2, IO_OUTPUT); /* get current output from upval */ + lua_setfield(L, -2, "stdout"); /* io.stdout = upval[IO_OUTPUT] */ *newfile(L) = stderr; lua_setfield(L, -2, "stderr"); /* io.stderr = newfile(stderr) */ return 1; diff --git a/src/llimits.h b/src/llimits.h index c3d5d532..5b11e820 100644 --- a/src/llimits.h +++ b/src/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.62 2004/12/13 12:15:11 roberto Exp $ +** $Id: llimits.h,v 1.63 2005/01/14 14:19:42 roberto Exp $ ** Limits, basic types, and some other `installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -73,8 +73,6 @@ typedef LUA_UACNUMBER l_uacNumber; typedef lu_int32 Instruction; -/* divisor for GC pace */ -#define GCDIV 8 /* maximum stack for a Lua function */ #define MAXSTACK 250 diff --git a/src/lmathlib.c b/src/lmathlib.c index fcd2eefb..add88970 100644 --- a/src/lmathlib.c +++ b/src/lmathlib.c @@ -1,5 +1,5 @@ /* -** $Id: lmathlib.c,v 1.61 2004/05/10 18:11:32 roberto Exp $ +** $Id: lmathlib.c,v 1.62 2005/01/07 20:00:33 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ @@ -225,8 +225,6 @@ LUALIB_API int luaopen_math (lua_State *L) { luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0); lua_pushnumber(L, PI); lua_setfield(L, -2, "pi"); - lua_pushcfunction(L, math_pow); - lua_setglobal(L, "__pow"); return 1; } @@ -1,5 +1,5 @@ /* -** $Id: lmem.c,v 1.67 2004/12/01 15:46:18 roberto Exp $ +** $Id: lmem.c,v 1.69 2005/02/23 17:30:22 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -22,19 +22,19 @@ /* ** About the realloc function: -** void * realloc (void *ud, void *ptr, size_t osize, size_t nsize); +** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); ** (`osize' is the old size, `nsize' is the new size) ** ** Lua ensures that (ptr == NULL) iff (osize == 0). ** -** * realloc(ud, NULL, 0, x) creates a new block of size `x' +** * frealloc(ud, NULL, 0, x) creates a new block of size `x' ** -** * realloc(ud, p, x, 0) frees the block `p' -** (in this specific case, realloc must return NULL). -** particularly, realloc(ud, NULL, 0, 0) does nothing +** * frealloc(ud, p, x, 0) frees the block `p' +** (in this specific case, frealloc must return NULL). +** particularly, frealloc(ud, NULL, 0, 0) does nothing ** (which is equivalent to free(NULL) in ANSI C) ** -** realloc returns NULL if it cannot create or reallocate the area +** frealloc returns NULL if it cannot create or reallocate the area ** (any reallocation to an equal or smaller size cannot fail!) */ @@ -76,11 +76,27 @@ void *luaM_toobig (lua_State *L) { void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { global_State *g = G(L); lua_assert((osize == 0) == (block == NULL)); - block = (*g->realloc)(g->ud, block, osize, nsize); + block = (*g->frealloc)(g->ud, block, osize, nsize); if (block == NULL && nsize > 0) luaD_throw(L, LUA_ERRMEM); lua_assert((nsize == 0) == (block == NULL)); g->totalbytes = (g->totalbytes - osize) + nsize; +#if 0 + { /* auxiliar patch to monitor garbage collection */ + static unsigned long total = 0; /* our "time" */ + static lu_mem last = 0; /* last totalmem that generated an output */ + static FILE *f = NULL; /* output file */ + if (nsize <= osize) total += 1; /* "time" always grow */ + else total += (nsize - osize); + if ((int)g->totalbytes - (int)last > 1000 || + (int)g->totalbytes - (int)last < -1000) { + last = g->totalbytes; + if (f == NULL) f = fopen("trace", "w"); + fprintf(f, "%lu %u %u %u %d\n", total, g->totalbytes, g->GCthreshold, + g->estimate, g->gcstate); + } + } +#endif return block; } diff --git a/src/loadlib.c b/src/loadlib.c index 4adcbdc0..957310b6 100644 --- a/src/loadlib.c +++ b/src/loadlib.c @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.15 2004/12/29 18:56:34 roberto Exp $ +** $Id: loadlib.c,v 1.18 2005/02/28 15:58:48 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h * @@ -293,45 +293,60 @@ static int ll_loadlib (lua_State *L) { */ -static const char *loadLua (lua_State *L, const char *fname, const char *name) { +static int loader_Lua (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP); const char *path; /* try first `LUA_PATH' for compatibility */ - lua_getglobal(L, "LUA_PATH"); + lua_pushstring(L, "LUA_PATH"); + lua_rawget(L, LUA_GLOBALSINDEX); path = lua_tostring(L, -1); if (!path) { lua_pop(L, 1); - luaL_getfield(L, LUA_GLOBALSINDEX, "package.path"); + lua_getfield(L, LUA_ENVIRONINDEX, "path"); path = lua_tostring(L, -1); } if (path == NULL) luaL_error(L, "`package.path' must be a string"); fname = luaL_searchpath(L, fname, path); - if (fname == NULL) return path; /* library not found in this path */ + if (fname == NULL) return 0; /* library not found in this path */ if (luaL_loadfile(L, fname) != 0) luaL_error(L, "error loading package `%s' (%s)", name, lua_tostring(L, -1)); - return NULL; /* library loaded successfully */ + return 1; /* library loaded successfully */ } -static const char *loadC (lua_State *L, const char *fname, const char *name) { +static int loader_C (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP); const char *path; const char *funcname; - luaL_getfield(L, LUA_GLOBALSINDEX, "package.cpath"); + lua_getfield(L, LUA_ENVIRONINDEX, "cpath"); path = lua_tostring(L, -1); if (path == NULL) luaL_error(L, "`package.cpath' must be a string"); fname = luaL_searchpath(L, fname, path); - if (fname == NULL) return path; /* library not found in this path */ + if (fname == NULL) return 0; /* library not found in this path */ funcname = luaL_gsub(L, name, ".", LUA_OFSEP); funcname = lua_pushfstring(L, "%s%s", POF, funcname); if (ll_loadfunc(L, fname, funcname) != 1) luaL_error(L, "error loading package `%s' (%s)", name, lua_tostring(L, -2)); - return NULL; /* library loaded successfully */ + return 1; /* library loaded successfully */ +} + + +static int loader_preload (lua_State *L) { + lua_getfield(L, LUA_ENVIRONINDEX, "preload"); + if (!lua_istable(L, -1)) + luaL_error(L, "`package.preload' must be a table"); + lua_getfield(L, -1, luaL_checkstring(L, 1)); + return 1; } static int ll_require (lua_State *L) { const char *name = luaL_checkstring(L, 1); + int i; lua_settop(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, 2, name); @@ -340,22 +355,18 @@ static int ll_require (lua_State *L) { /* else must load it; first mark it as loaded */ lua_pushboolean(L, 1); lua_setfield(L, 2, name); /* _LOADED[name] = true */ - /* check whether it is preloaded */ - lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); - lua_getfield(L, -1, name); - if (lua_isnil(L, -1)) { /* no preload function for that module? */ - const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP); - const char *cpath = loadC(L, fname, name); /* try a C module */ - if (cpath) { /* not found? */ - const char *path = loadLua(L, fname, name); /* try a Lua module */ - if (path) { /* yet not found? */ - lua_pushnil(L); - lua_setfield(L, 2, name); /* unmark _LOADED[name] */ - return luaL_error(L, "package `%s' not found\n" - " cpath: %s\n path: %s", - name, cpath, path); - } - } + /* iterate over available loaders */ + lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); + if (!lua_istable(L, -1)) + luaL_error(L, "`package.loaders' must be a table"); + for (i=1;; i++) { + lua_rawgeti(L, -1, i); /* get a loader */ + if (lua_isnil(L, -1)) + return luaL_error(L, "package `%s' not found", name); + lua_pushstring(L, name); + lua_call(L, 1, 1); /* call it */ + if (lua_isnil(L, -1)) lua_pop(L, 1); + else break; /* module loaded successfully */ } lua_pushvalue(L, 1); /* pass name as argument to module */ lua_call(L, 1, 1); /* run loaded module */ @@ -430,9 +441,13 @@ static const luaL_reg ll_funcs[] = { }; +static const lua_CFunction loaders[] = + {loader_preload, loader_C, loader_Lua, NULL}; + LUALIB_API int luaopen_loadlib (lua_State *L) { const char *path; + int i; /* create new type _LOADLIB */ luaL_newmetatable(L, "_LOADLIB"); lua_pushcfunction(L, gctm); @@ -441,6 +456,19 @@ LUALIB_API int luaopen_loadlib (lua_State *L) { lua_newtable(L); lua_pushvalue(L, -1); lua_setglobal(L, "package"); + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, "_PACKAGE"); + lua_pushvalue(L, -1); + lua_replace(L, LUA_ENVIRONINDEX); + /* create `loaders' table */ + lua_newtable(L); + /* fill it with pre-defined loaders */ + for (i=0; loaders[i] != NULL; i++) { + lua_pushcfunction(L, loaders[i]); + lua_rawseti(L, -2, i+1); + } + /* put it in field `loaders' */ + lua_setfield(L, -2, "loaders"); /* set field `path' */ path = getenv(LUA_PATH); if (path == NULL) path = LUA_PATH_DEFAULT; @@ -455,7 +483,7 @@ LUALIB_API int luaopen_loadlib (lua_State *L) { lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_setfield(L, -2, "loaded"); /* set field `preload' */ - lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); + lua_newtable(L); lua_setfield(L, -2, "preload"); lua_pushvalue(L, LUA_GLOBALSINDEX); luaL_openlib(L, NULL, ll_funcs, 0); /* open lib into global table */ diff --git a/src/lobject.c b/src/lobject.c index 154a0faf..f4464474 100644 --- a/src/lobject.c +++ b/src/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.7 2004/11/24 19:16:03 roberto Exp $ +** $Id: lobject.c,v 2.8 2005/01/10 18:17:39 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -73,7 +73,7 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) { case LUA_TNIL: return 1; case LUA_TNUMBER: - return nvalue(t1) == nvalue(t2); + return num_eq(nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ case LUA_TLIGHTUSERDATA: diff --git a/src/lobject.h b/src/lobject.h index 56c0fe8a..967b46c7 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.8 2004/12/04 18:10:22 roberto Exp $ +** $Id: lobject.h,v 2.11 2005/02/18 12:40:02 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -218,6 +218,7 @@ typedef union Udata { struct { CommonHeader; struct Table *metatable; + struct Table *env; size_t len; } uv; } Udata; @@ -271,7 +272,13 @@ typedef struct LocVar { typedef struct UpVal { CommonHeader; TValue *v; /* points to stack or to its own value */ - TValue value; /* the value (when closed) */ + union { + TValue value; /* the value (when closed) */ + struct { /* double linked list (when open) */ + struct UpVal *prev; + struct UpVal *next; + } l; + } u; } UpVal; @@ -280,7 +287,8 @@ typedef struct UpVal { */ #define ClosureHeader \ - CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ + struct Table *env typedef struct CClosure { ClosureHeader; @@ -292,7 +300,6 @@ typedef struct CClosure { typedef struct LClosure { ClosureHeader; struct Proto *p; - TValue g; /* global table for this closure */ UpVal *upvals[1]; } LClosure; @@ -330,7 +337,7 @@ typedef struct Table { struct Table *metatable; TValue *array; /* array part */ Node *node; - Node *firstfree; /* this position is free; all positions after it are full */ + Node *lastfree; /* any free position is before this position */ GCObject *gclist; int sizearray; /* size of `array' array */ } Table; @@ -351,6 +358,8 @@ typedef struct Table { extern const TValue luaO_nilobject; +#define ceillog2(x) (luaO_log2((x)-1) + 1) + int luaO_log2 (unsigned int x); int luaO_int2fb (unsigned int x); int luaO_fb2int (int x); diff --git a/src/loslib.c b/src/loslib.c index 4f1d2d03..dad959e2 100644 --- a/src/loslib.c +++ b/src/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.3 2004/10/08 18:57:16 roberto Exp $ +** $Id: loslib.c,v 1.4 2005/01/10 19:16:29 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -91,15 +91,13 @@ static int io_clock (lua_State *L) { */ static void setfield (lua_State *L, const char *key, int value) { - lua_pushstring(L, key); lua_pushinteger(L, value); - lua_rawset(L, -3); + lua_setfield(L, -2, key); } static void setboolfield (lua_State *L, const char *key, int value) { - lua_pushstring(L, key); lua_pushboolean(L, value); - lua_rawset(L, -3); + lua_setfield(L, -2, key); } static int getboolfield (lua_State *L, const char *key) { diff --git a/src/lparser.c b/src/lparser.c index b6b3c0a0..19e048ce 100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.11 2004/12/07 18:31:16 roberto Exp $ +** $Id: lparser.c,v 2.13 2005/01/05 18:20:51 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -547,7 +547,7 @@ static void constructor (LexState *ls, expdesc *t) { check_match(ls, '}', '{', line); lastlistfield(fs, &cc); SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ - SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ } /* }====================================================================== */ diff --git a/src/lstate.c b/src/lstate.c index bd238c58..18dd4f95 100644 --- a/src/lstate.c +++ b/src/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.19 2004/12/13 12:15:11 roberto Exp $ +** $Id: lstate.c,v 2.25 2005/02/23 17:30:22 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -76,33 +76,22 @@ static void freestack (lua_State *L, lua_State *L1) { ** open parts that may cause memory-allocation errors */ static void f_luaopen (lua_State *L, void *ud) { - Udata *u; /* head of udata list */ global_State *g = G(L); UNUSED(ud); - u = luaM_new(L, Udata); - u->uv.len = 0; - u->uv.metatable = NULL; - g->firstudata = obj2gco(u); - luaC_link(L, obj2gco(u), LUA_TUSERDATA); - setbit(u->uv.marked, FIXEDBIT); - setbit(L->marked, FIXEDBIT); stack_init(L, L); /* init stack */ - sethvalue(L, gt(L), luaH_new(L, 0, 4)); /* table of globals */ + sethvalue(L, gt(L), luaH_new(L, 0, 20)); /* table of globals */ hvalue(gt(L))->metatable = luaH_new(L, 0, 0); /* globals metatable */ - sethvalue(L, registry(L), luaH_new(L, 4, 4)); /* registry */ + sethvalue(L, registry(L), luaH_new(L, 6, 20)); /* registry */ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ luaT_init(L); luaX_init(L); luaS_fix(luaS_newliteral(L, MEMERRMSG)); g->GCthreshold = 4*g->totalbytes; - g->prevestimate = g->estimate = g->totalbytes; } static void preinit_state (lua_State *L, global_State *g) { L->l_G = g; - L->tt = LUA_TTHREAD; - L->marked = luaC_white(g); L->stack = NULL; L->stacksize = 0; L->errorJmp = NULL; @@ -125,20 +114,19 @@ static void close_state (lua_State *L) { global_State *g = G(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ luaC_freeall(L); /* collect all objects */ - lua_assert(g->rootgc == NULL); + lua_assert(g->rootgc == obj2gco(L)); lua_assert(g->strt.nuse == 0); luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); luaZ_freebuffer(L, &g->buff); freestack(L, L); lua_assert(g->totalbytes == sizeof(LG)); - (*g->realloc)(g->ud, fromstate(L), state_size(LG), 0); + (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); } lua_State *luaE_newthread (lua_State *L) { lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); - L1->next = L->next; /* link new thread after `L' */ - L->next = obj2gco(L1); + luaC_link(L, obj2gco(L1), LUA_TTHREAD); preinit_state(L1, G(L)); stack_init(L1, L); /* init stack */ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ @@ -167,11 +155,16 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { L = tostate(l); g = &((LG *)L)->g; L->next = NULL; - g->currentwhite = bitmask(WHITE0BIT); + L->tt = LUA_TTHREAD; + g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + L->marked = luaC_white(g); + set2bits(L->marked, FIXEDBIT, SFIXEDBIT); preinit_state(L, g); - g->realloc = f; + g->frealloc = f; g->ud = ud; g->mainthread = L; + g->uvhead.u.l.prev = &g->uvhead; + g->uvhead.u.l.next = &g->uvhead; g->GCthreshold = 0; /* mark it as unfinished state */ g->strt.size = 0; g->strt.nuse = 0; @@ -180,21 +173,17 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { luaZ_initbuffer(L, &g->buff); g->panic = NULL; g->gcstate = GCSpause; - g->gcgenerational = 0; g->rootgc = obj2gco(L); g->sweepstrgc = 0; g->sweepgc = &g->rootgc; - g->firstudata = NULL; g->gray = NULL; g->grayagain = NULL; g->weak = NULL; g->tmudata = NULL; - setnilvalue(gkey(g->dummynode)); - setnilvalue(gval(g->dummynode)); - gnext(g->dummynode) = NULL; g->totalbytes = sizeof(LG); - g->gcpace = GCDIV; - g->incgc = 1; + g->gcpace = 200; /* 200% (wait memory to double before next collection) */ + g->gcstepmul = 200; /* GC runs `twice the speed' of memory allocation */ + g->gcdept = 0; if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { /* memory allocation error: free partial state */ close_state(L); diff --git a/src/lstate.h b/src/lstate.h index 4f29190a..54469172 100644 --- a/src/lstate.h +++ b/src/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.10 2004/12/13 12:15:11 roberto Exp $ +** $Id: lstate.h,v 2.16 2005/02/23 17:30:22 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -67,30 +67,28 @@ typedef struct CallInfo { */ typedef struct global_State { stringtable strt; /* hash table for strings */ - lua_Alloc realloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to `realloc' */ + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to `frealloc' */ lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ - lu_byte gcgenerational; GCObject *rootgc; /* list of all collectable objects */ - GCObject *firstudata; /* udata go to the end of `rootgc' */ GCObject **sweepgc; /* position of sweep in `rootgc' */ int sweepstrgc; /* position of sweep in `strt' */ GCObject *gray; /* list of gray objects */ GCObject *grayagain; /* list of objects to be traversed atomically */ GCObject *weak; /* list of weak tables (to be cleared) */ - GCObject *tmudata; /* list of userdata to be GC */ + GCObject *tmudata; /* last element of list of userdata to be GC */ Mbuffer buff; /* temporary buffer for string concatentation */ lu_mem GCthreshold; lu_mem totalbytes; /* number of bytes currently allocated */ lu_mem estimate; /* an estimate of number of bytes actually in use */ - lu_mem prevestimate; /* previous estimate */ - int gcpace; /* relative `speed' of the GC */ - int incgc; /* 0 if GC is done non-incrementally */ + lu_mem gcdept; /* how much GC is `behind schedule' */ + int gcpace; /* size of pause between successive GCs */ + int gcstepmul; /* GC `granularity' */ lua_CFunction panic; /* to be called in unprotected errors */ TValue _registry; struct lua_State *mainthread; - Node dummynode[1]; /* common node array for all empty tables */ + UpVal uvhead; /* head of double-linked list of all open upvalues */ TString *tmname[TM_N]; /* array with tag-method names */ } global_State; @@ -118,6 +116,7 @@ struct lua_State { int hookcount; lua_Hook hook; TValue _gt; /* table of globals */ + TValue env; /* temporary place for environments */ GCObject *openupval; /* list of open upvalues in this stack */ GCObject *gclist; struct lua_longjmp *errorJmp; /* current error recover point */ diff --git a/src/lstring.c b/src/lstring.c index af2c6963..897089a4 100644 --- a/src/lstring.c +++ b/src/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.5 2004/11/24 19:16:03 roberto Exp $ +** $Id: lstring.c,v 2.7 2005/02/18 12:40:02 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -93,7 +93,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { } -Udata *luaS_newudata (lua_State *L, size_t s) { +Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { Udata *u; if (s > MAX_SIZET - sizeof(Udata)) luaM_toobig(L); @@ -102,9 +102,10 @@ Udata *luaS_newudata (lua_State *L, size_t s) { u->uv.tt = LUA_TUSERDATA; u->uv.len = s; u->uv.metatable = NULL; - /* chain it on udata list */ - u->uv.next = G(L)->firstudata->uv.next; - G(L)->firstudata->uv.next = obj2gco(u); + u->uv.env = e; + /* chain it on udata list (after main thread) */ + u->uv.next = G(L)->mainthread->next; + G(L)->mainthread->next = obj2gco(u); return u; } diff --git a/src/lstring.h b/src/lstring.h index 4198f57c..88f6da80 100644 --- a/src/lstring.h +++ b/src/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.40 2004/11/19 15:52:40 roberto Exp $ +** $Id: lstring.h,v 1.42 2005/02/23 17:30:22 roberto Exp $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -21,10 +21,10 @@ #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) -#define luaS_fix(s) setbit((s)->tsv.marked, FIXEDBIT) +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) void luaS_resize (lua_State *L, int newsize); -Udata *luaS_newudata (lua_State *L, size_t s); +Udata *luaS_newudata (lua_State *L, size_t s, Table *e); TString *luaS_newlstr (lua_State *L, const char *str, size_t l); diff --git a/src/ltable.c b/src/ltable.c index 8bfbf641..d4070dd5 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.12 2004/12/04 18:10:22 roberto Exp $ +** $Id: ltable.c,v 2.15 2005/01/10 18:17:39 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -68,6 +68,13 @@ #define numints cast(int, sizeof(lua_Number)/sizeof(int)) + +const Node luaH_dummynode = { + {{NULL}, LUA_TNIL}, /* value */ + {{NULL}, LUA_TNIL, NULL} /* key */ +}; + + /* ** hash for lua_Numbers */ @@ -112,7 +119,7 @@ static int arrayindex (const TValue *key) { lua_Number n = nvalue(key); int k; lua_number2int(k, n); - if (cast(lua_Number, k) == nvalue(key)) + if (num_eq(cast(lua_Number, k), nvalue(key))) return k; } return -1; /* `key' did not match some condition */ @@ -176,62 +183,77 @@ int luaH_next (lua_State *L, Table *t, StkId key) { */ -static void computesizes (int nums[], int ntotal, int *narray, int *nhash) { +static int computesizes (int nums[], int *narray) { int i; - int a = nums[0]; /* number of elements smaller than 2^i */ - int na = a; /* number of elements to go to array part */ - int n = (na == 0) ? -1 : 0; /* (log of) optimal size for array part */ - for (i = 1; a < *narray && *narray >= twoto(i-1); i++) { + int twotoi; /* 2^i */ + int a = 0; /* number of elements smaller than 2^i */ + int na = 0; /* number of elements to go to array part */ + int n = 0; /* optimal size for array part */ + for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { if (nums[i] > 0) { a += nums[i]; - if (a >= twoto(i-1)) { /* more than half elements in use? */ - n = i; - na = a; + if (a > twotoi/2) { /* more than half elements present? */ + n = twotoi; /* optimal size (till now) */ + na = a; /* all elements smaller than n will go to array part */ } } + if (a == *narray) break; /* all elements already counted */ + } + *narray = n; + lua_assert(*narray/2 <= na && na <= *narray); + return na; +} + + +static int countint (const TValue *key, int *nums) { + int k = arrayindex(key); + if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ + nums[ceillog2(k)]++; /* count as such */ + return 1; } - lua_assert(na <= *narray && *narray <= ntotal); - *nhash = ntotal - na; - *narray = (n == -1) ? 0 : twoto(n); - lua_assert(na <= *narray && na >= *narray/2); + else + return 0; } -static void numuse (const Table *t, int *narray, int *nhash) { - int nums[MAXBITS+1]; - int i, lg; - int totaluse = 0; - /* count elements in array part */ - for (i=0, lg=0; lg<=MAXBITS; lg++) { /* for each slice [2^(lg-1) to 2^lg) */ - int ttlg = twoto(lg); /* 2^lg */ - if (ttlg > t->sizearray) { - ttlg = t->sizearray; - if (i >= ttlg) break; +static int numusearray (const Table *t, int *nums) { + int lg; + int ttlg; /* 2^lg */ + int ause = 0; /* summation of `nums' */ + int i = 1; /* count to traverse all array keys */ + for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ + int lc = 0; /* counter */ + int lim = ttlg; + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ } - nums[lg] = 0; - for (; i<ttlg; i++) { - if (!ttisnil(&t->array[i])) { - nums[lg]++; - totaluse++; - } + /* count elements in range (2^(lg-1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; } + nums[lg] += lc; + ause += lc; } - for (; lg<=MAXBITS; lg++) nums[lg] = 0; /* reset other counts */ - *narray = totaluse; /* all previous uses were in array part */ - /* count elements in hash part */ - i = sizenode(t); + return ause; +} + + +static int numusehash (const Table *t, int *nums, int *pnasize) { + int totaluse = 0; /* total number of elements */ + int ause = 0; /* summation of `nums' */ + int i = sizenode(t); while (i--) { Node *n = &t->node[i]; if (!ttisnil(gval(n))) { - int k = arrayindex(key2tval(n)); - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ - nums[luaO_log2(k-1)+1]++; /* count as such */ - (*narray)++; - } + ause += countint(key2tval(n), nums); totaluse++; } } - computesizes(nums, totaluse, narray, nhash); + *pnasize += ause; + return totaluse; } @@ -244,18 +266,18 @@ static void setarrayvector (lua_State *L, Table *t, int size) { } -static void setnodevector (lua_State *L, Table *t, int lsize) { - int i; - int size = twoto(lsize); - if (lsize > MAXBITS) - luaG_runerror(L, "table overflow"); - if (lsize == 0) { /* no elements to hash part? */ - t->node = G(L)->dummynode; /* use common `dummynode' */ - lua_assert(ttisnil(gkey(t->node))); /* assert invariants: */ - lua_assert(ttisnil(gval(t->node))); - lua_assert(gnext(t->node) == NULL); /* (`dummynode' must be empty) */ +static void setnodevector (lua_State *L, Table *t, int size) { + int lsize; + if (size == 0) { /* no elements to hash part? */ + t->node = cast(Node *, &luaH_dummynode); /* use common `dummynode' */ + lsize = 0; } else { + int i; + lsize = ceillog2(size); + if (lsize > MAXBITS) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); t->node = luaM_newvector(L, size, Node); for (i=0; i<size; i++) { gnext(&t->node[i]) = NULL; @@ -264,31 +286,19 @@ static void setnodevector (lua_State *L, Table *t, int lsize) { } } t->lsizenode = cast(lu_byte, lsize); - t->firstfree = gnode(t, size-1); /* first free position to be used */ + t->lastfree = gnode(t, size); /* all positions are free */ } -void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { +static void resize (lua_State *L, Table *t, int nasize, int nhsize) { int i; int oldasize = t->sizearray; int oldhsize = t->lsizenode; - Node *nold; - Node temp[1]; - if (oldhsize) - nold = t->node; /* save old hash ... */ - else { /* old hash is `dummynode' */ - lua_assert(t->node == G(L)->dummynode); - temp[0] = t->node[0]; /* copy it to `temp' */ - nold = temp; - setnilvalue(gkey(G(L)->dummynode)); /* restate invariant */ - setnilvalue(gval(G(L)->dummynode)); - lua_assert(gnext(G(L)->dummynode) == NULL); - } + Node *nold = t->node; /* save old hash ... */ if (nasize > oldasize) /* array part must grow? */ setarrayvector(L, t, nasize); /* create new hash part with appropriate size */ setnodevector(L, t, nhsize); - /* re-insert elements */ if (nasize < oldasize) { /* array part must shrink? */ t->sizearray = nasize; /* re-insert elements from vanishing slice */ @@ -299,21 +309,39 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { /* shrink array */ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); } - /* re-insert elements in hash part */ + /* re-insert elements from hash part */ for (i = twoto(oldhsize) - 1; i >= 0; i--) { Node *old = nold+i; if (!ttisnil(gval(old))) setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); } - if (oldhsize) + if (nold != &luaH_dummynode) luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ } -static void rehash (lua_State *L, Table *t) { - int nasize, nhsize; - numuse(t, &nasize, &nhsize); /* compute new sizes for array and hash parts */ - luaH_resize(L, t, nasize, luaO_log2(nhsize)+1); +void luaH_resizearray (lua_State *L, Table *t, int nasize) { + int nsize = (t->node == &luaH_dummynode) ? 0 : sizenode(t); + resize(L, t, nasize, nsize); +} + + +static void rehash (lua_State *L, Table *t, const TValue *ek) { + int nasize, na; + int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ + int i; + int totaluse; + for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ + nasize = numusearray(t, nums); /* count keys in array part */ + totaluse = nasize; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + /* count extra key */ + nasize += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + na = computesizes(nums, &nasize); + /* resize the table to new computed sizes */ + resize(L, t, nasize, totaluse - na); } @@ -323,7 +351,7 @@ static void rehash (lua_State *L, Table *t) { */ -Table *luaH_new (lua_State *L, int narray, int lnhash) { +Table *luaH_new (lua_State *L, int narray, int nhash) { Table *t = luaM_new(L, Table); luaC_link(L, obj2gco(t), LUA_TTABLE); t->metatable = NULL; @@ -332,21 +360,30 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) { t->array = NULL; t->sizearray = 0; t->lsizenode = 0; - t->node = NULL; + t->node = cast(Node *, &luaH_dummynode); setarrayvector(L, t, narray); - setnodevector(L, t, lnhash); + setnodevector(L, t, nhash); return t; } void luaH_free (lua_State *L, Table *t) { - if (t->lsizenode) + if (t->node != &luaH_dummynode) luaM_freearray(L, t->node, sizenode(t), Node); luaM_freearray(L, t->array, t->sizearray, TValue); luaM_free(L, t); } +static Node *getfreepos (lua_State *L, Table *t) { + while (t->lastfree-- > t->node) { + if (ttisnil(gkey(t->lastfree))) + return t->lastfree; + } + return NULL; /* could not find a free place */ +} + + /* ** inserts a new key into a hash table; first, check whether key's main @@ -356,12 +393,16 @@ void luaH_free (lua_State *L, Table *t) { ** position), new key goes to an empty position. */ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { - TValue *val; Node *mp = luaH_mainposition(t, key); - if (!ttisnil(gval(mp))) { /* main position is not free? */ - /* `mp' of colliding node */ - Node *othern = luaH_mainposition(t, key2tval(mp)); - Node *n = t->firstfree; /* get a free place */ + if (!ttisnil(gval(mp)) || mp == &luaH_dummynode) { + Node *othern; + Node *n = getfreepos(L, 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 */ + } + lua_assert(n != &luaH_dummynode); + othern = luaH_mainposition(t, key2tval(mp)); if (othern != mp) { /* is colliding node out of its main position? */ /* yes; move colliding node into free position */ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ @@ -380,19 +421,7 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; luaC_barriert(L, t, key); lua_assert(ttisnil(gval(mp))); - for (;;) { /* correct `firstfree' */ - if (ttisnil(gkey(t->firstfree))) - return gval(mp); /* OK; table still has a free place */ - else if (t->firstfree == t->node) break; /* cannot decrement from here */ - else (t->firstfree)--; - } - /* no more free places; must create one */ - setbvalue(gval(mp), 0); /* avoid new key being removed */ - rehash(L, t); /* grow table */ - val = cast(TValue *, luaH_get(t, key)); /* get new position */ - lua_assert(ttisboolean(val)); - setnilvalue(val); - return val; + return gval(mp); } @@ -407,7 +436,7 @@ const TValue *luaH_getnum (Table *t, int key) { lua_Number nk = cast(lua_Number, key); Node *n = hashnum(t, nk); do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == nk) + if (ttisnumber(gkey(n)) && num_eq(nvalue(gkey(n)), nk)) return gval(n); /* that's it */ else n = gnext(n); } while (n); @@ -440,7 +469,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { case LUA_TNUMBER: { int k; lua_number2int(k, (nvalue(key))); - if (cast(lua_Number, k) == nvalue(key)) /* is an integer index? */ + if (num_eq(cast(lua_Number, k), nvalue(key))) /* is an integer index? */ return luaH_getnum(t, k); /* use specialized version */ /* else go through */ } @@ -464,7 +493,7 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { return cast(TValue *, p); else { if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && nvalue(key) != nvalue(key)) + else if (ttisnumber(key) && !num_eq(nvalue(key), nvalue(key))) luaG_runerror(L, "table index is NaN"); return newkey(L, t, key); } diff --git a/src/ltable.h b/src/ltable.h index cfc86017..9700062e 100644 --- a/src/ltable.h +++ b/src/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.3 2004/10/06 18:34:16 roberto Exp $ +** $Id: ltable.h,v 2.5 2005/01/05 18:20:51 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -18,6 +18,8 @@ #define key2tval(n) (cast(const TValue *, gkey(n))) +extern const Node luaH_dummynode; + const TValue *luaH_getnum (Table *t, int key); TValue *luaH_setnum (lua_State *L, Table *t, int key); const TValue *luaH_getstr (Table *t, TString *key); @@ -25,7 +27,7 @@ TValue *luaH_setstr (lua_State *L, Table *t, TString *key); const TValue *luaH_get (Table *t, const TValue *key); TValue *luaH_set (lua_State *L, Table *t, const TValue *key); Table *luaH_new (lua_State *L, int narray, int lnhash); -void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); +void luaH_resizearray (lua_State *L, Table *t, int nasize); void luaH_free (lua_State *L, Table *t); int luaH_next (lua_State *L, Table *t, StkId key); @@ -1,5 +1,5 @@ /* -** $Id: lua.c,v 1.133 2004/11/18 19:53:49 roberto Exp $ +** $Id: lua.c,v 1.135 2005/01/10 17:21:10 roberto Exp $ ** Lua stand-alone interpreter ** See Copyright Notice in lua.h */ @@ -79,11 +79,23 @@ static int report (lua_State *L, int status) { } +static int traceback (lua_State *L) { + luaL_getfield(L, LUA_GLOBALSINDEX, "debug.traceback"); + if (!lua_isfunction(L, -1)) + lua_pop(L, 1); + else { + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ + } + return 1; +} + + static int docall (lua_State *L, int narg, int clear) { int status; int base = lua_gettop(L) - narg; /* function index */ - lua_pushliteral(L, "_TRACEBACK"); - lua_rawget(L, LUA_GLOBALSINDEX); /* get traceback function */ + lua_pushcfunction(L, traceback); /* push traceback function */ lua_insert(L, base); /* put it under chunk and args */ signal(SIGINT, laction); status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); @@ -359,7 +371,7 @@ static int pmain (lua_State *L) { int interactive = 1; if (s->argv[0] && s->argv[0][0]) progname = s->argv[0]; globalL = L; - lua_userinit(L); /* open libraries */ + luaopen_stdlibs(L); /* open libraries */ status = handle_luainit(L); if (status == 0) { status = handle_argv(L, s->argv, &interactive); @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.197 2004/12/13 12:15:11 roberto Exp $ +** $Id: lua.h,v 1.202 2005/02/18 12:40:02 roberto Exp $ ** Lua - An Extensible Extension Language ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil ** http://www.lua.org mailto:info@lua.org @@ -17,8 +17,9 @@ #include "luaconf.h" -#define LUA_VERSION "Lua 5.1 (work4)" -#define LUA_COPYRIGHT "Copyright (C) 1994-2004 Tecgraf, PUC-Rio" +#define LUA_VERSION "Lua 5.1 (work5)" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2005 Tecgraf, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" @@ -33,11 +34,12 @@ ** pseudo-indices */ #define LUA_REGISTRYINDEX (-10000) -#define LUA_GLOBALSINDEX (-10001) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) -/* return codes for `lua_pcall', `lua_resume', and `lua_threadstatus' */ +/* return codes for `lua_pcall', `lua_resume', and `lua_status' */ #define LUA_YIELD 1 #define LUA_ERRRUN 2 #define LUA_ERRSYNTAX 3 @@ -109,112 +111,112 @@ typedef LUA_INTEGER lua_Integer; /* ** state manipulation */ -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud); -LUA_API void lua_close (lua_State *L); -LUA_API lua_State *lua_newthread (lua_State *L); +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); -LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf); +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); /* ** basic stack manipulation */ -LUA_API int lua_gettop (lua_State *L); -LUA_API void lua_settop (lua_State *L, int idx); -LUA_API void lua_pushvalue (lua_State *L, int idx); -LUA_API void lua_remove (lua_State *L, int idx); -LUA_API void lua_insert (lua_State *L, int idx); -LUA_API void lua_replace (lua_State *L, int idx); -LUA_API int lua_checkstack (lua_State *L, int sz); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); -LUA_API void lua_xmove (lua_State *from, lua_State *to, int n); +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); /* ** access functions (stack -> C) */ -LUA_API int lua_isnumber (lua_State *L, int idx); -LUA_API int lua_isstring (lua_State *L, int idx); -LUA_API int lua_iscfunction (lua_State *L, int idx); -LUA_API int lua_isuserdata (lua_State *L, int idx); -LUA_API int lua_type (lua_State *L, int idx); -LUA_API const char *lua_typename (lua_State *L, int tp); +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); -LUA_API int lua_equal (lua_State *L, int idx1, int idx2); -LUA_API int lua_rawequal (lua_State *L, int idx1, int idx2); -LUA_API int lua_lessthan (lua_State *L, int idx1, int idx2); +LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); -LUA_API lua_Number lua_tonumber (lua_State *L, int idx); -LUA_API lua_Integer lua_tointeger (lua_State *L, int idx); -LUA_API int lua_toboolean (lua_State *L, int idx); -LUA_API const char *lua_tostring (lua_State *L, int idx); -LUA_API size_t lua_objsize (lua_State *L, int idx); -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx); -LUA_API void *lua_touserdata (lua_State *L, int idx); -LUA_API lua_State *lua_tothread (lua_State *L, int idx); -LUA_API const void *lua_topointer (lua_State *L, int idx); +LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tostring) (lua_State *L, int idx); +LUA_API size_t (lua_objsize) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); /* ** push functions (C -> stack) */ -LUA_API void lua_pushnil (lua_State *L); -LUA_API void lua_pushnumber (lua_State *L, lua_Number n); -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n); -LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t l); -LUA_API void lua_pushstring (lua_State *L, const char *s); -LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, - va_list argp); -LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...); -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); -LUA_API void lua_pushboolean (lua_State *L, int b); -LUA_API void lua_pushlightuserdata (lua_State *L, void *p); -LUA_API int lua_pushthread (lua_State *L); +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); /* ** get functions (Lua -> stack) */ -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_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); -LUA_API void lua_getfenv (lua_State *L, int idx); +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_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); +LUA_API void (lua_getfenv) (lua_State *L, int idx); /* ** set functions (stack -> Lua) */ -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 int lua_setmetatable (lua_State *L, int objindex); -LUA_API int lua_setfenv (lua_State *L, int idx); +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 int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setfenv) (lua_State *L, int idx); /* ** `load' and `call' functions (load and run Lua code) */ -LUA_API void lua_call (lua_State *L, int nargs, int nresults); -LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc); -LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud); -LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *dt, - const char *chunkname); +LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API int (lua_load) (lua_State *L, lua_Chunkreader reader, void *dt, + const char *chunkname); -LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data); +LUA_API int (lua_dump) (lua_State *L, lua_Chunkwriter writer, void *data); /* ** coroutine functions */ -LUA_API int lua_yield (lua_State *L, int nresults); -LUA_API int lua_resume (lua_State *L, int narg); -LUA_API int lua_threadstatus (lua_State *L); +LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_status) (lua_State *L); /* ** garbage-collection function and options @@ -226,24 +228,22 @@ LUA_API int lua_threadstatus (lua_State *L); #define LUA_GCCOUNT 3 #define LUA_GCSTEP 4 #define LUA_GCSETPACE 5 -#define LUA_GCSETINCMODE 6 +#define LUA_GCSETSTEPMUL 6 -LUA_API int lua_gc (lua_State *L, int what, int data); +LUA_API int (lua_gc) (lua_State *L, int what, int data); /* ** miscellaneous functions */ -LUA_API const char *lua_version (void); +LUA_API int (lua_error) (lua_State *L); -LUA_API int lua_error (lua_State *L); +LUA_API int (lua_next) (lua_State *L, int idx); -LUA_API int lua_next (lua_State *L, int idx); +LUA_API void (lua_concat) (lua_State *L, int n); -LUA_API void lua_concat (lua_State *L, int n); - -LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud); +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); diff --git a/src/luaconf.h b/src/luaconf.h index 7ea477e2..04b8e990 100644 --- a/src/luaconf.h +++ b/src/luaconf.h @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.22 2004/12/27 15:58:15 roberto Exp $ +** $Id: luaconf.h,v 1.30 2005/02/28 15:59:11 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -96,7 +96,7 @@ #define stdin_is_tty() isatty(0) #elif defined(_WIN32) #include <io.h> -#include <fcntl.h> +#include <stdio.h> #define stdin_is_tty() _isatty(_fileno(stdin)) #else #define stdin_is_tty() 1 /* assume stdin is a tty */ @@ -108,16 +108,6 @@ #define PROGNAME "lua" -/* -** this macro allows you to open other libraries when starting the -** stand-alone interpreter -*/ -#define lua_userinit(L) luaopen_stdlibs(L) -/* -** #define lua_userinit(L) { int luaopen_mylibs(lua_State *L); \ -** luaopen_stdlibs(L); luaopen_mylibs(L); } -*/ - /* @@ -217,8 +207,7 @@ #if defined(__GNUC__) && defined(__i386) #define lua_number2int(i,d) __asm__ ("fistpl %0":"=m"(i):"t"(d):"st") -#elif defined(_WIN32) && defined(_M_IX86) -#include <math.h> +#elif defined(_MSC_VER) && defined(_M_IX86) #pragma warning(disable: 4514) __inline int l_lrint (double flt) { int i; @@ -248,6 +237,8 @@ __inline int l_lrint (double flt) /* function to convert a lua_Number to a string */ #include <stdio.h> #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +/* maximum size of previous conversion */ +#define MAX_NUMBER2STR 32 /* 16 digits, sign, point and \0 (+ some extra) */ /* function to convert a string to a lua_Number */ #define lua_str2number(s,p) strtod((s), (p)) @@ -258,12 +249,29 @@ __inline int l_lrint (double flt) #define LUA_UACNUMBER double +/* primitive operators for numbers */ +#define num_add(a,b) ((a)+(b)) +#define num_sub(a,b) ((a)-(b)) +#define num_mul(a,b) ((a)*(b)) +#define num_div(a,b) ((a)/(b)) +#define num_unm(a) (-(a)) +#define num_eq(a,b) ((a)==(b)) +#define num_lt(a,b) ((a)<(b)) +#define num_le(a,b) ((a)<=(b)) +#include <math.h> +#define num_pow(a,b) pow(a,b) + + /* type to ensure maximum alignment */ #define LUSER_ALIGNMENT_T union { double u; void *s; long l; } -/* exception handling */ +/* +** exception handling: by default, Lua handles errors with longjmp/setjmp +** when compiling as C code and with exceptions when compiling as C++ code. +** Change that if you prefer to use longjmp/setjmp even with C++. +*/ #ifndef __cplusplus /* default handling with long jumps */ #include <setjmp.h> @@ -282,18 +290,20 @@ __inline int l_lrint (double flt) /* -** macros for thread synchronization inside Lua core machine: -** all accesses to the global state and to global objects are synchronized. -** Because threads can read the stack of other threads -** (when running garbage collection), -** a thread must also synchronize any write-access to its own stack. -** Unsynchronized accesses are allowed only when reading its own stack, -** or when reading immutable fields from global objects -** (such as string values and udata values). +** macros for thread synchronization inside Lua core machine: This is +** an attempt to simplify the implementation of a multithreaded version +** of Lua. Do not change that unless you know what you are doing. all +** accesses to the global state and to global objects are synchronized. +** Because threads can read the stack of other threads (when running +** garbage collection), a thread must also synchronize any write-access +** to its own stack. Unsynchronized accesses are allowed only when +** reading its own stack, or when reading immutable fields from global +** objects (such as string values and udata values). */ #define lua_lock(L) ((void) 0) #define lua_unlock(L) ((void) 0) + /* ** this macro allows a thread switch in appropriate places in the Lua ** core @@ -303,7 +313,7 @@ __inline int l_lrint (double flt) /* allows user-specific initialization on new threads */ -#define lua_userstateopen(L) /* empty */ +#define lua_userstateopen(L) ((void)0) #endif @@ -321,9 +331,6 @@ __inline int l_lrint (double flt) #ifdef LUA_LIB - -/* `assert' options */ - /* environment variables that hold the search path for packages */ #define LUA_PATH "LUA_PATH" #define LUA_CPATH "LUA_CPATH" @@ -332,7 +339,7 @@ __inline int l_lrint (double flt) #define LUA_POF "luaopen_" /* separator for open functions in C libraries */ -#define LUA_OFSEP "" +#define LUA_OFSEP "_" /* directory separator (for submodules) */ #if defined(_WIN32) @@ -342,18 +349,20 @@ __inline int l_lrint (double flt) #endif /* separator of templates in a path */ -#define LUA_PATH_SEP ';' +#define LUA_PATHSEP ';' /* wild char in each template */ #define LUA_PATH_MARK "?" -/* maximum number of captures in pattern-matching */ -#define MAX_CAPTURES 32 /* arbitrary limit */ +/* maximum number of captures in pattern-matching (arbitrary limit) */ +#define MAX_CAPTURES 32 /* -** by default, gcc does not get `tmpname' +** by default, gcc does not get `os.tmpname', because it generates a warning +** when using `tmpname'. Change that if you really want (or do not want) +** `os.tmpname' available. */ #ifdef __GNUC__ #define USE_TMPNAME 0 @@ -363,7 +372,11 @@ __inline int l_lrint (double flt) /* -** Configuration for loadlib +** Configuration for loadlib: Lua tries to guess the dynamic-library +** system that your platform uses (either Windows' DLL, Mac's dyld, or +** dlopen). If your system is some kind of Unix, there is a good chance +** that USE_DLOPEN will work for it. You may need to adapt also the +** makefile. */ #if defined(_WIN32) #define USE_DLL diff --git a/src/lualib.h b/src/lualib.h index c8114ed2..a5dde236 100644 --- a/src/lualib.h +++ b/src/lualib.h @@ -1,5 +1,5 @@ /* -** $Id: lualib.h,v 1.32 2004/07/09 15:47:48 roberto Exp $ +** $Id: lualib.h,v 1.33 2005/01/10 16:31:30 roberto Exp $ ** Lua standard libraries ** See Copyright Notice in lua.h */ @@ -16,32 +16,32 @@ #define LUA_COLIBNAME "coroutine" -LUALIB_API int luaopen_base (lua_State *L); +LUALIB_API int (luaopen_base) (lua_State *L); #define LUA_TABLIBNAME "table" -LUALIB_API int luaopen_table (lua_State *L); +LUALIB_API int (luaopen_table) (lua_State *L); #define LUA_IOLIBNAME "io" -LUALIB_API int luaopen_io (lua_State *L); +LUALIB_API int (luaopen_io) (lua_State *L); #define LUA_OSLIBNAME "os" -LUALIB_API int luaopen_os (lua_State *L); +LUALIB_API int (luaopen_os) (lua_State *L); #define LUA_STRLIBNAME "string" -LUALIB_API int luaopen_string (lua_State *L); +LUALIB_API int (luaopen_string) (lua_State *L); #define LUA_MATHLIBNAME "math" -LUALIB_API int luaopen_math (lua_State *L); +LUALIB_API int (luaopen_math) (lua_State *L); #define LUA_DBLIBNAME "debug" -LUALIB_API int luaopen_debug (lua_State *L); +LUALIB_API int (luaopen_debug) (lua_State *L); -LUALIB_API int luaopen_loadlib (lua_State *L); +LUALIB_API int (luaopen_loadlib) (lua_State *L); /* open all previous libraries */ -LUALIB_API int luaopen_stdlibs (lua_State *L); +LUALIB_API int (luaopen_stdlibs) (lua_State *L); #endif @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.18 2004/12/03 20:35:33 roberto Exp $ +** $Id: lvm.c,v 2.26 2005/02/23 17:30:22 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -47,7 +47,7 @@ int luaV_tostring (lua_State *L, StkId obj) { if (!ttisnumber(obj)) return 0; else { - char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */ + char s[MAX_NUMBER2STR]; lua_number2str(s, nvalue(obj)); setsvalue2s(L, obj, luaS_new(L, s)); return 1; @@ -113,7 +113,7 @@ StkId luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val, const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ Table *h = hvalue(t); - const TValue *res = luaH_get(h, key); /* do a primitive set */ + const TValue *res = luaH_get(h, key); /* do a primitive get */ if (!ttisnil(res) || /* result is no nil? */ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ setobj2s(L, val, res); @@ -241,7 +241,7 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { if (ttype(l) != ttype(r)) return luaG_ordererror(L, l, r); else if (ttisnumber(l)) - return nvalue(l) < nvalue(r); + return num_lt(nvalue(l), nvalue(r)); else if (ttisstring(l)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) @@ -255,7 +255,7 @@ static int lessequal (lua_State *L, const TValue *l, const TValue *r) { if (ttype(l) != ttype(r)) return luaG_ordererror(L, l, r); else if (ttisnumber(l)) - return nvalue(l) <= nvalue(r); + return num_le(nvalue(l), nvalue(r)); else if (ttisstring(l)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ @@ -271,7 +271,7 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { lua_assert(ttype(t1) == ttype(t2)); switch (ttype(t1)) { case LUA_TNIL: return 1; - case LUA_TNUMBER: return nvalue(t1) == nvalue(t2); + case LUA_TNUMBER: return num_eq(nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); case LUA_TUSERDATA: { @@ -335,18 +335,11 @@ static StkId Arith (lua_State *L, StkId ra, const TValue *rb, if ((b = luaV_tonumber(rb, &tempb)) != NULL && (c = luaV_tonumber(rc, &tempc)) != NULL) { switch (op) { - case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break; - case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break; - case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break; - case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break; - case TM_POW: { - const TValue *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]); - if (!ttisfunction(f)) - luaG_runerror(L, "`__pow' (`^' operator) is not a function"); - prepTMcall(L, f, b, c); - callTMres(L, ra); - break; - } + case TM_ADD: setnvalue(ra, num_add(nvalue(b), nvalue(c))); break; + case TM_SUB: setnvalue(ra, num_sub(nvalue(b), nvalue(c))); break; + case TM_MUL: setnvalue(ra, num_mul(nvalue(b), nvalue(c))); break; + case TM_DIV: setnvalue(ra, num_div(nvalue(b), nvalue(c))); break; + case TM_POW: setnvalue(ra, num_pow(nvalue(b), nvalue(c))); break; default: lua_assert(0); break; } } @@ -435,9 +428,11 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { continue; } case OP_GETGLOBAL: { + TValue g; TValue *rb = KBx(i); - lua_assert(ttisstring(rb) && ttistable(&cl->g)); - base = luaV_gettable(L, &cl->g, rb, ra, pc); /***/ + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(rb)); + base = luaV_gettable(L, &g, rb, ra, pc); /***/ continue; } case OP_GETTABLE: { @@ -445,8 +440,10 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { continue; } case OP_SETGLOBAL: { - lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g)); - base = luaV_settable(L, &cl->g, KBx(i), ra, pc); /***/ + TValue g; + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(KBx(i))); + base = luaV_settable(L, &g, KBx(i), ra, pc); /***/ continue; } case OP_SETUPVAL: { @@ -461,8 +458,8 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { } case OP_NEWTABLE: { int b = GETARG_B(i); - b = luaO_fb2int(b); - sethvalue(L, ra, luaH_new(L, b, GETARG_C(i))); + int c = GETARG_C(i); + sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); L->ci->savedpc = pc; luaC_checkGC(L); /***/ base = L->base; @@ -478,7 +475,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rb = RKB(i); TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { - setnvalue(ra, nvalue(rb) + nvalue(rc)); + setnvalue(ra, num_add(nvalue(rb), nvalue(rc))); } else base = Arith(L, ra, rb, rc, TM_ADD, pc); /***/ @@ -488,7 +485,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rb = RKB(i); TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { - setnvalue(ra, nvalue(rb) - nvalue(rc)); + setnvalue(ra, num_sub(nvalue(rb), nvalue(rc))); } else base = Arith(L, ra, rb, rc, TM_SUB, pc); /***/ @@ -498,7 +495,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rb = RKB(i); TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { - setnvalue(ra, nvalue(rb) * nvalue(rc)); + setnvalue(ra, num_mul(nvalue(rb), nvalue(rc))); } else base = Arith(L, ra, rb, rc, TM_MUL, pc); /***/ @@ -508,21 +505,27 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { TValue *rb = RKB(i); TValue *rc = RKC(i); if (ttisnumber(rb) && ttisnumber(rc)) { - setnvalue(ra, nvalue(rb) / nvalue(rc)); + setnvalue(ra, num_div(nvalue(rb), nvalue(rc))); } else base = Arith(L, ra, rb, rc, TM_DIV, pc); /***/ continue; } case OP_POW: { - base = Arith(L, ra, RKB(i), RKC(i), TM_POW, pc); /***/ + TValue *rb = RKB(i); + TValue *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + setnvalue(ra, num_pow(nvalue(rb), nvalue(rc))); + } + else + base = Arith(L, ra, rb, rc, TM_POW, pc); /***/ continue; } case OP_UNM: { const TValue *rb = RB(i); TValue temp; if (tonumber(rb, &temp)) { - setnvalue(ra, -nvalue(rb)); + setnvalue(ra, num_unm(nvalue(rb))); } else { setnilvalue(&temp); @@ -617,9 +620,9 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { int aux; StkId func = ci->func; StkId pfunc = (ci+1)->func; /* previous function index */ + if (L->openupval) luaF_close(L, base); base = ci->base = ci->func + ((ci+1)->base - pfunc); L->base = base; - if (L->openupval) luaF_close(L, base); for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ setobjs2s(L, func+aux, pfunc+aux); ci->top = L->top = func+aux; /* correct top */ @@ -658,9 +661,9 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { } case OP_FORLOOP: { lua_Number step = nvalue(ra+2); - lua_Number idx = nvalue(ra) + step; /* increment index */ + lua_Number idx = num_add(nvalue(ra), step); /* increment index */ lua_Number limit = nvalue(ra+1); - if (step > 0 ? idx <= limit : idx >= limit) { + if (step > 0 ? num_le(idx, limit) : num_le(limit, idx)) { dojump(L, pc, GETARG_sBx(i)); /* jump back */ setnvalue(ra, idx); /* update internal index... */ setnvalue(ra+3, idx); /* ...and external index */ @@ -678,7 +681,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { luaG_runerror(L, "`for' limit must be a number"); else if (!tonumber(pstep, ra+2)) luaG_runerror(L, "`for' step must be a number"); - setnvalue(ra, nvalue(ra) - nvalue(pstep)); + setnvalue(ra, num_sub(nvalue(ra), nvalue(pstep))); dojump(L, pc, GETARG_sBx(i)); continue; } @@ -723,7 +726,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { if (c == 0) c = cast(int, *pc++); last = ((c-1)*LFIELDS_PER_FLUSH) + n + LUA_FIRSTINDEX - 1; if (last > h->sizearray) /* needs more space? */ - luaH_resize(L, h, last, h->lsizenode); /* pre-alloc it at once */ + luaH_resizearray(L, h, last); /* pre-alloc it at once */ for (; n > 0; n--) { TValue *val = ra+n; setobj2t(L, luaH_setnum(L, h, last--), val); @@ -741,7 +744,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { int nup, j; p = cl->p->p[GETARG_Bx(i)]; nup = p->nups; - ncl = luaF_newLclosure(L, nup, &cl->g); + ncl = luaF_newLclosure(L, nup, cl->env); ncl->l.p = p; for (j=0; j<nup; j++, pc++) { if (GET_OPCODE(*pc) == OP_GETUPVAL) |