summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2004-03-24 12:00:00 +0000
committerrepogen <>2004-03-24 12:00:00 +0000
commitced7bbbe7a257ce6de94069d5dbf6672aeafd4d9 (patch)
tree2a01a79e6a4f451dccd247c70310ad957204cefa /src
parente7731a8fb8a317aa5c444ef073bfad82fa5baa54 (diff)
downloadlua-github-ced7bbbe7a257ce6de94069d5dbf6672aeafd4d9.tar.gz
Lua 5.1-work05.1-work0
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
l---------src/RCS1
-rw-r--r--src/lapi.c430
-rw-r--r--src/lapi.h4
-rw-r--r--src/lcode.c52
-rw-r--r--src/ldebug.c113
-rw-r--r--src/ldebug.h9
-rw-r--r--src/ldo.c141
-rw-r--r--src/ldo.h8
-rw-r--r--src/ldump.c22
-rw-r--r--src/lfunc.c66
-rw-r--r--src/lfunc.h12
-rw-r--r--src/lgc.c669
-rw-r--r--src/lgc.h81
l---------src/lib/RCS1
-rw-r--r--src/lib/lauxlib.c125
-rw-r--r--src/lib/lbaselib.c139
-rw-r--r--src/lib/ldblib.c150
-rw-r--r--src/lib/liolib.c130
-rw-r--r--src/lib/lmathlib.c14
-rw-r--r--src/lib/loadlib.c26
-rw-r--r--src/lib/lstrlib.c54
-rw-r--r--src/lib/ltablib.c6
-rw-r--r--src/llex.c449
-rw-r--r--src/llex.h6
-rw-r--r--src/llimits.h65
-rw-r--r--src/lmem.c82
-rw-r--r--src/lobject.c48
-rw-r--r--src/lobject.h122
-rw-r--r--src/lopcodes.c87
-rw-r--r--src/lopcodes.h45
-rw-r--r--src/lparser.c254
-rw-r--r--src/lparser.h16
-rw-r--r--src/lstate.c171
-rw-r--r--src/lstate.h64
-rw-r--r--src/lstring.c37
-rw-r--r--src/lstring.h6
-rw-r--r--src/ltable.c109
-rw-r--r--src/ltable.h15
-rw-r--r--src/ltm.c22
-rw-r--r--src/ltm.h10
l---------src/lua/RCS1
-rw-r--r--src/lua/README2
-rw-r--r--src/lua/lua.c13
-rw-r--r--src/luac/Makefile8
l---------src/luac/RCS1
-rw-r--r--src/luac/README2
-rw-r--r--src/luac/luac.c77
-rw-r--r--src/luac/print.c39
-rw-r--r--src/lundump.c89
-rw-r--r--src/lundump.h11
-rw-r--r--src/lvm.c488
-rw-r--r--src/lvm.h15
-rw-r--r--src/lzio.c16
-rw-r--r--src/lzio.h18
55 files changed, 2561 insertions, 2082 deletions
diff --git a/src/Makefile b/src/Makefile
index bf64c03f..7812b918 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -20,7 +20,6 @@ OBJS= \
lstate.o \
lstring.o \
ltable.o \
- ltests.o \
ltm.o \
lundump.o \
lvm.o \
@@ -42,7 +41,6 @@ SRCS= \
lstate.c \
lstring.c \
ltable.c \
- ltests.c \
ltm.c \
lundump.c \
lvm.c \
diff --git a/src/RCS b/src/RCS
new file mode 120000
index 00000000..1ae38936
--- /dev/null
+++ b/src/RCS
@@ -0,0 +1 @@
+../RCS \ No newline at end of file
diff --git a/src/lapi.c b/src/lapi.c
index d5dd9ca4..1b086a0b 100644
--- a/src/lapi.c
+++ b/src/lapi.c
@@ -1,11 +1,12 @@
/*
-** $Id: lapi.c,v 1.235 2003/04/07 14:36:08 roberto Exp $
+** $Id: lapi.c,v 2.5 2004/03/23 17:07:34 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
#include <assert.h>
+#include <stdarg.h>
#include <string.h>
#define lapi_c
@@ -27,6 +28,12 @@
#include "lvm.h"
+/* function to convert a lua_Number to lua_Integer (with any rounding method) */
+#ifndef lua_number2integer
+#define lua_number2integer(i,n) ((i)=(lua_Integer)(n))
+#endif
+
+
const char lua_ident[] =
"$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
"$Authors: " LUA_AUTHORS " $\n"
@@ -35,63 +42,44 @@ const char lua_ident[] =
#ifndef api_check
-#define api_check(L, o) /*{ assert(o); }*/
+#define api_check(L, o) lua_assert(o)
#endif
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
-#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
+#define api_checkvalidindex(L, i) api_check(L, (i) != &luaO_nilobject)
+#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
-static TObject *negindex (lua_State *L, int idx) {
- if (idx > LUA_REGISTRYINDEX) {
+static TValue *luaA_index (lua_State *L, int idx) {
+ if (idx > 0) {
+ TValue *o = L->base + (idx - 1);
+ api_check(L, idx <= L->stack_last - L->base);
+ if (o >= L->top) return cast(TValue *, &luaO_nilobject);
+ else return o;
+ }
+ else if (idx > LUA_REGISTRYINDEX) {
api_check(L, idx != 0 && -idx <= L->top - L->base);
- return L->top+idx;
+ return L->top + idx;
}
else switch (idx) { /* pseudo-indices */
case LUA_REGISTRYINDEX: return registry(L);
case LUA_GLOBALSINDEX: return gt(L);
default: {
- TObject *func = (L->base - 1);
+ Closure *func = curr_func(L);
idx = LUA_GLOBALSINDEX - idx;
- lua_assert(iscfunction(func));
- return (idx <= clvalue(func)->c.nupvalues)
- ? &clvalue(func)->c.upvalue[idx-1]
- : NULL;
+ return (idx <= func->c.nupvalues)
+ ? &func->c.upvalue[idx-1]
+ : cast(TValue *, &luaO_nilobject);
}
}
}
-static TObject *luaA_index (lua_State *L, int idx) {
- if (idx > 0) {
- api_check(L, idx <= L->top - L->base);
- return L->base + idx - 1;
- }
- else {
- TObject *o = negindex(L, idx);
- api_check(L, o != NULL);
- return o;
- }
-}
-
-
-static TObject *luaA_indexAcceptable (lua_State *L, int idx) {
- if (idx > 0) {
- TObject *o = L->base+(idx-1);
- api_check(L, idx <= L->stack_last - L->base);
- if (o >= L->top) return NULL;
- else return o;
- }
- else
- return negindex(L, idx);
-}
-
-
-void luaA_pushobject (lua_State *L, const TObject *o) {
- setobj2s(L->top, o);
+void luaA_pushobject (lua_State *L, const TValue *o) {
+ setobj2s(L, L->top, o);
incr_top(L);
}
@@ -114,11 +102,12 @@ LUA_API int lua_checkstack (lua_State *L, int size) {
LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
int i;
+ if (from == to) return;
lua_lock(to);
api_checknelems(from, n);
from->top -= n;
for (i = 0; i < n; i++) {
- setobj2s(to->top, from->top + i);
+ setobj2s(to, to->top, from->top + i);
api_incr_top(to);
}
lua_unlock(to);
@@ -140,7 +129,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
lua_lock(L);
luaC_checkGC(L);
L1 = luaE_newthread(L);
- setthvalue(L->top, L1);
+ setthvalue(L, L->top, L1);
api_incr_top(L);
lua_unlock(L);
lua_userstateopen(L1);
@@ -179,7 +168,8 @@ LUA_API void lua_remove (lua_State *L, int idx) {
StkId p;
lua_lock(L);
p = luaA_index(L, idx);
- while (++p < L->top) setobjs2s(p-1, p);
+ api_checkvalidindex(L, p);
+ while (++p < L->top) setobjs2s(L, p-1, p);
L->top--;
lua_unlock(L);
}
@@ -190,16 +180,22 @@ LUA_API void lua_insert (lua_State *L, int idx) {
StkId q;
lua_lock(L);
p = luaA_index(L, idx);
- for (q = L->top; q>p; q--) setobjs2s(q, q-1);
- setobjs2s(p, L->top);
+ api_checkvalidindex(L, p);
+ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);
+ setobjs2s(L, p, L->top);
lua_unlock(L);
}
LUA_API void lua_replace (lua_State *L, int idx) {
+ StkId o;
lua_lock(L);
api_checknelems(L, 1);
- setobj(luaA_index(L, idx), L->top - 1); /* write barrier */
+ o = luaA_index(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);
L->top--;
lua_unlock(L);
}
@@ -207,7 +203,7 @@ LUA_API void lua_replace (lua_State *L, int idx) {
LUA_API void lua_pushvalue (lua_State *L, int idx) {
lua_lock(L);
- setobj2s(L->top, luaA_index(L, idx));
+ setobj2s(L, L->top, luaA_index(L, idx));
api_incr_top(L);
lua_unlock(L);
}
@@ -220,8 +216,8 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) {
LUA_API int lua_type (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- return (o == NULL) ? LUA_TNONE : ttype(o);
+ StkId o = luaA_index(L, idx);
+ return (o == &luaO_nilobject) ? LUA_TNONE : ttype(o);
}
@@ -232,15 +228,15 @@ LUA_API const char *lua_typename (lua_State *L, int t) {
LUA_API int lua_iscfunction (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- return (o == NULL) ? 0 : iscfunction(o);
+ StkId o = luaA_index(L, idx);
+ return iscfunction(o);
}
LUA_API int lua_isnumber (lua_State *L, int idx) {
- TObject n;
- const TObject *o = luaA_indexAcceptable(L, idx);
- return (o != NULL && tonumber(o, &n));
+ TValue n;
+ const TValue *o = luaA_index(L, idx);
+ return tonumber(o, &n);
}
@@ -251,16 +247,16 @@ LUA_API int lua_isstring (lua_State *L, int idx) {
LUA_API int lua_isuserdata (lua_State *L, int idx) {
- const TObject *o = luaA_indexAcceptable(L, idx);
- return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o)));
+ const TValue *o = luaA_index(L, idx);
+ return (ttisuserdata(o) || ttislightuserdata(o));
}
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
- StkId o1 = luaA_indexAcceptable(L, index1);
- StkId o2 = luaA_indexAcceptable(L, index2);
- return (o1 == NULL || o2 == NULL) ? 0 /* index out of range */
- : luaO_rawequalObj(o1, o2);
+ StkId o1 = luaA_index(L, index1);
+ StkId o2 = luaA_index(L, index2);
+ return (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0
+ : luaO_rawequalObj(o1, o2);
}
@@ -268,10 +264,10 @@ LUA_API int lua_equal (lua_State *L, int index1, int index2) {
StkId o1, o2;
int i;
lua_lock(L); /* may call tag method */
- o1 = luaA_indexAcceptable(L, index1);
- o2 = luaA_indexAcceptable(L, index2);
- i = (o1 == NULL || o2 == NULL) ? 0 /* index out of range */
- : equalobj(L, o1, o2);
+ o1 = luaA_index(L, index1);
+ o2 = luaA_index(L, index2);
+ i = (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0
+ : equalobj(L, o1, o2);
lua_unlock(L);
return i;
}
@@ -281,10 +277,10 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
StkId o1, o2;
int i;
lua_lock(L); /* may call tag method */
- o1 = luaA_indexAcceptable(L, index1);
- o2 = luaA_indexAcceptable(L, index2);
- i = (o1 == NULL || o2 == NULL) ? 0 /* index out-of-range */
- : luaV_lessthan(L, o1, o2);
+ o1 = luaA_index(L, index1);
+ o2 = luaA_index(L, index2);
+ i = (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0
+ : luaV_lessthan(L, o1, o2);
lua_unlock(L);
return i;
}
@@ -292,26 +288,37 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
- TObject n;
- const TObject *o = luaA_indexAcceptable(L, idx);
- if (o != NULL && tonumber(o, &n))
+ TValue n;
+ const TValue *o = luaA_index(L, idx);
+ if (tonumber(o, &n))
return nvalue(o);
else
return 0;
}
+LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = luaA_index(L, idx);
+ if (tonumber(o, &n)) {
+ lua_Integer res;
+ lua_number2integer(res, nvalue(o));
+ return res;
+ }
+ else
+ return 0;
+}
+
+
LUA_API int lua_toboolean (lua_State *L, int idx) {
- const TObject *o = luaA_indexAcceptable(L, idx);
- return (o != NULL) && !l_isfalse(o);
+ const TValue *o = luaA_index(L, idx);
+ return !l_isfalse(o);
}
LUA_API const char *lua_tostring (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- if (o == NULL)
- return NULL;
- else if (ttisstring(o))
+ StkId o = luaA_index(L, idx);
+ if (ttisstring(o))
return svalue(o);
else {
const char *s;
@@ -325,15 +332,13 @@ LUA_API const char *lua_tostring (lua_State *L, int idx) {
LUA_API size_t lua_strlen (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- if (o == NULL)
- return 0;
- else if (ttisstring(o))
- return tsvalue(o)->tsv.len;
+ StkId o = luaA_index(L, idx);
+ if (ttisstring(o))
+ return tsvalue(o)->len;
else {
size_t l;
lua_lock(L); /* `luaV_tostring' may create a new string */
- l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0);
+ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);
lua_unlock(L);
return l;
}
@@ -341,16 +346,15 @@ LUA_API size_t lua_strlen (lua_State *L, int idx) {
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f;
+ StkId o = luaA_index(L, idx);
+ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;
}
LUA_API void *lua_touserdata (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- if (o == NULL) return NULL;
+ StkId o = luaA_index(L, idx);
switch (ttype(o)) {
- case LUA_TUSERDATA: return (uvalue(o) + 1);
+ case LUA_TUSERDATA: return (rawuvalue(o) + 1);
case LUA_TLIGHTUSERDATA: return pvalue(o);
default: return NULL;
}
@@ -358,24 +362,21 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) {
LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
+ StkId o = luaA_index(L, idx);
+ return (!ttisthread(o)) ? NULL : thvalue(o);
}
LUA_API const void *lua_topointer (lua_State *L, int idx) {
- StkId o = luaA_indexAcceptable(L, idx);
- if (o == NULL) return NULL;
- else {
- switch (ttype(o)) {
- case LUA_TTABLE: return hvalue(o);
- case LUA_TFUNCTION: return clvalue(o);
- case LUA_TTHREAD: return thvalue(o);
- case LUA_TUSERDATA:
- case LUA_TLIGHTUSERDATA:
- return lua_touserdata(L, idx);
- default: return NULL;
- }
+ StkId o = luaA_index(L, idx);
+ switch (ttype(o)) {
+ case LUA_TTABLE: return hvalue(o);
+ case LUA_TFUNCTION: return clvalue(o);
+ case LUA_TTHREAD: return thvalue(o);
+ case LUA_TUSERDATA:
+ case LUA_TLIGHTUSERDATA:
+ return lua_touserdata(L, idx);
+ default: return NULL;
}
}
@@ -402,10 +403,18 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
}
+LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
+ lua_lock(L);
+ setnvalue(L->top, cast(lua_Number, n));
+ api_incr_top(L);
+ lua_unlock(L);
+}
+
+
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
lua_lock(L);
luaC_checkGC(L);
- setsvalue2s(L->top, luaS_newlstr(L, s, len));
+ setsvalue2s(L, L->top, luaS_newlstr(L, s, len));
api_incr_top(L);
lua_unlock(L);
}
@@ -452,8 +461,9 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
cl->c.f = fn;
L->top -= n;
while (n--)
- setobj2n(&cl->c.upvalue[n], L->top+n);
- setclvalue(L->top, cl);
+ setobj2n(L, &cl->c.upvalue[n], L->top+n);
+ setclvalue(L, L->top, cl);
+ lua_assert(iswhite(obj2gco(cl)));
api_incr_top(L);
lua_unlock(L);
}
@@ -485,7 +495,21 @@ LUA_API void lua_gettable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = luaA_index(L, idx);
- setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0));
+ api_checkvalidindex(L, t);
+ luaV_gettable(L, t, L->top - 1, L->top - 1);
+ lua_unlock(L);
+}
+
+
+LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ t = luaA_index(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_gettable(L, t, &key, L->top);
+ api_incr_top(L);
lua_unlock(L);
}
@@ -495,7 +519,7 @@ LUA_API void lua_rawget (lua_State *L, int idx) {
lua_lock(L);
t = luaA_index(L, idx);
api_check(L, ttistable(t));
- setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1));
+ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
lua_unlock(L);
}
@@ -505,41 +529,39 @@ LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
lua_lock(L);
o = luaA_index(L, idx);
api_check(L, ttistable(o));
- setobj2s(L->top, luaH_getnum(hvalue(o), n));
+ setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
api_incr_top(L);
lua_unlock(L);
}
-LUA_API void lua_newtable (lua_State *L) {
+LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
lua_lock(L);
luaC_checkGC(L);
- sethvalue(L->top, luaH_new(L, 0, 0));
+ sethvalue(L, L->top, luaH_new(L, narray, luaO_log2(nrec) + 1));
api_incr_top(L);
lua_unlock(L);
}
LUA_API int lua_getmetatable (lua_State *L, int objindex) {
- const TObject *obj;
+ const TValue *obj;
Table *mt = NULL;
int res;
lua_lock(L);
- obj = luaA_indexAcceptable(L, objindex);
- if (obj != NULL) {
- switch (ttype(obj)) {
- case LUA_TTABLE:
- mt = hvalue(obj)->metatable;
- break;
- case LUA_TUSERDATA:
- mt = uvalue(obj)->uv.metatable;
- break;
- }
+ obj = luaA_index(L, objindex);
+ switch (ttype(obj)) {
+ case LUA_TTABLE:
+ mt = hvalue(obj)->metatable;
+ break;
+ case LUA_TUSERDATA:
+ mt = uvalue(obj)->metatable;
+ break;
}
- if (mt == NULL || mt == hvalue(defaultmeta(L)))
+ if (mt == NULL)
res = 0;
else {
- sethvalue(L->top, mt);
+ sethvalue(L, L->top, mt);
api_incr_top(L);
res = 1;
}
@@ -552,7 +574,8 @@ LUA_API void lua_getfenv (lua_State *L, int idx) {
StkId o;
lua_lock(L);
o = luaA_index(L, idx);
- setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
+ api_checkvalidindex(L, o);
+ setobj2s(L, L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
api_incr_top(L);
lua_unlock(L);
}
@@ -568,19 +591,35 @@ LUA_API void lua_settable (lua_State *L, int idx) {
lua_lock(L);
api_checknelems(L, 2);
t = luaA_index(L, idx);
+ api_checkvalidindex(L, t);
luaV_settable(L, t, L->top - 2, L->top - 1);
L->top -= 2; /* pop index and value */
lua_unlock(L);
}
+LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
+ StkId t;
+ TValue key;
+ lua_lock(L);
+ api_checknelems(L, 1);
+ t = luaA_index(L, idx);
+ api_checkvalidindex(L, t);
+ setsvalue(L, &key, luaS_new(L, k));
+ luaV_settable(L, t, &key, L->top - 1);
+ L->top--; /* pop value */
+ lua_unlock(L);
+}
+
+
LUA_API void lua_rawset (lua_State *L, int idx) {
StkId t;
lua_lock(L);
api_checknelems(L, 2);
t = luaA_index(L, idx);
api_check(L, ttistable(t));
- setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */
+ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
+ luaC_barrier(L, hvalue(t), L->top-1);
L->top -= 2;
lua_unlock(L);
}
@@ -592,27 +631,38 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
api_checknelems(L, 1);
o = luaA_index(L, idx);
api_check(L, ttistable(o));
- setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */
+ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
+ luaC_barrier(L, hvalue(o), L->top-1);
L->top--;
lua_unlock(L);
}
LUA_API int lua_setmetatable (lua_State *L, int objindex) {
- TObject *obj, *mt;
+ TValue *obj;
+ Table *mt;
int res = 1;
lua_lock(L);
api_checknelems(L, 1);
obj = luaA_index(L, objindex);
- mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L);
- api_check(L, ttistable(mt));
+ api_checkvalidindex(L, obj);
+ if (ttisnil(L->top - 1))
+ mt = NULL;
+ else {
+ api_check(L, ttistable(L->top - 1));
+ mt = hvalue(L->top - 1);
+ }
switch (ttype(obj)) {
case LUA_TTABLE: {
- hvalue(obj)->metatable = hvalue(mt); /* write barrier */
+ hvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarrier(L, hvalue(obj), mt);
break;
}
case LUA_TUSERDATA: {
- uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */
+ uvalue(obj)->metatable = mt;
+ if (mt)
+ luaC_objbarrier(L, rawuvalue(obj), mt);
break;
}
default: {
@@ -632,6 +682,7 @@ LUA_API int lua_setfenv (lua_State *L, int idx) {
lua_lock(L);
api_checknelems(L, 1);
o = luaA_index(L, idx);
+ api_checkvalidindex(L, o);
L->top--;
api_check(L, ttistable(L->top));
if (isLfunction(o)) {
@@ -679,7 +730,13 @@ LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
int status;
ptrdiff_t func;
lua_lock(L);
- func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
+ if (errfunc == 0)
+ func = 0;
+ else {
+ StkId o = luaA_index(L, errfunc);
+ api_checkvalidindex(L, o);
+ func = savestack(L, o);
+ }
c.func = L->top - (nargs+1); /* function to be called */
c.nresults = nresults;
status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
@@ -702,7 +759,7 @@ static void f_Ccall (lua_State *L, void *ud) {
Closure *cl;
cl = luaF_newCclosure(L, 0);
cl->c.f = c->func;
- setclvalue(L->top, cl); /* push function */
+ setclvalue(L, L->top, cl); /* push function */
incr_top(L);
setpvalue(L->top, c->ud); /* push only argument */
incr_top(L);
@@ -726,12 +783,10 @@ LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
const char *chunkname) {
ZIO z;
int status;
- int c;
lua_lock(L);
if (!chunkname) chunkname = "?";
- luaZ_init(&z, reader, data, chunkname);
- c = luaZ_lookahead(&z);
- status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0]));
+ luaZ_init(L, &z, reader, data);
+ status = luaD_protectedparser(L, &z, chunkname);
lua_unlock(L);
return status;
}
@@ -739,14 +794,12 @@ LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
int status;
- TObject *o;
+ TValue *o;
lua_lock(L);
api_checknelems(L, 1);
o = L->top - 1;
- if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) {
- luaU_dump(L, clvalue(o)->l.p, writer, data);
- status = 1;
- }
+ if (isLfunction(o))
+ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);
else
status = 0;
lua_unlock(L);
@@ -755,39 +808,34 @@ LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
/*
-** Garbage-collection functions
+** Garbage-collection function
*/
-/* GC values are expressed in Kbytes: #bytes/2^10 */
-#define GCscalel(x) ((x)>>10)
-#define GCscale(x) (cast(int, GCscalel(x)))
-#define GCunscale(x) (cast(lu_mem, x)<<10)
-
-LUA_API int lua_getgcthreshold (lua_State *L) {
- int threshold;
- lua_lock(L);
- threshold = GCscale(G(L)->GCthreshold);
- lua_unlock(L);
- return threshold;
+LUA_API int lua_gc (lua_State *L, int what, int data) {
+ global_State *g = G(L);
+ switch (what) {
+ case LUA_GCSTOP: {
+ g->GCthreshold = MAXLMEM;
+ return 0;
+ }
+ case LUA_GCRESTART: {
+ g->GCthreshold = g->nblocks;
+ return 0;
+ }
+ case LUA_GCCOLLECT: {
+ lua_lock(L);
+ luaC_fullgc(L);
+ lua_unlock(L);
+ return 0;
+ }
+ case LUA_GCCOUNT: {
+ /* GC values are expressed in Kbytes: #bytes/2^10 */
+ return cast(int, g->nblocks >> 10);
+ }
+ default: return -1; /* invalid option */
+ }
}
-LUA_API int lua_getgccount (lua_State *L) {
- int count;
- lua_lock(L);
- count = GCscale(G(L)->nblocks);
- lua_unlock(L);
- return count;
-}
-
-LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
- lua_lock(L);
- if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM))
- G(L)->GCthreshold = MAX_LUMEM;
- else
- G(L)->GCthreshold = GCunscale(newthreshold);
- luaC_checkGC(L);
- lua_unlock(L);
-}
/*
@@ -835,7 +883,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
L->top -= (n-1);
}
else if (n == 0) { /* push empty string */
- setsvalue2s(L->top, luaS_newlstr(L, NULL, 0));
+ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));
api_incr_top(L);
}
/* else n == 1; nothing to do */
@@ -843,39 +891,28 @@ 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;
+}
+
+
LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
Udata *u;
lua_lock(L);
luaC_checkGC(L);
u = luaS_newudata(L, size);
- setuvalue(L->top, u);
+ setuvalue(L, L->top, u);
api_incr_top(L);
lua_unlock(L);
return u + 1;
}
-LUA_API int lua_pushupvalues (lua_State *L) {
- Closure *func;
- int n, i;
- lua_lock(L);
- api_check(L, iscfunction(L->base - 1));
- func = clvalue(L->base - 1);
- n = func->c.nupvalues;
- luaD_checkstack(L, n + LUA_MINSTACK);
- for (i=0; i<n; i++) {
- setobj2s(L->top, &func->c.upvalue[i]);
- L->top++;
- }
- lua_unlock(L);
- return n;
-}
-static const char *aux_upvalue (lua_State *L, int funcindex, int n,
- TObject **val) {
+static const char *aux_upvalue (lua_State *L, StkId fi, int n, TValue **val) {
Closure *f;
- StkId fi = luaA_index(L, funcindex);
if (!ttisfunction(fi)) return NULL;
f = clvalue(fi);
if (f->c.isC) {
@@ -894,11 +931,11 @@ static const char *aux_upvalue (lua_State *L, int funcindex, int n,
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
const char *name;
- TObject *val;
+ TValue *val;
lua_lock(L);
- name = aux_upvalue(L, funcindex, n, &val);
+ name = aux_upvalue(L, luaA_index(L, funcindex), n, &val);
if (name) {
- setobj2s(L->top, val);
+ setobj2s(L, L->top, val);
api_incr_top(L);
}
lua_unlock(L);
@@ -908,13 +945,16 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
const char *name;
- TObject *val;
+ TValue *val;
+ StkId fi;
lua_lock(L);
+ fi = luaA_index(L, funcindex);
api_checknelems(L, 1);
- name = aux_upvalue(L, funcindex, n, &val);
+ name = aux_upvalue(L, fi, n, &val);
if (name) {
L->top--;
- setobj(val, L->top); /* write barrier */
+ setobj(L, val, L->top);
+ luaC_barrier(L, clvalue(fi), L->top);
}
lua_unlock(L);
return name;
diff --git a/src/lapi.h b/src/lapi.h
index d12612f3..0ff8beb6 100644
--- a/src/lapi.h
+++ b/src/lapi.h
@@ -1,5 +1,5 @@
/*
-** $Id: lapi.h,v 1.21 2002/03/04 21:29:41 roberto Exp $
+** $Id: lapi.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
@@ -11,6 +11,6 @@
#include "lobject.h"
-void luaA_pushobject (lua_State *L, const TObject *o);
+void luaA_pushobject (lua_State *L, const TValue *o);
#endif
diff --git a/src/lcode.c b/src/lcode.c
index d626ecd6..de6939bb 100644
--- a/src/lcode.c
+++ b/src/lcode.c
@@ -1,5 +1,5 @@
/*
-** $Id: lcode.c,v 1.117 2003/04/03 13:35:34 roberto Exp $
+** $Id: lcode.c,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -14,6 +14,7 @@
#include "lcode.h"
#include "ldebug.h"
#include "ldo.h"
+#include "lgc.h"
#include "llex.h"
#include "lmem.h"
#include "lobject.h"
@@ -88,7 +89,7 @@ static int luaK_getjump (FuncState *fs, int pc) {
static Instruction *getjumpcontrol (FuncState *fs, int pc) {
Instruction *pi = &fs->f->code[pc];
- if (pc >= 1 && testOpMode(GET_OPCODE(*(pi-1)), OpModeT))
+ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
return pi-1;
else
return pi;
@@ -206,41 +207,46 @@ static void freeexp (FuncState *fs, expdesc *e) {
}
-static int addk (FuncState *fs, TObject *k, TObject *v) {
- const TObject *idx = luaH_get(fs->h, k);
+static int addk (FuncState *fs, TValue *k, TValue *v) {
+ lua_State *L = fs->L;
+ TValue *idx = luaH_set(L, fs->h, k);
+ Proto *f = fs->f;
+ int oldsize = f->sizek;
if (ttisnumber(idx)) {
lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v));
return cast(int, nvalue(idx));
}
else { /* constant not found; create a new entry */
- Proto *f = fs->f;
- luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject,
+ setnvalue(idx, cast(lua_Number, fs->nk));
+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
MAXARG_Bx, "constant table overflow");
- setobj2n(&f->k[fs->nk], v);
- setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk));
+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
+ setobj(L, &f->k[fs->nk], v);
+ luaC_barrier(L, f, v);
return fs->nk++;
}
}
int luaK_stringK (FuncState *fs, TString *s) {
- TObject o;
- setsvalue(&o, s);
+ TValue o;
+ setsvalue(fs->L, &o, s);
return addk(fs, &o, &o);
}
int luaK_numberK (FuncState *fs, lua_Number r) {
- TObject o;
+ TValue o;
setnvalue(&o, r);
return addk(fs, &o, &o);
}
static int nil_constant (FuncState *fs) {
- TObject k, v;
+ TValue k, v;
setnilvalue(&v);
- sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */
+ /* cannot use nil as key; instead use table itself to represent nil */
+ sethvalue(fs->L, &k, fs->h);
return addk(fs, &k, &v);
}
@@ -416,25 +422,25 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
}
-void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
switch (var->k) {
case VLOCAL: {
- freeexp(fs, exp);
- luaK_exp2reg(fs, exp, var->info);
+ freeexp(fs, ex);
+ luaK_exp2reg(fs, ex, var->info);
return;
}
case VUPVAL: {
- int e = luaK_exp2anyreg(fs, exp);
+ int e = luaK_exp2anyreg(fs, ex);
luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0);
break;
}
case VGLOBAL: {
- int e = luaK_exp2anyreg(fs, exp);
+ int e = luaK_exp2anyreg(fs, ex);
luaK_codeABx(fs, OP_SETGLOBAL, e, var->info);
break;
}
case VINDEXED: {
- int e = luaK_exp2RK(fs, exp);
+ int e = luaK_exp2RK(fs, ex);
luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e);
break;
}
@@ -443,7 +449,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
break;
}
}
- freeexp(fs, exp);
+ freeexp(fs, ex);
}
@@ -462,8 +468,7 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
static void invertjump (FuncState *fs, expdesc *e) {
Instruction *pc = getjumpcontrol(fs, e->info);
- lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) &&
- GET_OPCODE(*pc) != OP_TEST);
+ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TEST);
SETARG_A(*pc, !(GETARG_A(*pc)));
}
@@ -703,12 +708,15 @@ int luaK_code (FuncState *fs, Instruction i, int line) {
int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
lua_assert(getOpMode(o) == iABC);
+ lua_assert(getBMode(o) != OpArgN || b == 0);
+ lua_assert(getCMode(o) != OpArgN || c == 0);
return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
}
int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
+ lua_assert(getCMode(o) == OpArgN);
return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
}
diff --git a/src/ldebug.c b/src/ldebug.c
index 8e511e3b..42080ccd 100644
--- a/src/ldebug.c
+++ b/src/ldebug.c
@@ -1,13 +1,15 @@
/*
-** $Id: ldebug.c,v 1.150 2003/03/19 21:24:04 roberto Exp $
+** $Id: ldebug.c,v 2.3 2004/03/23 13:10:16 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
-#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
#include <string.h>
+
#define ldebug_c
#include "lua.h"
@@ -30,14 +32,8 @@
static const char *getfuncname (CallInfo *ci, const char **name);
-#define isLua(ci) (!((ci)->state & CI_C))
-
-
static int currentpc (CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */
- if (ci->state & CI_HASFRAME) /* function has a frame? */
- ci->u.l.savedpc = *ci->u.l.pc; /* use `pc' from there */
- /* function's pc is saved */
return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
}
@@ -51,14 +47,6 @@ static int currentline (CallInfo *ci) {
}
-void luaG_inithooks (lua_State *L) {
- CallInfo *ci;
- for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */
- currentpc(ci);
- L->hookinit = 1;
-}
-
-
/*
** this function can be called asynchronous (e.g. during a signal)
*/
@@ -71,7 +59,6 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
L->basehookcount = count;
resethookcount(L);
L->hookmask = cast(lu_byte, mask);
- L->hookinit = 0;
return 1;
}
@@ -97,7 +84,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
lua_lock(L);
for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
level--;
- if (!(ci->state & CI_C)) /* Lua function? */
+ if (f_isLua(ci)) /* Lua function? */
level -= ci->u.l.tailcalls; /* skip lost tail calls */
}
if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */
@@ -151,7 +138,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
if (!name || name[0] == '(') /* `(' starts private locals */
name = NULL;
else
- setobjs2s(ci->base+(n-1), L->top);
+ setobjs2s(L, ci->base+(n-1), L->top);
}
lua_unlock(L);
return name;
@@ -174,18 +161,6 @@ static void funcinfo (lua_Debug *ar, StkId func) {
}
-static const char *travglobals (lua_State *L, const TObject *o) {
- Table *g = hvalue(gt(L));
- int i = sizenode(g);
- while (i--) {
- Node *n = gnode(g, i);
- if (luaO_rawequalObj(o, gval(n)) && ttisstring(gkey(n)))
- return getstr(tsvalue(gkey(n)));
- }
- return NULL;
-}
-
-
static void info_tailcall (lua_State *L, lua_Debug *ar) {
ar->name = ar->namewhat = "";
ar->what = "tail";
@@ -217,15 +192,13 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
case 'n': {
ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL;
if (ar->namewhat == NULL) {
- /* try to find a global name */
- if ((ar->name = travglobals(L, f)) != NULL)
- ar->namewhat = "global";
- else ar->namewhat = ""; /* not found */
+ ar->namewhat = ""; /* not found */
+ ar->name = NULL;
}
break;
}
case 'f': {
- setobj2s(L->top, f);
+ setobj2s(L, L->top, f);
break;
}
default: status = 0; /* invalid option */
@@ -296,8 +269,16 @@ static int checkopenop (const Proto *pt, int pc) {
}
-static int checkRK (const Proto *pt, int r) {
- return (r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek));
+static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
+ switch (mode) {
+ case OpArgN: check(r == 0); break;
+ case OpArgU: break;
+ case OpArgR: checkreg(pt, r); break;
+ case OpArgK:
+ check(r < pt->maxstacksize || (r >= MAXSTACK && r-MAXSTACK < pt->sizek));
+ break;
+ }
+ return 1;
}
@@ -312,34 +293,34 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
int a = GETARG_A(i);
int b = 0;
int c = 0;
+ check(op < NUM_OPCODES);
checkreg(pt, a);
switch (getOpMode(op)) {
case iABC: {
b = GETARG_B(i);
c = GETARG_C(i);
- if (testOpMode(op, OpModeBreg)) {
- checkreg(pt, b);
- }
- else if (testOpMode(op, OpModeBrk))
- check(checkRK(pt, b));
- if (testOpMode(op, OpModeCrk))
- check(checkRK(pt, c));
+ check(checkArgMode(pt, b, getBMode(op)));
+ check(checkArgMode(pt, c, getCMode(op)));
break;
}
case iABx: {
b = GETARG_Bx(i);
- if (testOpMode(op, OpModeK)) check(b < pt->sizek);
+ if (getBMode(op) == OpArgK) check(b < pt->sizek);
break;
}
case iAsBx: {
b = GETARG_sBx(i);
+ if (getBMode(op) == OpArgR) {
+ int dest = pc+1+b;
+ check(0 <= dest && dest < pt->sizecode);
+ }
break;
}
}
- if (testOpMode(op, OpModesetA)) {
+ if (testAMode(op)) {
if (a == reg) last = pc; /* change register `a' */
}
- if (testOpMode(op, OpModeT)) {
+ if (testTMode(op)) {
check(pc+2 < pt->sizecode); /* check skip */
check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
}
@@ -369,20 +350,21 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
break;
}
case OP_CONCAT: {
- /* `c' is a register, and at least two operands */
- check(c < MAXSTACK && b < c);
+ check(b < c); /* at least two operands */
break;
}
- case OP_TFORLOOP:
- checkreg(pt, a+c+5);
+ case OP_TFORLOOP: {
+ checkreg(pt, a+5); /* space for control variables */
if (reg >= a) last = pc; /* affect all registers above base */
- /* go through */
+ break;
+ }
+ case OP_TFORPREP:
case OP_FORLOOP:
- checkreg(pt, a+2);
+ case OP_FORPREP:
+ checkreg(pt, a+3);
/* go through */
case OP_JMP: {
int dest = pc+1+b;
- check(0 <= dest && dest < pt->sizecode);
/* not full check and jump is forward and do not skip `lastpc'? */
if (reg != NO_REG && pc < dest && dest <= lastpc)
pc += b; /* do the jump */
@@ -436,7 +418,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
int luaG_checkcode (const Proto *pt) {
- return luaG_symbexec(pt, pt->sizecode, NO_REG);
+ return (luaG_symbexec(pt, pt->sizecode, NO_REG) != 0);
}
@@ -478,6 +460,11 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) {
*name = kname(p, k);
return "field";
}
+ case OP_GETUPVAL: {
+ int u = GETARG_B(i); /* upvalue index */
+ *name = getstr(p->upvalues[u]);
+ return "upvalue";
+ }
case OP_SELF: {
int k = GETARG_C(i); /* key index */
*name = kname(p, k);
@@ -504,7 +491,7 @@ static const char *getfuncname (CallInfo *ci, const char **name) {
/* only ANSI way to check whether a pointer points to an array */
-static int isinstack (CallInfo *ci, const TObject *o) {
+static int isinstack (CallInfo *ci, const TValue *o) {
StkId p;
for (p = ci->base; p < ci->top; p++)
if (o == p) return 1;
@@ -512,7 +499,7 @@ static int isinstack (CallInfo *ci, const TObject *o) {
}
-void luaG_typeerror (lua_State *L, const TObject *o, const char *op) {
+void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
const char *name = NULL;
const char *t = luaT_typenames[ttype(o)];
const char *kind = (isinstack(L->ci, o)) ?
@@ -532,15 +519,15 @@ void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
}
-void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) {
- TObject temp;
+void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
+ TValue temp;
if (luaV_tonumber(p1, &temp) == NULL)
p2 = p1; /* first operand is wrong */
luaG_typeerror(L, p2, "perform arithmetic on");
}
-int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) {
+int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
const char *t1 = luaT_typenames[ttype(p1)];
const char *t2 = luaT_typenames[ttype(p2)];
if (t1[2] == t2[2])
@@ -566,8 +553,8 @@ void luaG_errormsg (lua_State *L) {
if (L->errfunc != 0) { /* is there an error handling function? */
StkId errfunc = restorestack(L, L->errfunc);
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
- setobjs2s(L->top, L->top - 1); /* move argument */
- setobjs2s(L->top - 1, errfunc); /* push function */
+ setobjs2s(L, L->top, L->top - 1); /* move argument */
+ setobjs2s(L, L->top - 1, errfunc); /* push function */
incr_top(L);
luaD_call(L, L->top - 2, 1); /* call it */
}
diff --git a/src/ldebug.h b/src/ldebug.h
index 7ff39583..d7163f2d 100644
--- a/src/ldebug.h
+++ b/src/ldebug.h
@@ -1,5 +1,5 @@
/*
-** $Id: ldebug.h,v 1.32 2002/11/18 11:01:55 roberto Exp $
+** $Id: ldebug.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@@ -18,11 +18,10 @@
#define resethookcount(L) (L->hookcount = L->basehookcount)
-void luaG_inithooks (lua_State *L);
-void luaG_typeerror (lua_State *L, const TObject *o, const char *opname);
+void luaG_typeerror (lua_State *L, const TValue *o, const char *opname);
void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
-void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2);
-int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2);
+void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2);
+int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2);
void luaG_runerror (lua_State *L, const char *fmt, ...);
void luaG_errormsg (lua_State *L);
int luaG_checkcode (const Proto *pt);
diff --git a/src/ldo.c b/src/ldo.c
index a6d344cd..b65c5610 100644
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.c,v 1.217a 2003/04/03 13:35:34 roberto Exp $
+** $Id: ldo.c,v 2.2 2004/03/23 17:02:58 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -39,6 +39,20 @@
*/
+#ifndef LUA_USEEXCEPTIONS
+
+#define L_THROW(c) longjmp((c)->b, 1)
+#define L_TRY(c,a) if (setjmp((c)->b) == 0) { a }
+
+#else
+
+#define L_THROW(c) throw(c)
+#define L_TRY(c,a) try { a } catch(...) \
+ { if ((c)->status == 0) (c)->status = -1; }
+
+#endif
+
+
/* chain list of long jump buffers */
struct lua_longjmp {
struct lua_longjmp *previous;
@@ -50,16 +64,16 @@ struct lua_longjmp {
static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
switch (errcode) {
case LUA_ERRMEM: {
- setsvalue2s(oldtop, luaS_new(L, MEMERRMSG));
+ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
break;
}
case LUA_ERRERR: {
- setsvalue2s(oldtop, luaS_new(L, "error in error handling"));
+ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
break;
}
case LUA_ERRSYNTAX:
case LUA_ERRRUN: {
- setobjs2s(oldtop, L->top - 1); /* error message on current top */
+ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
break;
}
}
@@ -70,10 +84,10 @@ static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
void luaD_throw (lua_State *L, int errcode) {
if (L->errorJmp) {
L->errorJmp->status = errcode;
- longjmp(L->errorJmp->b, 1);
+ L_THROW(L->errorJmp);
}
else {
- G(L)->panic(L);
+ if (G(L)->panic) G(L)->panic(L);
exit(EXIT_FAILURE);
}
}
@@ -84,8 +98,9 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
lj.status = 0;
lj.previous = L->errorJmp; /* chain new error handler */
L->errorJmp = &lj;
- if (setjmp(lj.b) == 0)
+ L_TRY(&lj,
(*f)(L, ud);
+ );
L->errorJmp = lj.previous; /* restore old error handler */
return lj.status;
}
@@ -103,12 +118,12 @@ static void restore_stack_limit (lua_State *L) {
/* }====================================================== */
-static void correctstack (lua_State *L, TObject *oldstack) {
+static void correctstack (lua_State *L, TValue *oldstack) {
CallInfo *ci;
GCObject *up;
L->top = (L->top - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->gch.next)
- gcotouv(up)->v = (gcotouv(up)->v - oldstack) + L->stack;
+ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
for (ci = L->base_ci; ci <= L->ci; ci++) {
ci->top = (ci->top - oldstack) + L->stack;
ci->base = (ci->base - oldstack) + L->stack;
@@ -118,8 +133,8 @@ static void correctstack (lua_State *L, TObject *oldstack) {
void luaD_reallocstack (lua_State *L, int newsize) {
- TObject *oldstack = L->stack;
- luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject);
+ TValue *oldstack = L->stack;
+ luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
L->stacksize = newsize;
L->stack_last = L->stack+newsize-1-EXTRA_STACK;
correctstack(L, oldstack);
@@ -183,7 +198,6 @@ void luaD_callhook (lua_State *L, int event, int line) {
static void adjust_varargs (lua_State *L, int nfixargs, StkId base) {
int i;
Table *htab;
- TObject nname;
int actual = L->top - base; /* actual number of arguments */
if (actual < nfixargs) {
luaD_checkstack(L, nfixargs - actual);
@@ -193,27 +207,28 @@ static void adjust_varargs (lua_State *L, int nfixargs, StkId base) {
actual -= nfixargs; /* number of extra arguments */
htab = luaH_new(L, actual, 1); /* create `arg' table */
for (i=0; i<actual; i++) /* put extra arguments into `arg' table */
- setobj2n(luaH_setnum(L, htab, i+1), L->top - actual + i);
+ setobj2n(L, luaH_setnum(L, htab, i+1), L->top - actual + i);
/* store counter in field `n' */
- setsvalue(&nname, luaS_newliteral(L, "n"));
- setnvalue(luaH_set(L, htab, &nname), cast(lua_Number, actual));
+ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")),
+ cast(lua_Number, actual));
L->top -= actual; /* remove extra elements from the stack */
- sethvalue(L->top, htab);
+ sethvalue(L, L->top, htab);
+ lua_assert(iswhite(obj2gco(htab)));
incr_top(L);
}
static StkId tryfuncTM (lua_State *L, StkId func) {
- const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
+ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
StkId p;
ptrdiff_t funcr = savestack(L, func);
if (!ttisfunction(tm))
luaG_typeerror(L, func, "call");
/* Open a hole inside the stack at `func' */
- for (p = L->top; p > func; p--) setobjs2s(p, p-1);
+ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
incr_top(L);
func = restorestack(L, funcr); /* previous call may change stack */
- setobj2s(func, tm); /* tag method is the new function to be called */
+ setobj2s(L, func, tm); /* tag method is the new function to be called */
return func;
}
@@ -228,6 +243,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
cl = &clvalue(func)->l;
if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci;
+ StkId st;
Proto *p = cl->p;
if (p->is_vararg) /* varargs? */
adjust_varargs(L, p->numparams, func+1);
@@ -237,9 +253,8 @@ StkId luaD_precall (lua_State *L, StkId func) {
ci->top = L->base + p->maxstacksize;
ci->u.l.savedpc = p->code; /* starting point */
ci->u.l.tailcalls = 0;
- ci->state = CI_SAVEDPC;
- while (L->top < ci->top)
- setnilvalue(L->top++);
+ for (st = L->top; st < ci->top; st++)
+ setnilvalue(st);
L->top = ci->top;
return NULL;
}
@@ -250,14 +265,10 @@ StkId luaD_precall (lua_State *L, StkId func) {
ci = ++L->ci; /* now `enter' new function */
L->base = L->ci->base = restorestack(L, funcr) + 1;
ci->top = L->top + LUA_MINSTACK;
- ci->state = CI_C; /* a C function */
if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
lua_unlock(L);
-#ifdef LUA_COMPATUPVALUES
- lua_pushupvalues(L);
-#endif
- n = (*clvalue(L->base - 1)->c.f)(L); /* do the actual call */
+ n = (*curr_func(L)->c.f)(L); /* do the actual call */
lua_lock(L);
return L->top - n;
}
@@ -267,7 +278,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
static StkId callrethooks (lua_State *L, StkId firstResult) {
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
luaD_callhook(L, LUA_HOOKRET, -1);
- if (!(L->ci->state & CI_C)) { /* Lua function? */
+ if (f_isLua(L->ci)) { /* Lua function? */
while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */
luaD_callhook(L, LUA_HOOKTAILRET, -1);
}
@@ -284,7 +295,7 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
L->base = L->ci->base; /* restore base */
/* move results to correct place */
while (wanted != 0 && firstResult < L->top) {
- setobjs2s(res++, firstResult++);
+ setobjs2s(L, res++, firstResult++);
wanted--;
}
while (wanted-- > 0)
@@ -301,7 +312,6 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
*/
void luaD_call (lua_State *L, StkId func, int nResults) {
StkId firstResult;
- lua_assert(!(L->ci->state & CI_CALLING));
if (++L->nCcalls >= LUA_MAXCCALLS) {
if (L->nCcalls == LUA_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
@@ -310,7 +320,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
}
firstResult = luaD_precall(L, func);
if (firstResult == NULL) /* is a Lua function? */
- firstResult = luaV_execute(L); /* call it */
+ firstResult = luaV_execute(L, 1); /* call it */
luaD_poscall(L, nResults, firstResult);
L->nCcalls--;
luaC_checkGC(L);
@@ -321,27 +331,23 @@ static void resume (lua_State *L, void *ud) {
StkId firstResult;
int nargs = *cast(int *, ud);
CallInfo *ci = L->ci;
- if (ci == L->base_ci) { /* no activation record? */
- lua_assert(nargs < L->top - L->base);
+ if (!L->isSuspended) {
+ lua_assert(ci == L->base_ci && nargs < L->top - L->base);
luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */
}
- else { /* inside a yield */
- lua_assert(ci->state & CI_YIELD);
- if (ci->state & CI_C) { /* `common' yield? */
+ else { /* resuming from previous yield */
+ if (!f_isLua(ci)) { /* `common' yield? */
/* finish interrupted execution of `OP_CALL' */
int nresults;
- lua_assert((ci-1)->state & CI_SAVEDPC);
lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
luaD_poscall(L, nresults, L->top - nargs); /* complete it */
if (nresults >= 0) L->top = L->ci->top;
- }
- else { /* yielded inside a hook: just continue its execution */
- ci->state &= ~CI_YIELD;
- }
+ } /* else yielded inside a hook: just continue its execution */
}
- firstResult = luaV_execute(L);
+ L->isSuspended = 0;
+ firstResult = luaV_execute(L, L->ci - L->base_ci);
if (firstResult != NULL) /* return? */
luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
}
@@ -349,7 +355,7 @@ static void resume (lua_State *L, void *ud) {
static int resume_error (lua_State *L, const char *msg) {
L->top = L->ci->base;
- setsvalue2s(L->top, luaS_new(L, msg));
+ setsvalue2s(L, L->top, luaS_new(L, msg));
incr_top(L);
lua_unlock(L);
return LUA_ERRRUN;
@@ -360,14 +366,16 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
int status;
lu_byte old_allowhooks;
lua_lock(L);
- if (L->ci == L->base_ci) {
- if (nargs >= L->top - L->base)
- return resume_error(L, "cannot resume dead coroutine");
+ lua_assert(L->errfunc == 0 && L->nCcalls == 0);
+ if (!L->isSuspended) {
+ if (L->ci == L->base_ci) { /* no activation record? */
+ if (nargs >= L->top - L->base)
+ return resume_error(L, "cannot resume dead coroutine");
+ }
+ else
+ return resume_error(L, "cannot resume non-suspended coroutine");
}
- else if (!(L->ci->state & CI_YIELD)) /* not inside a yield? */
- return resume_error(L, "cannot resume non-suspended coroutine");
old_allowhooks = L->allowhook;
- lua_assert(L->errfunc == 0 && L->nCcalls == 0);
status = luaD_rawrunprotected(L, resume, &nargs);
if (status != 0) { /* error? */
L->ci = L->base_ci; /* go back to initial level */
@@ -389,17 +397,15 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
ci = L->ci;
if (L->nCcalls > 0)
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
- if (ci->state & CI_C) { /* usual yield */
- if ((ci-1)->state & CI_C)
- luaG_runerror(L, "cannot yield a C function");
+ if (!f_isLua(ci)) { /* usual yield */
if (L->top - nresults > L->base) { /* is there garbage in the stack? */
int i;
for (i=0; i<nresults; i++) /* move down results */
- setobjs2s(L->base + i, L->top - nresults + i);
+ setobjs2s(L, L->base + i, L->top - nresults + i);
L->top = L->base + nresults;
}
} /* else it's an yield inside a hook: nothing to do */
- ci->state |= CI_YIELD;
+ L->isSuspended = 1;
lua_unlock(L);
return -1;
}
@@ -436,35 +442,34 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
struct SParser { /* data to `f_parser' */
ZIO *z;
Mbuffer buff; /* buffer to be used by the scanner */
- int bin;
+ const char *name;
};
static void f_parser (lua_State *L, void *ud) {
- struct SParser *p;
+ int i;
Proto *tf;
Closure *cl;
+ struct SParser *p = cast(struct SParser *, ud);
+ int c = luaZ_lookahead(p->z);
luaC_checkGC(L);
- p = cast(struct SParser *, ud);
- tf = p->bin ? luaU_undump(L, p->z, &p->buff) : luaY_parser(L, p->z, &p->buff);
- cl = luaF_newLclosure(L, 0, gt(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->l.p = tf;
- setclvalue(L->top, cl);
+ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
+ cl->l.upvals[i] = luaF_newupval(L);
+ setclvalue(L, L->top, cl);
incr_top(L);
}
-int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
struct SParser p;
int status;
- ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */
- p.z = z; p.bin = bin;
+ p.z = z; p.name = name;
luaZ_initbuffer(L, &p.buff);
- status = luaD_rawrunprotected(L, f_parser, &p);
+ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
- if (status != 0) { /* error? */
- StkId oldtop = restorestack(L, oldtopr);
- seterrorobj(L, status, oldtop);
- }
return status;
}
diff --git a/src/ldo.h b/src/ldo.h
index 2a61bf5b..85511f2c 100644
--- a/src/ldo.h
+++ b/src/ldo.h
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.h,v 1.56 2002/12/04 17:29:32 roberto Exp $
+** $Id: ldo.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -24,7 +24,7 @@
#define luaD_checkstack(L,n) \
- if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TObject)) \
+ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
luaD_growstack(L, n); \
else condhardstacktests(luaD_reallocstack(L, L->stacksize));
@@ -32,7 +32,7 @@
#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
-#define restorestack(L,n) ((TObject *)((char *)L->stack + (n)))
+#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
@@ -42,7 +42,7 @@
typedef void (*Pfunc) (lua_State *L, void *ud);
void luaD_resetprotection (lua_State *L);
-int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
void luaD_callhook (lua_State *L, int event, int line);
StkId luaD_precall (lua_State *L, StkId func);
void luaD_call (lua_State *L, StkId func, int nResults);
diff --git a/src/ldump.c b/src/ldump.c
index 234b011f..dc4ebad1 100644
--- a/src/ldump.c
+++ b/src/ldump.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldump.c,v 1.4 2003/02/11 23:52:12 lhf Exp $
+** $Id: ldump.c,v 1.6 2004/03/24 00:25:08 lhf Exp $
** save bytecodes
** See Copyright Notice in lua.h
*/
@@ -22,6 +22,7 @@ typedef struct {
lua_State* L;
lua_Chunkwriter write;
void* data;
+ int strip;
} DumpState;
static void DumpBlock(const void* b, size_t size, DumpState* D)
@@ -103,7 +104,7 @@ static void DumpConstants(const Proto* f, DumpState* D)
DumpInt(n=f->sizek,D);
for (i=0; i<n; i++)
{
- const TObject* o=&f->k[i];
+ const TValue* o=&f->k[i];
DumpByte(ttype(o),D);
switch (ttype(o))
{
@@ -111,7 +112,7 @@ static void DumpConstants(const Proto* f, DumpState* D)
DumpNumber(nvalue(o),D);
break;
case LUA_TSTRING:
- DumpString(tsvalue(o),D);
+ DumpString(rawtsvalue(o),D);
break;
case LUA_TNIL:
break;
@@ -132,9 +133,9 @@ static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
DumpByte(f->numparams,D);
DumpByte(f->is_vararg,D);
DumpByte(f->maxstacksize,D);
- DumpLines(f,D);
- DumpLocals(f,D);
- DumpUpvalues(f,D);
+ if (D->strip) DumpInt(0,D); else DumpLines(f,D);
+ if (D->strip) DumpInt(0,D); else DumpLocals(f,D);
+ if (D->strip) DumpInt(0,D); else DumpUpvalues(f,D);
DumpConstants(f,D);
DumpCode(f,D);
}
@@ -147,10 +148,6 @@ static void DumpHeader(DumpState* D)
DumpByte(sizeof(int),D);
DumpByte(sizeof(size_t),D);
DumpByte(sizeof(Instruction),D);
- DumpByte(SIZE_OP,D);
- DumpByte(SIZE_A,D);
- DumpByte(SIZE_B,D);
- DumpByte(SIZE_C,D);
DumpByte(sizeof(lua_Number),D);
DumpNumber(TEST_NUMBER,D);
}
@@ -158,13 +155,14 @@ static void DumpHeader(DumpState* D)
/*
** dump function as precompiled chunk
*/
-void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data)
+int luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data, int strip)
{
DumpState D;
D.L=L;
D.write=w;
D.data=data;
+ D.strip=strip;
DumpHeader(&D);
DumpFunction(Main,NULL,&D);
+ return 1;
}
-
diff --git a/src/lfunc.c b/src/lfunc.c
index 31044fa5..d9f4e27e 100644
--- a/src/lfunc.c
+++ b/src/lfunc.c
@@ -1,11 +1,11 @@
/*
-** $Id: lfunc.c,v 1.67 2003/03/18 12:50:04 roberto Exp $
+** $Id: lfunc.c,v 2.3 2004/03/15 21:04:33 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
-#include <stdlib.h>
+#include <stddef.h>
#define lfunc_c
@@ -18,65 +18,75 @@
#include "lstate.h"
-#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
- cast(int, sizeof(TObject)*((n)-1)))
-
-#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
- cast(int, sizeof(TObject *)*((n)-1)))
-
-
Closure *luaF_newCclosure (lua_State *L, int nelems) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
- luaC_link(L, valtogco(c), LUA_TFUNCTION);
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->c.isC = 1;
c->c.nupvalues = cast(lu_byte, nelems);
return c;
}
-Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e) {
+Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
- luaC_link(L, valtogco(c), LUA_TFUNCTION);
+ luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->l.isC = 0;
c->l.g = *e;
c->l.nupvalues = cast(lu_byte, nelems);
+ while (nelems--) c->l.upvals[nelems] = NULL;
return c;
}
+UpVal *luaF_newupval (lua_State *L) {
+ UpVal *uv = luaM_new(L, UpVal);
+ luaC_link(L, obj2gco(uv), LUA_TUPVAL);
+ uv->v = &uv->value;
+ setnilvalue(uv->v);
+ return uv;
+}
+
+
UpVal *luaF_findupval (lua_State *L, StkId level) {
GCObject **pp = &L->openupval;
UpVal *p;
- UpVal *v;
+ UpVal *uv;
while ((p = ngcotouv(*pp)) != NULL && p->v >= level) {
if (p->v == level) return p;
pp = &p->next;
}
- v = luaM_new(L, UpVal); /* not found: create a new one */
- v->tt = LUA_TUPVAL;
- v->marked = 1; /* open upvalues should not be collected */
- v->v = level; /* current value lives in the stack */
- v->next = *pp; /* chain it in the proper position */
- *pp = valtogco(v);
- return v;
+ uv = luaM_new(L, UpVal); /* not found: create a new one */
+ uv->tt = LUA_TUPVAL;
+ uv->marked = luaC_white(G(L));
+ uv->v = level; /* current value lives in the stack */
+ uv->next = *pp; /* chain it in the proper position */
+ *pp = obj2gco(uv);
+ return uv;
}
void luaF_close (lua_State *L, StkId level) {
- UpVal *p;
- while ((p = ngcotouv(L->openupval)) != NULL && p->v >= level) {
- setobj(&p->value, p->v); /* save current value (write barrier) */
- p->v = &p->value; /* now current value lives here */
- L->openupval = p->next; /* remove from `open' list */
- luaC_link(L, valtogco(p), LUA_TUPVAL);
+ UpVal *uv;
+ global_State *g = G(L);
+ while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) {
+ GCObject *o = obj2gco(uv);
+ lua_assert(!isblack(o));
+ L->openupval = uv->next; /* remove from `open' list */
+ if (isdead(g, o))
+ luaM_freelem(L, uv); /* free upvalue */
+ else {
+ setobj(L, &uv->value, uv->v);
+ uv->v = &uv->value; /* now current value lives here */
+ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
+ }
}
}
Proto *luaF_newproto (lua_State *L) {
Proto *f = luaM_new(L, Proto);
- luaC_link(L, valtogco(f), LUA_TPROTO);
+ luaC_link(L, obj2gco(f), LUA_TPROTO);
f->k = NULL;
f->sizek = 0;
f->p = NULL;
@@ -102,7 +112,7 @@ Proto *luaF_newproto (lua_State *L) {
void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->code, f->sizecode, Instruction);
luaM_freearray(L, f->p, f->sizep, Proto *);
- luaM_freearray(L, f->k, f->sizek, TObject);
+ luaM_freearray(L, f->k, f->sizek, TValue);
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
diff --git a/src/lfunc.h b/src/lfunc.h
index 5d532507..04437601 100644
--- a/src/lfunc.h
+++ b/src/lfunc.h
@@ -1,5 +1,5 @@
/*
-** $Id: lfunc.h,v 1.21 2003/03/18 12:50:04 roberto Exp $
+** $Id: lfunc.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -11,9 +11,17 @@
#include "lobject.h"
+#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
+ cast(int, sizeof(TValue)*((n)-1)))
+
+#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
+ cast(int, sizeof(TValue *)*((n)-1)))
+
+
Proto *luaF_newproto (lua_State *L);
Closure *luaF_newCclosure (lua_State *L, int nelems);
-Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *e);
+Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *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);
diff --git a/src/lgc.c b/src/lgc.c
index 5e036d38..db1b1c89 100644
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 1.171a 2003/04/03 13:35:34 roberto Exp $
+** $Id: lgc.c,v 2.6 2004/03/23 12:57:12 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -22,117 +22,130 @@
#include "ltm.h"
-typedef struct GCState {
- GCObject *tmark; /* list of marked objects to be traversed */
- GCObject *wk; /* list of traversed key-weak tables (to be cleared) */
- GCObject *wv; /* list of traversed value-weak tables */
- GCObject *wkv; /* list of traversed key-value weak tables */
- global_State *g;
-} GCState;
+#define GCSTEPSIZE (40*sizeof(TValue))
+#define GCFREECOST (sizeof(TValue)/2)
+#define GCSWEEPCOST sizeof(TValue)
+#define GCFINALIZECOST (10*sizeof(TValue))
-/*
-** some userful bit tricks
-*/
-#define setbit(x,b) ((x) |= (1<<(b)))
-#define resetbit(x,b) ((x) &= cast(lu_byte, ~(1<<(b))))
-#define testbit(x,b) ((x) & (1<<(b)))
+#define FIXEDMASK bitmask(FIXEDBIT)
+
+#define maskmarks \
+ cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT)))
-#define unmark(x) resetbit((x)->gch.marked, 0)
-#define ismarked(x) ((x)->gch.marked & ((1<<4)|1))
+#define makewhite(g,x) \
+ ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite)
-#define stringmark(s) setbit((s)->tsv.marked, 0)
+#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)->uv.marked, 1))
-#define markfinalized(u) resetbit((u)->uv.marked, 1)
+#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
+#define markfinalized(u) setbit((u)->marked, FINALIZEDBIT)
-#define KEYWEAKBIT 1
-#define VALUEWEAKBIT 2
-#define KEYWEAK (1<<KEYWEAKBIT)
-#define VALUEWEAK (1<<VALUEWEAKBIT)
+#define KEYWEAK bitmask(KEYWEAKBIT)
+#define VALUEWEAK bitmask(VALUEWEAKBIT)
-#define markobject(st,o) { checkconsistency(o); \
- if (iscollectable(o) && !ismarked(gcvalue(o))) reallymarkobject(st,gcvalue(o)); }
-#define condmarkobject(st,o,c) { checkconsistency(o); \
- if (iscollectable(o) && !ismarked(gcvalue(o)) && (c)) \
- reallymarkobject(st,gcvalue(o)); }
+#define markvalue(g,o) { checkconsistency(o); \
+ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
-#define markvalue(st,t) { if (!ismarked(valtogco(t))) \
- reallymarkobject(st, valtogco(t)); }
+#define markobject(g,t) { if (iswhite(obj2gco(t))) \
+ reallymarkobject(g, obj2gco(t)); }
-static void reallymarkobject (GCState *st, GCObject *o) {
- lua_assert(!ismarked(o));
- setbit(o->gch.marked, 0); /* mark object */
+static void removeentry (Node *n) {
+ setnilvalue(gval(n)); /* remove corresponding value ... */
+ if (iscollectable(gkey(n)))
+ setttype(gkey(n), LUA_TNONE); /* dead key; remove it */
+}
+
+
+static void reallymarkobject (global_State *g, GCObject *o) {
+ lua_assert(iswhite(o) && !isdead(g, o));
+ white2gray(o);
switch (o->gch.tt) {
+ case LUA_TSTRING: {
+ return;
+ }
case LUA_TUSERDATA: {
- markvalue(st, gcotou(o)->uv.metatable);
- break;
+ Table *mt = gco2u(o)->metatable;
+ gray2black(o); /* udata are never gray */
+ if (mt) markobject(g, mt);
+ return;
+ }
+ case LUA_TUPVAL: {
+ UpVal *uv = gco2uv(o);
+ if (uv->v == &uv->value) { /* closed? */
+ markvalue(g, uv->v);
+ gray2black(o);
+ }
+ return;
}
case LUA_TFUNCTION: {
- gcotocl(o)->c.gclist = st->tmark;
- st->tmark = o;
+ gco2cl(o)->c.gclist = g->gray;
+ g->gray = o;
break;
}
case LUA_TTABLE: {
- gcotoh(o)->gclist = st->tmark;
- st->tmark = o;
+ gco2h(o)->gclist = g->gray;
+ g->gray = o;
break;
}
case LUA_TTHREAD: {
- gcototh(o)->gclist = st->tmark;
- st->tmark = o;
+ gco2th(o)->gclist = g->gray;
+ g->gray = o;
break;
}
case LUA_TPROTO: {
- gcotop(o)->gclist = st->tmark;
- st->tmark = o;
+ gco2p(o)->gclist = g->gray;
+ g->gray = o;
break;
}
- default: lua_assert(o->gch.tt == LUA_TSTRING);
+ default: lua_assert(0);
}
}
-static void marktmu (GCState *st) {
+static void marktmu (global_State *g) {
GCObject *u;
- for (u = st->g->tmudata; u; u = u->gch.next) {
- unmark(u); /* may be marked, if left from previous GC */
- reallymarkobject(st, u);
+ for (u = g->tmudata; u; u = u->gch.next) {
+ makewhite(g, u); /* may be marked, if left from previous GC */
+ reallymarkobject(g, u);
}
}
/* move `dead' udata that need finalization to list `tmudata' */
-size_t luaC_separateudata (lua_State *L) {
+size_t luaC_separateudata (lua_State *L, int all) {
size_t deadmem = 0;
- GCObject **p = &G(L)->rootudata;
+ GCObject **p = &G(L)->firstudata;
GCObject *curr;
GCObject *collected = NULL; /* to collect udata with gc event */
GCObject **lastcollected = &collected;
- while ((curr = *p) != NULL) {
- lua_assert(curr->gch.tt == LUA_TUSERDATA);
- if (ismarked(curr) || isfinalized(gcotou(curr)))
+ while ((curr = *p)->gch.tt == LUA_TUSERDATA) {
+ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
p = &curr->gch.next; /* don't bother with them */
-
- else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) {
- markfinalized(gcotou(curr)); /* don't need finalization */
+ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
+ markfinalized(gco2u(curr)); /* don't need finalization */
p = &curr->gch.next;
}
else { /* must call its gc method */
- deadmem += sizeudata(gcotou(curr)->uv.len);
+ deadmem += sizeudata(gco2u(curr)->len);
+ 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;
}
}
+ lua_assert(curr == obj2gco(G(L)->mainthread));
/* insert collected udata with gc event into `tmudata' list */
*lastcollected = G(L)->tmudata;
G(L)->tmudata = collected;
@@ -140,89 +153,85 @@ size_t luaC_separateudata (lua_State *L) {
}
-static void removekey (Node *n) {
- setnilvalue(gval(n)); /* remove corresponding value ... */
- if (iscollectable(gkey(n)))
- setttype(gkey(n), LUA_TNONE); /* dead key; remove it */
-}
-
-
-static void traversetable (GCState *st, Table *h) {
+static int traversetable (global_State *g, Table *h) {
int i;
int weakkey = 0;
int weakvalue = 0;
- const TObject *mode;
- markvalue(st, h->metatable);
- lua_assert(h->lsizenode || h->node == st->g->dummynode);
- mode = gfasttm(st->g, h->metatable, TM_MODE);
+ 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);
weakvalue = (strchr(svalue(mode), 'v') != NULL);
if (weakkey || weakvalue) { /* is really weak? */
- GCObject **weaklist;
h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) |
(weakvalue << VALUEWEAKBIT));
- weaklist = (weakkey && weakvalue) ? &st->wkv :
- (weakkey) ? &st->wk :
- &st->wv;
- h->gclist = *weaklist; /* must be cleared after GC, ... */
- *weaklist = valtogco(h); /* ... so put in the appropriate list */
+ h->gclist = g->weak; /* must be cleared after GC, ... */
+ g->weak = obj2gco(h); /* ... so put in the appropriate list */
}
}
+ if (weakkey && weakvalue) return 1;
if (!weakvalue) {
i = h->sizearray;
while (i--)
- markobject(st, &h->array[i]);
+ markvalue(g, &h->array[i]);
}
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
- if (!ttisnil(gval(n))) {
+ if (ttisnil(gval(n)))
+ removeentry(n); /* remove empty entries */
+ else {
lua_assert(!ttisnil(gkey(n)));
- condmarkobject(st, gkey(n), !weakkey);
- condmarkobject(st, gval(n), !weakvalue);
+ if (!weakkey) markvalue(g, gkey(n));
+ if (!weakvalue) markvalue(g, gval(n));
}
}
+ return weakkey || weakvalue;
}
-static void traverseproto (GCState *st, Proto *f) {
+/*
+** All marks are conditional because a GC may happen while the
+** prototype is still being created
+*/
+static void traverseproto (global_State *g, Proto *f) {
int i;
- stringmark(f->source);
- for (i=0; i<f->sizek; i++) { /* mark literal strings */
- if (ttisstring(f->k+i))
- stringmark(tsvalue(f->k+i));
+ if (f->source) stringmark(f->source);
+ for (i=0; i<f->sizek; i++) /* mark literals */
+ markvalue(g, &f->k[i]);
+ for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
+ if (f->upvalues[i])
+ stringmark(f->upvalues[i]);
+ }
+ for (i=0; i<f->sizep; i++) { /* mark nested protos */
+ if (f->p[i])
+ markobject(g, f->p[i]);
+ }
+ for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
+ if (f->locvars[i].varname)
+ stringmark(f->locvars[i].varname);
}
- for (i=0; i<f->sizeupvalues; i++) /* mark upvalue names */
- stringmark(f->upvalues[i]);
- for (i=0; i<f->sizep; i++) /* mark nested protos */
- markvalue(st, f->p[i]);
- for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */
- stringmark(f->locvars[i].varname);
- lua_assert(luaG_checkcode(f));
}
-static void traverseclosure (GCState *st, Closure *cl) {
+static void traverseclosure (global_State *g, Closure *cl) {
if (cl->c.isC) {
int i;
for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
- markobject(st, &cl->c.upvalue[i]);
+ markvalue(g, &cl->c.upvalue[i]);
}
else {
int i;
lua_assert(cl->l.nupvalues == cl->l.p->nups);
- markvalue(st, hvalue(&cl->l.g));
- markvalue(st, cl->l.p);
- for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
- UpVal *u = cl->l.upvals[i];
- if (!u->marked) {
- markobject(st, &u->value);
- u->marked = 1;
- }
- }
+ 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]);
}
}
@@ -239,101 +248,121 @@ static void checkstacksizes (lua_State *L, StkId max) {
}
-static void traversestack (GCState *st, lua_State *L1) {
+static void traversestack (global_State *g, lua_State *l) {
StkId o, lim;
CallInfo *ci;
- markobject(st, gt(L1));
- lim = L1->top;
- for (ci = L1->base_ci; ci <= L1->ci; ci++) {
- lua_assert(ci->top <= L1->stack_last);
- lua_assert(ci->state & (CI_C | CI_HASFRAME | CI_SAVEDPC));
- if (lim < ci->top)
- lim = ci->top;
+ markvalue(g, gt(l));
+ lim = l->top;
+ for (ci = l->base_ci; ci <= l->ci; ci++) {
+ lua_assert(ci->top <= l->stack_last);
+ if (lim < ci->top) lim = ci->top;
}
- for (o = L1->stack; o < L1->top; o++)
- markobject(st, o);
+ for (o = l->stack; o < l->top; o++)
+ markvalue(g, o);
for (; o <= lim; o++)
setnilvalue(o);
- checkstacksizes(L1, lim);
+ checkstacksizes(l, lim);
}
-static void propagatemarks (GCState *st) {
- while (st->tmark) { /* traverse marked objects */
- switch (st->tmark->gch.tt) {
+/*
+** traverse a given `quantity' of gray objects,
+** turning them to black. Returns extra `quantity' traversed.
+*/
+static l_mem propagatemarks (global_State *g, l_mem lim) {
+ GCObject *o;
+ while ((o = g->gray) != NULL) {
+ lua_assert(isgray(o));
+ gray2black(o);
+ switch (o->gch.tt) {
case LUA_TTABLE: {
- Table *h = gcotoh(st->tmark);
- st->tmark = h->gclist;
- traversetable(st, h);
+ Table *h = gco2h(o);
+ g->gray = h->gclist;
+ if (traversetable(g, h)) /* table is weak? */
+ black2gray(o); /* keep it gray */
+ lim -= sizeof(Table) + sizeof(TValue) * h->sizearray +
+ sizeof(Node) * sizenode(h);
break;
}
case LUA_TFUNCTION: {
- Closure *cl = gcotocl(st->tmark);
- st->tmark = cl->c.gclist;
- traverseclosure(st, cl);
+ Closure *cl = gco2cl(o);
+ g->gray = cl->c.gclist;
+ traverseclosure(g, cl);
+ lim -= (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
+ sizeLclosure(cl->l.nupvalues);
break;
}
case LUA_TTHREAD: {
- lua_State *th = gcototh(st->tmark);
- st->tmark = th->gclist;
- traversestack(st, th);
+ lua_State *th = gco2th(o);
+ g->gray = th->gclist;
+ th->gclist = g->grayagain;
+ g->grayagain = o;
+ black2gray(o);
+ traversestack(g, th);
+ lim -= sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * th->size_ci;
break;
}
case LUA_TPROTO: {
- Proto *p = gcotop(st->tmark);
- st->tmark = p->gclist;
- traverseproto(st, p);
+ Proto *p = gco2p(o);
+ g->gray = p->gclist;
+ traverseproto(g, p);
+ lim -= sizeof(Proto) + sizeof(Instruction) * p->sizecode +
+ sizeof(Proto *) * p->sizep +
+ sizeof(TValue) * p->sizek +
+ sizeof(int) * p->sizelineinfo +
+ sizeof(LocVar) * p->sizelocvars +
+ sizeof(TString *) * p->sizeupvalues;
break;
}
default: lua_assert(0);
}
+ if (lim <= 0) return lim;
}
-}
-
-
-static int valismarked (const TObject *o) {
- if (ttisstring(o))
- stringmark(tsvalue(o)); /* strings are `values', so are never weak */
- return !iscollectable(o) || testbit(o->value.gc->gch.marked, 0);
+ return lim;
}
/*
-** clear collected keys from weaktables
+** The next function tells whether a key or value can be cleared from
+** a weak table. Non-collectable objects are never removed from weak
+** tables. Strings behave as `values', so are never removed too. for
+** other objects: if really collected, cannot keep them; for userdata
+** being finalized, keep them in keys, but not in values
*/
-static void cleartablekeys (GCObject *l) {
- while (l) {
- Table *h = gcotoh(l);
- int i = sizenode(h);
- lua_assert(h->marked & KEYWEAK);
- while (i--) {
- Node *n = gnode(h, i);
- if (!valismarked(gkey(n))) /* key was collected? */
- removekey(n); /* remove entry from table */
- }
- l = h->gclist;
+static int iscleared (const TValue *o, int iskey) {
+ if (!iscollectable(o)) return 0;
+ if (ttisstring(o)) {
+ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
+ return 0;
}
+ return iswhite(gcvalue(o)) ||
+ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
}
/*
-** clear collected values from weaktables
+** clear collected entries from weaktables
*/
-static void cleartablevalues (GCObject *l) {
+static void cleartable (GCObject *l) {
while (l) {
- Table *h = gcotoh(l);
+ Table *h = gco2h(l);
int i = h->sizearray;
- lua_assert(h->marked & VALUEWEAK);
- while (i--) {
- TObject *o = &h->array[i];
- if (!valismarked(o)) /* value was collected? */
- setnilvalue(o); /* remove value */
+ lua_assert(testbit(h->marked, VALUEWEAKBIT) ||
+ testbit(h->marked, KEYWEAKBIT));
+ if (testbit(h->marked, VALUEWEAKBIT)) {
+ while (i--) {
+ TValue *o = &h->array[i];
+ if (iscleared(o, 0)) /* value was collected? */
+ setnilvalue(o); /* remove value */
+ }
}
i = sizenode(h);
while (i--) {
Node *n = gnode(h, i);
- if (!valismarked(gval(n))) /* value was collected? */
- removekey(n); /* remove entry from table */
+ if (!ttisnil(gval(n)) && /* non-empty entry? */
+ (iscleared(gkey(n), 1) || iscleared(gval(n), 0)))
+ removeentry(n); /* remove entry from table */
}
l = h->gclist;
}
@@ -342,21 +371,21 @@ static void cleartablevalues (GCObject *l) {
static void freeobj (lua_State *L, GCObject *o) {
switch (o->gch.tt) {
- case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break;
- case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break;
- case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break;
- case LUA_TTABLE: luaH_free(L, gcotoh(o)); break;
+ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
+ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
+ case LUA_TUPVAL: luaM_freelem(L, gco2uv(o)); break;
+ case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
case LUA_TTHREAD: {
- lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread);
- luaE_freethread(L, gcototh(o));
+ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);
+ luaE_freethread(L, gco2th(o));
break;
}
case LUA_TSTRING: {
- luaM_free(L, o, sizestring(gcotots(o)->tsv.len));
+ luaM_free(L, o, sizestring(gco2ts(o)->len));
break;
}
case LUA_TUSERDATA: {
- luaM_free(L, o, sizeudata(gcotou(o)->uv.len));
+ luaM_free(L, o, sizeudata(gco2u(o)->len));
break;
}
default: lua_assert(0);
@@ -364,135 +393,283 @@ static void freeobj (lua_State *L, GCObject *o) {
}
-static int sweeplist (lua_State *L, GCObject **p, int limit) {
+static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed,
+ lu_int32 *count);
+
+
+static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed,
+ l_mem *plim, lu_int32 *count) {
GCObject *curr;
- int count = 0; /* number of collected items */
+ global_State *g = G(L);
+ l_mem lim = *plim;
+ int deadmask = otherwhite(g);
+ if (keepfixed) deadmask |= FIXEDMASK;
while ((curr = *p) != NULL) {
- if (curr->gch.marked > limit) {
- unmark(curr);
+ if (((curr->gch.marked ^ FIXEDMASK) & deadmask) != deadmask) {
+ makewhite(g, curr);
+ if (curr->gch.tt == LUA_TTHREAD)
+ lim -= sweepwholelist(L, &gco2th(curr)->openupval, keepfixed, count);
p = &curr->gch.next;
+ lim -= GCSWEEPCOST;
}
else {
- count++;
+ lua_assert(iswhite(curr));
*p = curr->gch.next;
+ if (curr == g->rootgc) /* is the first element of the list? */
+ g->rootgc = curr->gch.next; /* adjust first */
freeobj(L, curr);
+ lim -= GCFREECOST;
+ if (count) (*count)--;
}
+ if (lim <= 0) break;
}
- return count;
+ *plim = lim;
+ return p;
}
-static void sweepstrings (lua_State *L, int all) {
+static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed,
+ lu_int32 *count) {
+ l_mem lim = MAXLMEM;
+ /* empty lists are quite common here, so avoid useless calls */
+ if (*p) sweeplist(L, p, keepfixed, &lim, count);
+ return MAXLMEM - lim;
+}
+
+
+static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) {
int i;
- for (i=0; i<G(L)->strt.size; i++) { /* for each list */
- G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all);
+ global_State *g = G(L);
+ for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */
+ lim -= sweepwholelist(L, &G(L)->strt.hash[i], keepfixed, &g->strt.nuse);
+ if (lim <= 0) break;
}
+ g->sweepstrgc = i+1;
+ return lim;
}
-static void checkSizes (lua_State *L, size_t deadmem) {
+static void checkSizes (lua_State *L) {
+ global_State *g = G(L);
/* check size of string hash */
- if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) &&
- G(L)->strt.size > MINSTRTABSIZE*2)
- luaS_resize(L, G(L)->strt.size/2); /* table is too big */
+ if (g->strt.nuse < cast(lu_int32, G(L)->strt.size/4) &&
+ g->strt.size > MINSTRTABSIZE*2)
+ luaS_resize(L, g->strt.size/2); /* table is too big */
/* check size of buffer */
- if (luaZ_sizebuffer(&G(L)->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
- size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2;
- luaZ_resizebuffer(L, &G(L)->buff, newsize);
+ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
+ size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
+ luaZ_resizebuffer(L, &g->buff, newsize);
}
- G(L)->GCthreshold = 2*G(L)->nblocks - deadmem; /* new threshold */
}
-static void do1gcTM (lua_State *L, Udata *udata) {
- const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC);
+static void GCTM (lua_State *L) {
+ global_State *g = G(L);
+ GCObject *o = g->tmudata;
+ 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;
+ makewhite(g, o);
+ tm = fasttm(L, udata->uv.metatable, TM_GC);
if (tm != NULL) {
- setobj2s(L->top, tm);
- setuvalue(L->top+1, udata);
+ lu_byte oldah = L->allowhook;
+ L->allowhook = 0; /* stop debug hooks during GC tag method */
+ 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 */
}
}
+/*
+** Call all GC tag methods
+*/
void luaC_callGCTM (lua_State *L) {
- lu_byte oldah = L->allowhook;
- L->allowhook = 0; /* stop debug hooks during GC tag methods */
- L->top++; /* reserve space to keep udata while runs its gc method */
- while (G(L)->tmudata != NULL) {
- GCObject *o = G(L)->tmudata;
- Udata *udata = gcotou(o);
- G(L)->tmudata = udata->uv.next; /* remove udata from `tmudata' */
- udata->uv.next = G(L)->rootudata; /* return it to `root' list */
- G(L)->rootudata = o;
- setuvalue(L->top - 1, udata); /* keep a reference to it */
- unmark(o);
- markfinalized(udata);
- do1gcTM(L, udata);
- }
- L->top--;
- L->allowhook = oldah; /* restore hooks */
+ while (G(L)->tmudata)
+ GCTM(L);
}
-void luaC_sweep (lua_State *L, int all) {
- if (all) all = 256; /* larger than any mark */
- sweeplist(L, &G(L)->rootudata, all);
- sweepstrings(L, all);
- sweeplist(L, &G(L)->rootgc, all);
+void luaC_sweepall (lua_State *L) {
+ global_State *g = G(L);
+ l_mem dummy = MAXLMEM;
+ /* finish (occasional) current sweep */
+ sweepstrings(L, 0, MAXLMEM);
+ sweeplist(L, &g->rootgc, 0, &dummy, NULL);
+ /* do a whole new sweep */
+ markobject(g, g->mainthread); /* cannot collect main thread */
+ g->currentwhite = otherwhite(g);
+ g->sweepgc = &g->rootgc;
+ g->sweepstrgc = 0;
+ sweepstrings(L, 0, MAXLMEM);
+ sweeplist(L, &g->rootgc, 0, &dummy, NULL);
}
/* mark root set */
-static void markroot (GCState *st, lua_State *L) {
- global_State *g = st->g;
- markobject(st, defaultmeta(L));
- markobject(st, registry(L));
- traversestack(st, g->mainthread);
- if (L != g->mainthread) /* another thread is running? */
- markvalue(st, L); /* cannot collect it */
+static void markroot (lua_State *L) {
+ global_State *g = G(L);
+ lua_assert(g->gray == NULL);
+ g->grayagain = NULL;
+ g->weak = NULL;
+ markobject(g, g->mainthread);
+ /* make global table be traversed before main stack */
+ markvalue(g, gt(g->mainthread));
+ markvalue(g, registry(L));
+ g->gcstate = GCSpropagate;
}
-static size_t mark (lua_State *L) {
- size_t deadmem;
- GCState st;
- GCObject *wkv;
- st.g = G(L);
- st.tmark = NULL;
- st.wkv = st.wk = st.wv = NULL;
- markroot(&st, L);
- propagatemarks(&st); /* mark all reachable objects */
- cleartablevalues(st.wkv);
- cleartablevalues(st.wv);
- wkv = st.wkv; /* keys must be cleared after preserving udata */
- st.wkv = NULL;
- st.wv = NULL;
- deadmem = luaC_separateudata(L); /* separate userdata to be preserved */
- marktmu(&st); /* mark `preserved' userdata */
- propagatemarks(&st); /* remark, to propagate `preserveness' */
- cleartablekeys(wkv);
- /* `propagatemarks' may resuscitate some weak tables; clear them too */
- cleartablekeys(st.wk);
- cleartablevalues(st.wv);
- cleartablekeys(st.wkv);
- cleartablevalues(st.wkv);
- return deadmem;
+static void remarkupvals (global_State *g) {
+ GCObject *o;
+ for (o = obj2gco(g->mainthread); o; o = o->gch.next) {
+ if (iswhite(o)) {
+ GCObject *curr;
+ for (curr = gco2th(o)->openupval; curr != NULL; curr = curr->gch.next) {
+ if (isgray(curr))
+ markvalue(g, gco2uv(curr)->v);
+ }
+ }
+ }
+}
+
+
+static void atomic (lua_State *L) {
+ global_State *g = G(L);
+ lua_assert(g->gray == NULL);
+ /* remark occasional upvalues of (maybe) dead threads */
+ remarkupvals(g);
+ /* remark weak tables */
+ g->gray = g->weak;
+ g->weak = NULL;
+ lua_assert(!iswhite(obj2gco(g->mainthread)));
+ markobject(g, L); /* mark running thread */
+ propagatemarks(g, MAXLMEM);
+ /* remark gray again */
+ g->gray = g->grayagain;
+ g->grayagain = NULL;
+ propagatemarks(g, MAXLMEM);
+ luaC_separateudata(L, 0); /* separate userdata to be preserved */
+ marktmu(g); /* mark `preserved' userdata */
+ propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */
+ cleartable(g->weak); /* remove collected objects from weak tables */
+ /* flip current white */
+ g->currentwhite = otherwhite(g);
+ g->gcstate = GCSsweepstring;
+}
+
+
+static l_mem singlestep (lua_State *L, l_mem lim) {
+ global_State *g = G(L);
+ switch (g->gcstate) {
+ case GCSpropagate: {
+ if (g->gray)
+ lim = propagatemarks(g, lim);
+ else { /* no more `gray' objects */
+ atomic(L); /* finish mark phase */
+ lim = 0;
+ }
+ break;
+ }
+ case GCSsweepstring: {
+ lim = sweepstrings(L, 1, lim);
+ if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */
+ g->sweepstrgc = 0;
+ g->gcstate = GCSsweep; /* end sweep-string phase */
+ }
+ break;
+ }
+ case GCSsweep: {
+ g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim, NULL);
+ if (*g->sweepgc == NULL) { /* nothing more to sweep? */
+ checkSizes(L);
+ g->sweepgc = &g->rootgc;
+ g->gcstate = GCSfinalize; /* end sweep phase */
+ }
+ break;
+ }
+ case GCSfinalize: {
+ if (g->tmudata) {
+ GCTM(L);
+ lim -= GCFINALIZECOST;
+ }
+ else { /* no more `udata' to finalize */
+ markroot(L); /* may restart collection */
+ lim = 0;
+ }
+ break;
+ }
+ default: lua_assert(0);
+ }
+ return lim;
+}
+
+
+void luaC_step (lua_State *L) {
+ global_State *g = G(L);
+ l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
+ do {
+ lim = singlestep(L, lim);
+ if (g->gcstate == GCSfinalize && g->tmudata == NULL)
+ break; /* do not start new collection */
+ } while (lim > 0);
+ g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2;
+ lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/2);
}
-void luaC_collectgarbage (lua_State *L) {
- size_t deadmem = mark(L);
- luaC_sweep(L, 0);
- checkSizes(L, deadmem);
- luaC_callGCTM(L);
+void luaC_fullgc (lua_State *L) {
+ global_State *g = G(L);
+ while (g->gcstate != GCSfinalize) {
+ singlestep(L, MAXLMEM);
+ }
+ markroot(L);
+ while (g->gcstate != GCSfinalize) {
+ singlestep(L, MAXLMEM);
+ }
+ g->GCthreshold = g->nblocks + GCSTEPSIZE;
+ luaC_callGCTM(L); /* call finalizers */
+}
+
+
+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->gcstate != GCSfinalize);
+ if (g->gcstate != GCSpropagate) /* sweeping phases? */
+ black2gray(o); /* just mark as gray to avoid other barriers */
+ else /* breaking invariant! */
+ reallymarkobject(g, v); /* restore it */
}
void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
- o->gch.next = G(L)->rootgc;
- G(L)->rootgc = o;
- o->gch.marked = 0;
+ global_State *g = G(L);
+ o->gch.next = g->rootgc;
+ g->rootgc = o;
+ o->gch.marked = luaC_white(g);
o->gch.tt = tt;
}
+
+void luaC_linkupval (lua_State *L, UpVal *uv) {
+ global_State *g = G(L);
+ GCObject *o = obj2gco(uv);
+ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
+ g->rootgc = o;
+ if (isgray(o)) {
+ if (g->gcstate == GCSpropagate) {
+ gray2black(o); /* closed upvalues need barrier */
+ luaC_barrier(L, uv, uv->v);
+ }
+ else { /* sweep phase: sweep it (turning it into white) */
+ makewhite(g, o);
+ lua_assert(g->gcstate != GCSfinalize);
+ }
+ }
+}
+
diff --git a/src/lgc.h b/src/lgc.h
index 3f4d7486..1ff59860 100644
--- a/src/lgc.h
+++ b/src/lgc.h
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.h,v 1.19a 2003/02/28 19:45:15 roberto Exp $
+** $Id: lgc.h,v 2.5 2004/03/15 21:04:33 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -11,15 +11,84 @@
#include "lobject.h"
-#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \
- if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); }
+/*
+** Possible states of the Garbage Collector
+*/
+#define GCSpropagate 0
+#define GCSsweepstring 1
+#define GCSsweep 2
+#define GCSfinalize 3
+
+
+/*
+** some userful bit tricks
+*/
+#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
+#define setbits(x,m) ((x) |= (m))
+#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 resetbit(x,b) resetbits(x, bitmask(b))
+#define testbit(x,b) testbits(x, bitmask(b))
+#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
+#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
+#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2)))
+
+
+
+/*
+** Layout for bit use in `marked' field:
+** bit 0 - object is gray
+** bit 1 - object is black
+** bit 2 - For userdata: is finalized;
+ for tables: has weak keys
+** bit 3 - for tables: has weak values
+** bit 4 - object is fixed (should not be collected)
+*/
+
+#define WHITE0BIT 0
+#define WHITE1BIT 1
+#define BLACKBIT 2
+#define FINALIZEDBIT 3
+#define KEYWEAKBIT 3
+#define VALUEWEAKBIT 4
+#define FIXEDBIT 5
+
+
+#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 changewhite(x) ((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT))
+
+#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
+
+#define luaC_white(g) cast(lu_byte, (g)->currentwhite)
+
+
+#define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \
+ luaC_step(L); }
+
+
+#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
+ luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
+#define luaC_objbarrier(L,p,o) \
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
+ luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
-size_t luaC_separateudata (lua_State *L);
+size_t luaC_separateudata (lua_State *L, int all);
void luaC_callGCTM (lua_State *L);
-void luaC_sweep (lua_State *L, int all);
-void luaC_collectgarbage (lua_State *L);
+void luaC_sweepall (lua_State *L);
+void luaC_step (lua_State *L);
+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);
#endif
diff --git a/src/lib/RCS b/src/lib/RCS
new file mode 120000
index 00000000..1ae38936
--- /dev/null
+++ b/src/lib/RCS
@@ -0,0 +1 @@
+../RCS \ No newline at end of file
diff --git a/src/lib/lauxlib.c b/src/lib/lauxlib.c
index ee2d1339..96131019 100644
--- a/src/lib/lauxlib.c
+++ b/src/lib/lauxlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.c,v 1.100 2003/04/07 14:35:00 roberto Exp $
+** $Id: lauxlib.c,v 1.110 2004/03/23 16:38:43 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -9,6 +9,7 @@
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
@@ -74,7 +75,7 @@ static void tag_error (lua_State *L, int narg, int tag) {
LUALIB_API void luaL_where (lua_State *L, int level) {
lua_Debug ar;
if (lua_getstack(L, level, &ar)) { /* check function at level */
- lua_getinfo(L, "Snl", &ar); /* get info about it */
+ lua_getinfo(L, "Sl", &ar); /* get info about it */
if (ar.currentline > 0) { /* is there info? */
lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
return;
@@ -107,15 +108,13 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
- lua_pushstring(L, tname);
- lua_rawget(L, LUA_REGISTRYINDEX); /* get registry.name */
+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
if (!lua_isnil(L, -1)) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
lua_pop(L, 1);
lua_newtable(L); /* create metatable */
- lua_pushstring(L, tname);
- lua_pushvalue(L, -2);
- lua_rawset(L, LUA_REGISTRYINDEX); /* registry.name = metatable */
+ lua_pushvalue(L, -1);
+ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
lua_pushvalue(L, -1);
lua_pushstring(L, tname);
lua_rawset(L, LUA_REGISTRYINDEX); /* registry[metatable] = name */
@@ -124,8 +123,7 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
LUALIB_API void luaL_getmetatable (lua_State *L, const char *tname) {
- lua_pushstring(L, tname);
- lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_getfield(L, LUA_REGISTRYINDEX, tname);
}
@@ -196,11 +194,25 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
}
+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
+ lua_Integer d = lua_tointeger(L, narg);
+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
+ tag_error(L, narg, LUA_TNUMBER);
+ return d;
+}
+
+
+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
+ lua_Integer def) {
+ if (lua_isnoneornil(L, narg)) return def;
+ else return luaL_checkinteger(L, narg);
+}
+
+
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
if (!lua_getmetatable(L, obj)) /* no metatable? */
return 0;
- lua_pushstring(L, event);
- lua_rawget(L, -2);
+ lua_getfield(L, -1, event);
if (lua_isnil(L, -1)) {
lua_pop(L, 2); /* remove metatable and metafield */
return 0;
@@ -225,24 +237,23 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
const luaL_reg *l, int nup) {
if (libname) {
- lua_pushstring(L, libname);
- lua_gettable(L, LUA_GLOBALSINDEX); /* check whether lib already exists */
+ /* check whether lib already exists */
+ lua_getglobal(L, libname);
if (lua_isnil(L, -1)) { /* no? */
lua_pop(L, 1);
lua_newtable(L); /* create it */
- lua_pushstring(L, libname);
- lua_pushvalue(L, -2);
- lua_settable(L, LUA_GLOBALSINDEX); /* register it with given name */
+ lua_pushvalue(L, -1);
+ /* register it with given name */
+ lua_setglobal(L, libname);
}
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
}
for (; l->name; l++) {
int i;
- lua_pushstring(L, l->name);
for (i=0; i<nup; i++) /* copy upvalues to the top */
- lua_pushvalue(L, -(nup+1));
+ lua_pushvalue(L, -nup);
lua_pushcclosure(L, l->func, nup);
- lua_settable(L, -(nup+3));
+ lua_setfield(L, -(nup+2), l->name);
}
lua_pop(L, nup); /* remove upvalues */
}
@@ -256,8 +267,7 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
*/
static int checkint (lua_State *L, int topop) {
- int n = (int)lua_tonumber(L, -1);
- if (n == 0 && !lua_isnumber(L, -1)) n = -1;
+ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
lua_pop(L, topop);
return n;
}
@@ -270,9 +280,8 @@ static void getsizes (lua_State *L) {
lua_newtable(L); /* create it */
lua_pushvalue(L, -1); /* `size' will be its own metatable */
lua_setmetatable(L, -2);
- lua_pushliteral(L, "__mode");
- lua_pushliteral(L, "k");
- lua_rawset(L, -3); /* metatable(N).__mode = "k" */
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */
lua_pushvalue(L, -1);
lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF); /* store in register */
}
@@ -281,33 +290,23 @@ static void getsizes (lua_State *L) {
void luaL_setn (lua_State *L, int t, int n) {
t = abs_index(L, t);
- lua_pushliteral(L, "n");
- lua_rawget(L, t);
- if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
- lua_pushliteral(L, "n"); /* use it */
- lua_pushnumber(L, (lua_Number)n);
- lua_rawset(L, t);
- }
- else { /* use `sizes' */
- getsizes(L);
- lua_pushvalue(L, t);
- lua_pushnumber(L, (lua_Number)n);
- lua_rawset(L, -3); /* sizes[t] = n */
- lua_pop(L, 1); /* remove `sizes' */
- }
+ getsizes(L);
+ lua_pushvalue(L, t);
+ lua_pushinteger(L, n);
+ lua_rawset(L, -3); /* sizes[t] = n */
+ lua_pop(L, 1); /* remove `sizes' */
}
int luaL_getn (lua_State *L, int t) {
int n;
t = abs_index(L, t);
- lua_pushliteral(L, "n"); /* try t.n */
- lua_rawget(L, t);
- if ((n = checkint(L, 1)) >= 0) return n;
- getsizes(L); /* else try sizes[t] */
+ getsizes(L); /* try sizes[t] */
lua_pushvalue(L, t);
lua_rawget(L, -2);
if ((n = checkint(L, 2)) >= 0) return n;
+ lua_getfield(L, t, "n"); /* else try t.n */
+ if ((n = checkint(L, 1)) >= 0) return n;
for (n = 1; ; n++) { /* else must count elements */
lua_rawgeti(L, t, n);
if (lua_isnil(L, -1)) break;
@@ -424,7 +423,7 @@ LUALIB_API int luaL_ref (lua_State *L, int t) {
return LUA_REFNIL; /* `nil' has a unique fixed reference */
}
lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
- ref = (int)lua_tonumber(L, -1); /* ref = t[FREELIST_REF] */
+ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
lua_pop(L, 1); /* remove it from stack */
if (ref != 0) { /* any free element? */
lua_rawgeti(L, t, ref); /* remove it from list */
@@ -447,7 +446,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
t = abs_index(L, t);
lua_rawgeti(L, t, FREELIST_REF);
lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
- lua_pushnumber(L, (lua_Number)ref);
+ lua_pushinteger(L, ref);
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
}
}
@@ -461,6 +460,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
*/
typedef struct LoadF {
+ int extraline;
FILE *f;
char buff[LUAL_BUFFERSIZE];
} LoadF;
@@ -469,6 +469,11 @@ typedef struct LoadF {
static const char *getF (lua_State *L, void *ud, size_t *size) {
LoadF *lf = (LoadF *)ud;
(void)L;
+ if (lf->extraline) {
+ lf->extraline = 0;
+ *size = 1;
+ return "\n";
+ }
if (feof(lf->f)) return NULL;
*size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f);
return (*size > 0) ? lf->buff : NULL;
@@ -488,6 +493,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
int status, readstatus;
int c;
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
+ lf.extraline = 0;
if (filename == NULL) {
lua_pushliteral(L, "=stdin");
lf.f = stdin;
@@ -495,14 +501,23 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
else {
lua_pushfstring(L, "@%s", filename);
lf.f = fopen(filename, "r");
+ if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */
}
- if (lf.f == NULL) return errfile(L, fnameindex); /* unable to open file */
- c = ungetc(getc(lf.f), lf.f);
- if (!(isspace(c) || isprint(c)) && lf.f != stdin) { /* binary file? */
+ c = getc(lf.f);
+ if (c == '#') { /* Unix exec. file? */
+ lf.extraline = 1;
+ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
+ if (c == '\n') c = getc(lf.f);
+ }
+ if (c == LUA_SIGNATURE[0] && lf.f != stdin) { /* binary file? */
fclose(lf.f);
lf.f = fopen(filename, "rb"); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */
+ /* skip eventual `#!...' */
+ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
+ lf.extraline = 0;
}
+ ungetc(c, lf.f);
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
readstatus = ferror(lf.f);
if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */
@@ -542,6 +557,22 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
/* }====================================================== */
+static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
+ (void)ud;
+ if (nsize == 0) {
+ free(ptr);
+ return NULL;
+ }
+ else
+ return realloc(ptr, nsize);
+}
+
+
+LUALIB_API lua_State *luaL_newstate (void) {
+ return lua_newstate(l_alloc, NULL);
+}
+
+
/*
** {======================================================
** compatibility code
diff --git a/src/lib/lbaselib.c b/src/lib/lbaselib.c
index b6a4baed..42b0355a 100644
--- a/src/lib/lbaselib.c
+++ b/src/lib/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.130b 2003/04/03 13:35:34 roberto Exp $
+** $Id: lbaselib.c,v 1.140 2004/03/09 17:34:35 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -78,10 +78,8 @@ static int luaB_tonumber (lua_State *L) {
static int luaB_error (lua_State *L) {
int level = luaL_optint(L, 2, 1);
- luaL_checkany(L, 1);
- if (!lua_isstring(L, 1) || level == 0)
- lua_pushvalue(L, 1); /* propagate error message without changes */
- else { /* add extra information */
+ lua_settop(L, 1);
+ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
luaL_where(L, level);
lua_pushvalue(L, 1);
lua_concat(L, 2);
@@ -187,15 +185,32 @@ static int luaB_rawset (lua_State *L) {
static int luaB_gcinfo (lua_State *L) {
- lua_pushnumber(L, (lua_Number)lua_getgccount(L));
- lua_pushnumber(L, (lua_Number)lua_getgcthreshold(L));
- return 2;
+ lua_pushinteger(L, lua_getgccount(L));
+ return 1;
}
static int luaB_collectgarbage (lua_State *L) {
- lua_setgcthreshold(L, luaL_optint(L, 1, 0));
- return 0;
+ static const char *const opts[] = {"stop", "restart", "collect", "count",
+ NULL};
+ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART,
+ LUA_GCCOLLECT, LUA_GCCOUNT};
+ int o;
+ int ex;
+#if 1
+ if (lua_isnumber(L, 1)) {
+ int v = lua_tointeger(L, 1);
+ lua_settop(L, 0);
+ if (v == 0) lua_pushstring(L, "collect");
+ else if (v >= 10000) lua_pushstring(L, "stop");
+ else lua_pushstring(L, "restart");
+ }
+#endif
+ o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts);
+ ex = luaL_optint(L, 2, 0);
+ luaL_argcheck(L, o >= 0, 1, "invalid option");
+ lua_pushinteger(L, lua_gc(L, optsnum[o], ex));
+ return 1;
}
@@ -220,8 +235,7 @@ static int luaB_next (lua_State *L) {
static int luaB_pairs (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
- lua_pushliteral(L, "next");
- lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
+ lua_getglobal(L, "next"); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
return 3;
@@ -229,19 +243,18 @@ static int luaB_pairs (lua_State *L) {
static int luaB_ipairs (lua_State *L) {
- lua_Number i = lua_tonumber(L, 2);
+ int i = (int)lua_tointeger(L, 2);
luaL_checktype(L, 1, LUA_TTABLE);
if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */
- lua_pushliteral(L, "ipairs");
- lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
+ lua_getglobal(L, "ipairs"); /* return generator, */
lua_pushvalue(L, 1); /* state, */
- lua_pushnumber(L, 0); /* and initial value */
+ lua_pushinteger(L, 0); /* and initial value */
return 3;
}
else { /* `for' step */
i++; /* next value */
- lua_pushnumber(L, i);
- lua_rawgeti(L, 1, (int)i);
+ lua_pushinteger(L, i);
+ lua_rawgeti(L, 1, i);
return (lua_isnil(L, -1)) ? 0 : 2;
}
}
@@ -272,11 +285,51 @@ static int luaB_loadfile (lua_State *L) {
}
+struct Aux_load {
+ int func;
+ int res;
+};
+
+
+static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
+ struct Aux_load *al = (struct Aux_load *)ud;
+ luaL_unref(L, al->res, LUA_REGISTRYINDEX);
+ lua_getref(L, al->func);
+ lua_call(L, 0, 1);
+ if (lua_isnil(L, -1)) {
+ *size = 0;
+ return NULL;
+ }
+ else if (lua_isstring(L, -1)) {
+ const char *res = lua_tostring(L, -1);
+ *size = lua_strlen(L, -1);
+ al->res = luaL_ref(L, LUA_REGISTRYINDEX);
+ return res;
+ }
+ else luaL_error(L, "reader function must return a string");
+ return NULL; /* to avoid warnings */
+}
+
+
+static int luaB_load (lua_State *L) {
+ struct Aux_load al;
+ int status;
+ const char *cname = luaL_optstring(L, 2, "=(load)");
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+ lua_settop(L, 1);
+ al.func = luaL_ref(L, LUA_REGISTRYINDEX);
+ al.res = LUA_REFNIL;
+ status = lua_load(L, generic_reader, &al, cname);
+ luaL_unref(L, al.func, LUA_REGISTRYINDEX);
+ luaL_unref(L, al.res, LUA_REGISTRYINDEX);
+ return load_aux(L, status);
+}
+
+
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
int n = lua_gettop(L);
- int status = luaL_loadfile(L, fname);
- if (status != 0) lua_error(L);
+ if (luaL_loadfile(L, fname) != 0) lua_error(L);
lua_call(L, 0, LUA_MULTRET);
return lua_gettop(L) - n;
}
@@ -325,7 +378,9 @@ static int luaB_xpcall (lua_State *L) {
static int luaB_tostring (lua_State *L) {
- char buff[128];
+ char buff[4*sizeof(void *) + 2]; /* enough space for a `%p' */
+ const char *tn = "";
+ const void *p = NULL;
luaL_checkany(L, 1);
if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
return 1; /* use its value */
@@ -339,24 +394,29 @@ static int luaB_tostring (lua_State *L) {
case LUA_TBOOLEAN:
lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
return 1;
+ case LUA_TNIL:
+ lua_pushliteral(L, "nil");
+ return 1;
case LUA_TTABLE:
- sprintf(buff, "table: %p", lua_topointer(L, 1));
+ p = lua_topointer(L, 1);
+ tn = "table";
break;
case LUA_TFUNCTION:
- sprintf(buff, "function: %p", lua_topointer(L, 1));
+ p = lua_topointer(L, 1);
+ tn = "function";
break;
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
- sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
+ p = lua_touserdata(L, 1);
+ tn = "userdata";
break;
case LUA_TTHREAD:
- sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1));
+ p = lua_tothread(L, 1);
+ tn = "thread";
break;
- case LUA_TNIL:
- lua_pushliteral(L, "nil");
- return 1;
}
- lua_pushstring(L, buff);
+ sprintf(buff, "%p", p);
+ lua_pushfstring(L, "%s: %s", tn, buff);
return 1;
}
@@ -441,14 +501,14 @@ static void pushcomposename (lua_State *L) {
const char *wild;
int n = 1;
while ((wild = strchr(path, LUA_PATH_MARK)) != NULL) {
- /* is there stack space for prefix, name, and eventual last sufix? */
+ /* is there stack space for prefix, name, and eventual last suffix? */
luaL_checkstack(L, 3, "too many marks in a path component");
lua_pushlstring(L, path, wild - path); /* push prefix */
lua_pushvalue(L, 1); /* push package name (in place of MARK) */
path = wild + 1; /* continue after MARK */
n += 2;
}
- lua_pushstring(L, path); /* push last sufix (`n' already includes this) */
+ lua_pushstring(L, path); /* push last suffix (`n' already includes this) */
lua_concat(L, n);
}
@@ -530,6 +590,7 @@ static const luaL_reg base_funcs[] = {
{"loadfile", luaB_loadfile},
{"dofile", luaB_dofile},
{"loadstring", luaB_loadstring},
+ {"load", luaB_load},
{"require", luaB_require},
{NULL, NULL}
};
@@ -645,23 +706,19 @@ static const luaL_reg co_funcs[] = {
static void base_open (lua_State *L) {
- lua_pushliteral(L, "_G");
lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_openlib(L, NULL, base_funcs, 0); /* open lib into global table */
- lua_pushliteral(L, "_VERSION");
lua_pushliteral(L, LUA_VERSION);
- lua_rawset(L, -3); /* set global _VERSION */
+ lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */
/* `newproxy' needs a weaktable as upvalue */
- lua_pushliteral(L, "newproxy");
lua_newtable(L); /* new table `w' */
lua_pushvalue(L, -1); /* `w' will be its own metatable */
lua_setmetatable(L, -2);
- lua_pushliteral(L, "__mode");
- lua_pushliteral(L, "k");
- lua_rawset(L, -3); /* metatable(w).__mode = "k" */
+ lua_pushliteral(L, "kv");
+ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
lua_pushcclosure(L, luaB_newproxy, 1);
- lua_rawset(L, -3); /* set global `newproxy' */
- lua_rawset(L, -1); /* set global _G */
+ lua_setfield(L, -2, "newproxy"); /* set global `newproxy' */
+ lua_setfield(L, -1, "_G"); /* set global _G */
}
@@ -670,6 +727,6 @@ LUALIB_API int luaopen_base (lua_State *L) {
luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0);
lua_newtable(L);
lua_setglobal(L, REQTAB);
- return 0;
+ return 2;
}
diff --git a/src/lib/ldblib.c b/src/lib/ldblib.c
index 6dc9b64c..dd4e0363 100644
--- a/src/lib/ldblib.c
+++ b/src/lib/ldblib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldblib.c,v 1.80 2003/04/03 13:35:34 roberto Exp $
+** $Id: ldblib.c,v 1.84 2003/11/05 11:59:14 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -19,37 +19,50 @@
static void settabss (lua_State *L, const char *i, const char *v) {
- lua_pushstring(L, i);
lua_pushstring(L, v);
- lua_rawset(L, -3);
+ lua_setfield(L, -2, i);
}
static void settabsi (lua_State *L, const char *i, int v) {
- lua_pushstring(L, i);
- lua_pushnumber(L, (lua_Number)v);
- lua_rawset(L, -3);
+ lua_pushinteger(L, v);
+ lua_setfield(L, -2, i);
+}
+
+
+static lua_State *getthread (lua_State *L, int *arg) {
+ if (lua_isthread(L, 1)) {
+ *arg = 1;
+ return lua_tothread(L, 1);
+ }
+ else {
+ *arg = 0;
+ return L;
+ }
}
static int getinfo (lua_State *L) {
lua_Debug ar;
- const char *options = luaL_optstring(L, 2, "flnSu");
- if (lua_isnumber(L, 1)) {
- if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ const char *options = luaL_optstring(L, arg+2, "flnSu");
+ if (lua_isnumber(L, arg+1)) {
+ if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
lua_pushnil(L); /* level out of range */
return 1;
}
}
- else if (lua_isfunction(L, 1)) {
+ else if (lua_isfunction(L, arg+1)) {
lua_pushfstring(L, ">%s", options);
options = lua_tostring(L, -1);
- lua_pushvalue(L, 1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
}
else
- return luaL_argerror(L, 1, "function or level expected");
- if (!lua_getinfo(L, options, &ar))
- return luaL_argerror(L, 2, "invalid option");
+ return luaL_argerror(L, arg+1, "function or level expected");
+ if (!lua_getinfo(L1, options, &ar))
+ return luaL_argerror(L, arg+2, "invalid option");
lua_newtable(L);
for (; *options; options++) {
switch (*options) {
@@ -70,9 +83,11 @@ static int getinfo (lua_State *L) {
settabss(L, "namewhat", ar.namewhat);
break;
case 'f':
- lua_pushliteral(L, "func");
- lua_pushvalue(L, -3);
- lua_rawset(L, -3);
+ if (L == L1)
+ lua_pushvalue(L, -2);
+ else
+ lua_xmove(L1, L, 1);
+ lua_setfield(L, -2, "func");
break;
}
}
@@ -81,12 +96,15 @@ static int getinfo (lua_State *L) {
static int getlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
const char *name;
- if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
- return luaL_argerror(L, 1, "level out of range");
- name = lua_getlocal(L, &ar, luaL_checkint(L, 2));
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
if (name) {
+ lua_xmove(L1, L, 1);
lua_pushstring(L, name);
lua_pushvalue(L, -2);
return 2;
@@ -99,11 +117,15 @@ static int getlocal (lua_State *L) {
static int setlocal (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
- if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
- return luaL_argerror(L, 1, "level out of range");
- luaL_checkany(L, 3);
- lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2)));
+ if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
+ return luaL_argerror(L, arg+1, "level out of range");
+ luaL_checkany(L, arg+3);
+ lua_settop(L, arg+3);
+ lua_xmove(L, L1, 1);
+ lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
return 1;
}
@@ -141,16 +163,16 @@ static void hookf (lua_State *L, lua_Debug *ar) {
{"call", "return", "line", "count", "tail return"};
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_pushlightuserdata(L, L);
+ lua_rawget(L, -2);
if (lua_isfunction(L, -1)) {
lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0)
- lua_pushnumber(L, (lua_Number)ar->currentline);
+ lua_pushinteger(L, ar->currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
}
- else
- lua_pop(L, 1); /* pop result from gettable */
}
@@ -174,36 +196,59 @@ static char *unmakemask (int mask, char *smask) {
}
+static void gethooktable (lua_State *L) {
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ lua_newtable(L);
+ lua_pushlightuserdata(L, (void *)&KEY_HOOK);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+ }
+}
+
+
static int sethook (lua_State *L) {
- if (lua_isnoneornil(L, 1)) {
- lua_settop(L, 1);
- lua_sethook(L, NULL, 0, 0); /* turn off hooks */
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
+ if (lua_isnoneornil(L, arg+1)) {
+ lua_settop(L, arg+1);
+ lua_sethook(L1, NULL, 0, 0); /* turn off hooks */
}
else {
- const char *smask = luaL_checkstring(L, 2);
- int count = luaL_optint(L, 3, 0);
- luaL_checktype(L, 1, LUA_TFUNCTION);
- lua_sethook(L, hookf, makemask(smask, count), count);
+ const char *smask = luaL_checkstring(L, arg+2);
+ int count = luaL_optint(L, arg+3, 0);
+ luaL_checktype(L, arg+1, LUA_TFUNCTION);
+ lua_sethook(L1, hookf, makemask(smask, count), count);
}
- lua_pushlightuserdata(L, (void *)&KEY_HOOK);
- lua_pushvalue(L, 1);
- lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */
+ gethooktable(L1);
+ lua_pushlightuserdata(L1, L1);
+ lua_pushvalue(L, arg+1);
+ lua_xmove(L, L1, 1);
+ lua_rawset(L1, -3); /* set new hook */
+ lua_pop(L1, 1); /* remove hook table */
return 0;
}
static int gethook (lua_State *L) {
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
char buff[5];
- int mask = lua_gethookmask(L);
- lua_Hook hook = lua_gethook(L);
+ int mask = lua_gethookmask(L1);
+ lua_Hook hook = lua_gethook(L1);
if (hook != NULL && hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else {
- lua_pushlightuserdata(L, (void *)&KEY_HOOK);
- lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
+ gethooktable(L1);
+ lua_pushlightuserdata(L1, L1);
+ lua_rawget(L1, -2); /* get hook */
+ lua_remove(L1, -2); /* remove hook table */
+ lua_xmove(L1, L, 1);
}
lua_pushstring(L, unmakemask(mask, buff));
- lua_pushnumber(L, (lua_Number)lua_gethookcount(L));
+ lua_pushinteger(L, lua_gethookcount(L1));
return 3;
}
@@ -227,27 +272,29 @@ static int debug (lua_State *L) {
static int errorfb (lua_State *L) {
int level = 1; /* skip level 0 (it's this function) */
int firstpart = 1; /* still before eventual `...' */
+ int arg;
+ lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
- if (lua_gettop(L) == 0)
+ if (lua_gettop(L) == arg)
lua_pushliteral(L, "");
- else if (!lua_isstring(L, 1)) return 1; /* no string message */
+ else if (!lua_isstring(L, arg+1)) return 1; /* no string message */
else lua_pushliteral(L, "\n");
lua_pushliteral(L, "stack traceback:");
- while (lua_getstack(L, level++, &ar)) {
+ while (lua_getstack(L1, level++, &ar)) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
- if (!lua_getstack(L, level+LEVELS2, &ar))
+ if (!lua_getstack(L1, level+LEVELS2, &ar))
level--; /* keep going */
else {
lua_pushliteral(L, "\n\t..."); /* too many levels */
- while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */
+ while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\n\t");
- lua_getinfo(L, "Snl", &ar);
+ lua_getinfo(L1, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
@@ -268,9 +315,9 @@ static int errorfb (lua_State *L) {
ar.short_src, ar.linedefined);
}
}
- lua_concat(L, lua_gettop(L));
+ lua_concat(L, lua_gettop(L) - arg);
}
- lua_concat(L, lua_gettop(L));
+ lua_concat(L, lua_gettop(L) - arg);
return 1;
}
@@ -291,9 +338,8 @@ static const luaL_reg dblib[] = {
LUALIB_API int luaopen_debug (lua_State *L) {
luaL_openlib(L, LUA_DBLIBNAME, dblib, 0);
- lua_pushliteral(L, "_TRACEBACK");
lua_pushcfunction(L, errorfb);
- lua_settable(L, LUA_GLOBALSINDEX);
+ lua_setglobal(L, "_TRACEBACK");
return 1;
}
diff --git a/src/lib/liolib.c b/src/lib/liolib.c
index 96b38831..1815c96b 100644
--- a/src/lib/liolib.c
+++ b/src/lib/liolib.c
@@ -1,5 +1,5 @@
/*
-** $Id: liolib.c,v 2.39a 2003/03/19 21:16:12 roberto Exp $
+** $Id: liolib.c,v 2.49 2003/10/10 13:29:28 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -37,16 +37,12 @@
** by default, posix systems get `popen'
*/
#ifndef USE_POPEN
-#ifdef _POSIX_C_SOURCE
-#if _POSIX_C_SOURCE >= 2
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 2
#define USE_POPEN 1
-#endif
-#endif
-#endif
-
-#ifndef USE_POPEN
+#else
#define USE_POPEN 0
#endif
+#endif
@@ -65,8 +61,8 @@
#define FILEHANDLE "FILE*"
-#define IO_INPUT "_input"
-#define IO_OUTPUT "_output"
+#define IO_INPUT 1
+#define IO_OUTPUT 2
static int pushresult (lua_State *L, int i, const char *filename) {
@@ -80,7 +76,7 @@ static int pushresult (lua_State *L, int i, const char *filename) {
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
else
lua_pushfstring(L, "%s", strerror(errno));
- lua_pushnumber(L, errno);
+ lua_pushinteger(L, errno);
return 3;
}
}
@@ -127,23 +123,6 @@ static FILE **newfile (lua_State *L) {
}
-/*
-** assumes that top of the stack is the `io' library, and next is
-** the `io' metatable
-*/
-static void registerfile (lua_State *L, FILE *f, const char *name,
- const char *impname) {
- lua_pushstring(L, name);
- *newfile(L) = f;
- if (impname) {
- lua_pushstring(L, impname);
- lua_pushvalue(L, -2);
- lua_settable(L, -6); /* metatable[impname] = file */
- }
- lua_settable(L, -3); /* io[name] = file */
-}
-
-
static int aux_close (lua_State *L) {
FILE *f = tofile(L, 1);
if (f == stdin || f == stdout || f == stderr)
@@ -158,10 +137,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_pushstring(L, IO_OUTPUT);
- lua_rawget(L, lua_upvalueindex(1));
- }
+ if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE)
+ lua_rawgeti(L, lua_upvalueindex(1), IO_OUTPUT);
return pushresult(L, aux_close(L), NULL);
}
@@ -175,7 +152,7 @@ static int io_gc (lua_State *L) {
static int io_tostring (lua_State *L) {
- char buff[128];
+ char buff[4*sizeof(void *) + 2]; /* enough space for a `%p' */
FILE **f = topfile(L, 1);
if (*f == NULL)
strcpy(buff, "closed");
@@ -216,17 +193,15 @@ static int io_tmpfile (lua_State *L) {
}
-static FILE *getiofile (lua_State *L, const char *name) {
- lua_pushstring(L, name);
- lua_rawget(L, lua_upvalueindex(1));
+static FILE *getiofile (lua_State *L, int f) {
+ lua_rawgeti(L, lua_upvalueindex(1), f);
return tofile(L, -1);
}
-static int g_iofile (lua_State *L, const char *name, const char *mode) {
+static int g_iofile (lua_State *L, int f, const char *mode) {
if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1);
- lua_pushstring(L, name);
if (filename) {
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
@@ -239,11 +214,10 @@ static int g_iofile (lua_State *L, const char *name, const char *mode) {
tofile(L, 1); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
- lua_rawset(L, lua_upvalueindex(1));
+ lua_rawseti(L, lua_upvalueindex(1), f);
}
/* return current value */
- lua_pushstring(L, name);
- lua_rawget(L, lua_upvalueindex(1));
+ lua_rawgeti(L, lua_upvalueindex(1), f);
return 1;
}
@@ -262,8 +236,7 @@ static int io_readline (lua_State *L);
static void aux_lines (lua_State *L, int idx, int close) {
- lua_pushliteral(L, FILEHANDLE);
- lua_rawget(L, LUA_REGISTRYINDEX);
+ lua_getfield(L, LUA_REGISTRYINDEX, FILEHANDLE);
lua_pushvalue(L, idx);
lua_pushboolean(L, close); /* close/not close file when finished */
lua_pushcclosure(L, io_readline, 3);
@@ -279,8 +252,8 @@ static int f_lines (lua_State *L) {
static int io_lines (lua_State *L) {
if (lua_isnoneornil(L, 1)) { /* no arguments? */
- lua_pushstring(L, IO_INPUT);
- lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */
+ /* will iterate over default input */
+ lua_rawgeti(L, lua_upvalueindex(1), IO_INPUT);
return f_lines(L);
}
else {
@@ -372,7 +345,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
success = 1;
for (n = first; nargs-- && success; n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
- size_t l = (size_t)lua_tonumber(L, n);
+ size_t l = (size_t)lua_tointeger(L, n);
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
}
else {
@@ -467,18 +440,29 @@ static int f_seek (lua_State *L) {
static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L, 1);
int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames);
- long offset = luaL_optlong(L, 3, 0);
+ lua_Integer offset = luaL_optinteger(L, 3, 0);
luaL_argcheck(L, op != -1, 2, "invalid mode");
op = fseek(f, offset, mode[op]);
if (op)
return pushresult(L, 0, NULL); /* error */
else {
- lua_pushnumber(L, ftell(f));
+ lua_pushinteger(L, ftell(f));
return 1;
}
}
+static int f_setvbuf (lua_State *L) {
+ static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
+ static const char *const modenames[] = {"no", "full", "line", NULL};
+ FILE *f = tofile(L, 1);
+ int op = luaL_findstring(luaL_checkstring(L, 2), modenames);
+ luaL_argcheck(L, op != -1, 2, "invalid mode");
+ return pushresult(L, setvbuf(f, NULL, mode[op], 0) == 0, NULL);
+}
+
+
+
static int io_flush (lua_State *L) {
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
@@ -510,6 +494,7 @@ static const luaL_reg flib[] = {
{"read", f_read},
{"lines", f_lines},
{"seek", f_seek},
+ {"setvbuf", f_setvbuf},
{"write", f_write},
{"close", io_close},
{"__gc", io_gc},
@@ -520,10 +505,14 @@ static const luaL_reg flib[] = {
static void createmeta (lua_State *L) {
luaL_newmetatable(L, FILEHANDLE); /* create new metatable for file handles */
+ /* create (and set) default files */
+ *newfile(L) = stdin;
+ lua_rawseti(L, -2, IO_INPUT);
+ *newfile(L) = stdout;
+ lua_rawseti(L, -2, IO_OUTPUT);
/* file methods */
- lua_pushliteral(L, "__index");
- lua_pushvalue(L, -2); /* push metatable */
- lua_rawset(L, -3); /* metatable.__index = metatable */
+ lua_pushvalue(L, -1); /* push metatable */
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_openlib(L, NULL, flib, 0);
}
@@ -537,7 +526,7 @@ static void createmeta (lua_State *L) {
*/
static int io_execute (lua_State *L) {
- lua_pushnumber(L, system(luaL_checkstring(L, 1)));
+ lua_pushinteger(L, system(luaL_checkstring(L, 1)));
return 1;
}
@@ -591,7 +580,7 @@ static int io_clock (lua_State *L) {
static void setfield (lua_State *L, const char *key, int value) {
lua_pushstring(L, key);
- lua_pushnumber(L, value);
+ lua_pushinteger(L, value);
lua_rawset(L, -3);
}
@@ -603,8 +592,7 @@ static void setboolfield (lua_State *L, const char *key, int value) {
static int getboolfield (lua_State *L, const char *key) {
int res;
- lua_pushstring(L, key);
- lua_gettable(L, -2);
+ lua_getfield(L, -1, key);
res = lua_toboolean(L, -1);
lua_pop(L, 1);
return res;
@@ -613,12 +601,11 @@ static int getboolfield (lua_State *L, const char *key) {
static int getfield (lua_State *L, const char *key, int d) {
int res;
- lua_pushstring(L, key);
- lua_gettable(L, -2);
+ lua_getfield(L, -1, key);
if (lua_isnumber(L, -1))
- res = (int)(lua_tonumber(L, -1));
+ res = (int)lua_tointeger(L, -1);
else {
- if (d == -2)
+ if (d < 0)
return luaL_error(L, "field `%s' missing in date table", key);
res = d;
}
@@ -629,10 +616,9 @@ static int getfield (lua_State *L, const char *key, int d) {
static int io_date (lua_State *L) {
const char *s = luaL_optstring(L, 1, "%c");
- time_t t = (time_t)(luaL_optnumber(L, 2, -1));
+ lua_Number n = luaL_optnumber(L, 2, -1);
+ time_t t = (n == -1) ? time(NULL) : (time_t)n;
struct tm *stm;
- if (t == (time_t)(-1)) /* no time given? */
- t = time(NULL); /* use current time */
if (*s == '!') { /* UTC? */
stm = gmtime(&t);
s++; /* skip `!' */
@@ -642,7 +628,7 @@ static int io_date (lua_State *L) {
if (stm == NULL) /* invalid date? */
lua_pushnil(L);
else if (strcmp(s, "*t") == 0) {
- lua_newtable(L);
+ lua_createtable(L, 0, 9); /* 9 = number of fields */
setfield(L, "sec", stm->tm_sec);
setfield(L, "min", stm->tm_min);
setfield(L, "hour", stm->tm_hour);
@@ -675,9 +661,9 @@ static int io_time (lua_State *L) {
ts.tm_sec = getfield(L, "sec", 0);
ts.tm_min = getfield(L, "min", 0);
ts.tm_hour = getfield(L, "hour", 12);
- ts.tm_mday = getfield(L, "day", -2);
- ts.tm_mon = getfield(L, "month", -2) - 1;
- ts.tm_year = getfield(L, "year", -2) - 1900;
+ ts.tm_mday = getfield(L, "day", -1);
+ ts.tm_mon = getfield(L, "month", -1) - 1;
+ ts.tm_year = getfield(L, "year", -1) - 1900;
ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts);
if (t == (time_t)(-1))
@@ -742,9 +728,15 @@ LUALIB_API int luaopen_io (lua_State *L) {
lua_pushvalue(L, -1);
luaL_openlib(L, LUA_IOLIBNAME, iolib, 1);
/* put predefined file handles into `io' table */
- registerfile(L, stdin, "stdin", IO_INPUT);
- registerfile(L, stdout, "stdout", IO_OUTPUT);
- registerfile(L, stderr, "stderr", NULL);
+ lua_pushliteral(L, "stdin");
+ lua_rawgeti(L, 2, IO_INPUT);
+ lua_rawset(L, 3);
+ lua_pushliteral(L, "stdout");
+ lua_rawgeti(L, 2, IO_OUTPUT);
+ lua_rawset(L, 3);
+ lua_pushliteral(L, "stderr");
+ *newfile(L) = stderr;
+ lua_rawset(L, 3);
return 1;
}
diff --git a/src/lib/lmathlib.c b/src/lib/lmathlib.c
index f074a56e..6041b2e3 100644
--- a/src/lib/lmathlib.c
+++ b/src/lib/lmathlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmathlib.c,v 1.56 2003/03/11 12:30:37 roberto Exp $
+** $Id: lmathlib.c,v 1.59 2003/11/05 11:59:14 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -128,7 +128,7 @@ static int math_rad (lua_State *L) {
static int math_frexp (lua_State *L) {
int e;
lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
- lua_pushnumber(L, e);
+ lua_pushinteger(L, e);
return 2;
}
@@ -179,14 +179,14 @@ static int math_random (lua_State *L) {
case 1: { /* only upper limit */
int u = luaL_checkint(L, 1);
luaL_argcheck(L, 1<=u, 1, "interval is empty");
- lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */
+ lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
break;
}
case 2: { /* lower and upper limits */
int l = luaL_checkint(L, 1);
int u = luaL_checkint(L, 2);
luaL_argcheck(L, l<=u, 2, "interval is empty");
- lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */
+ lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
break;
}
default: return luaL_error(L, "wrong number of arguments");
@@ -235,12 +235,10 @@ static const luaL_reg mathlib[] = {
*/
LUALIB_API int luaopen_math (lua_State *L) {
luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0);
- lua_pushliteral(L, "pi");
lua_pushnumber(L, PI);
- lua_settable(L, -3);
- lua_pushliteral(L, "__pow");
+ lua_setfield(L, -2, "pi");
lua_pushcfunction(L, math_pow);
- lua_settable(L, LUA_GLOBALSINDEX);
+ lua_setglobal(L, "__pow");
return 1;
}
diff --git a/src/lib/loadlib.c b/src/lib/loadlib.c
index ac4d697a..2a6b39e1 100644
--- a/src/lib/loadlib.c
+++ b/src/lib/loadlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: loadlib.c,v 1.4 2003/04/07 20:11:53 roberto Exp $
+** $Id: loadlib.c,v 1.5 2003/05/14 21:01:53 roberto Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
*
@@ -136,33 +136,13 @@ static int loadlib(lua_State *L)
** Those systems support dlopen, so they should have defined USE_DLOPEN.
** The default (no)implementation gives them a special error message.
*/
-#ifdef linux
-#define LOADLIB
-#endif
-
-#ifdef sun
-#define LOADLIB
-#endif
-
-#ifdef sgi
-#define LOADLIB
-#endif
-
-#ifdef BSD
-#define LOADLIB
-#endif
-
-#ifdef _WIN32
-#define LOADLIB
-#endif
-
-#ifdef LOADLIB
-#undef LOADLIB
+#if defined(linux) || defined(sun) || defined(sgi) || defined(BSD) || defined(_WIN32)
#define LOADLIB "`loadlib' not installed (check your Lua configuration)"
#else
#define LOADLIB "`loadlib' not supported"
#endif
+
static int loadlib(lua_State *L)
{
lua_pushnil(L);
diff --git a/src/lib/lstrlib.c b/src/lib/lstrlib.c
index 8752e3ab..36b226d2 100644
--- a/src/lib/lstrlib.c
+++ b/src/lib/lstrlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstrlib.c,v 1.98 2003/04/03 13:35:34 roberto Exp $
+** $Id: lstrlib.c,v 1.101 2004/01/02 11:54:14 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -25,13 +25,13 @@
#endif
-typedef long sint32; /* a signed version for size_t */
+typedef lua_Integer sint32; /* a signed version for size_t */
static int str_len (lua_State *L) {
size_t l;
luaL_checklstring(L, 1, &l);
- lua_pushnumber(L, (lua_Number)l);
+ lua_pushinteger(L, l);
return 1;
}
@@ -45,8 +45,8 @@ static sint32 posrelat (sint32 pos, size_t len) {
static int str_sub (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- sint32 start = posrelat(luaL_checklong(L, 2), l);
- sint32 end = posrelat(luaL_optlong(L, 3, -1), l);
+ sint32 start = posrelat(luaL_checkinteger(L, 2), l);
+ sint32 end = posrelat(luaL_optinteger(L, 3, -1), l);
if (start < 1) start = 1;
if (end > (sint32)l) end = (sint32)l;
if (start <= end)
@@ -56,6 +56,17 @@ static int str_sub (lua_State *L) {
}
+static int str_reverse (lua_State *L) {
+ size_t l;
+ luaL_Buffer b;
+ const char *s = luaL_checklstring(L, 1, &l);
+ luaL_buffinit(L, &b);
+ while (l--) luaL_putchar(&b, s[l]);
+ luaL_pushresult(&b);
+ return 1;
+}
+
+
static int str_lower (lua_State *L) {
size_t l;
size_t i;
@@ -97,10 +108,10 @@ static int str_rep (lua_State *L) {
static int str_byte (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
- sint32 pos = posrelat(luaL_optlong(L, 2, 1), l);
+ sint32 pos = posrelat(luaL_optinteger(L, 2, 1), l);
if (pos <= 0 || (size_t)(pos) > l) /* index out of range? */
return 0; /* no answer */
- lua_pushnumber(L, uchar(s[pos-1]));
+ lua_pushinteger(L, uchar(s[pos-1]));
return 1;
}
@@ -189,7 +200,7 @@ static const char *luaI_classend (MatchState *ms, const char *p) {
switch (*p++) {
case ESC: {
if (*p == '\0')
- luaL_error(ms->L, "malformed pattern (ends with `%')");
+ luaL_error(ms->L, "malformed pattern (ends with `%%')");
return p+1;
}
case '[': {
@@ -452,7 +463,7 @@ static void push_onecapture (MatchState *ms, int i) {
int l = ms->capture[i].len;
if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
if (l == CAP_POSITION)
- lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1));
+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
else
lua_pushlstring(ms->L, ms->capture[i].init, l);
}
@@ -477,7 +488,7 @@ static int str_find (lua_State *L) {
size_t l1, l2;
const char *s = luaL_checklstring(L, 1, &l1);
const char *p = luaL_checklstring(L, 2, &l2);
- sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1;
+ sint32 init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
if (init < 0) init = 0;
else if ((size_t)(init) > l1) init = (sint32)l1;
if (lua_toboolean(L, 4) || /* explicit request? */
@@ -485,8 +496,8 @@ static int str_find (lua_State *L) {
/* do a plain search */
const char *s2 = lmemfind(s+init, l1-init, p, l2);
if (s2) {
- lua_pushnumber(L, (lua_Number)(s2-s+1));
- lua_pushnumber(L, (lua_Number)(s2-s+l2));
+ lua_pushinteger(L, s2-s+1);
+ lua_pushinteger(L, s2-s+l2);
return 2;
}
}
@@ -501,8 +512,8 @@ static int str_find (lua_State *L) {
const char *res;
ms.level = 0;
if ((res=match(&ms, s1, p)) != NULL) {
- lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */
- lua_pushnumber(L, (lua_Number)(res-s)); /* end */
+ lua_pushinteger(L, s1-s+1); /* start */
+ lua_pushinteger(L, res-s); /* end */
return push_captures(&ms, NULL, 0) + 2;
}
} while (s1++<ms.src_end && !anchor);
@@ -521,7 +532,7 @@ static int gfind_aux (lua_State *L) {
ms.L = L;
ms.src_init = s;
ms.src_end = s+ls;
- for (src = s + (size_t)lua_tonumber(L, lua_upvalueindex(3));
+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
src <= ms.src_end;
src++) {
const char *e;
@@ -529,7 +540,7 @@ static int gfind_aux (lua_State *L) {
if ((e = match(&ms, src, p)) != NULL) {
int newstart = e-s;
if (e == src) newstart++; /* empty match? go at least one position */
- lua_pushnumber(L, (lua_Number)newstart);
+ lua_pushinteger(L, newstart);
lua_replace(L, lua_upvalueindex(3));
return push_captures(&ms, src, e);
}
@@ -542,7 +553,7 @@ static int gfind (lua_State *L) {
luaL_checkstring(L, 1);
luaL_checkstring(L, 2);
lua_settop(L, 2);
- lua_pushnumber(L, 0);
+ lua_pushinteger(L, 0);
lua_pushcclosure(L, gfind_aux, 3);
return 1;
}
@@ -616,7 +627,7 @@ static int str_gsub (lua_State *L) {
}
luaL_addlstring(&b, src, ms.src_end-src);
luaL_pushresult(&b);
- lua_pushnumber(L, (lua_Number)n); /* number of substitutions */
+ lua_pushinteger(L, n); /* number of substitutions */
return 2;
}
@@ -671,7 +682,7 @@ static const char *scanformat (lua_State *L, const char *strfrmt,
luaL_error(L, "invalid format (width or precision too long)");
if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */
luaL_error(L, "invalid format (too long)");
- form[0] = '%';
+ form[0] = ESC;
strncpy(form+1, strfrmt, p-strfrmt+1);
form[p-strfrmt+2] = 0;
return p;
@@ -686,9 +697,9 @@ static int str_format (lua_State *L) {
luaL_Buffer b;
luaL_buffinit(L, &b);
while (strfrmt < strfrmt_end) {
- if (*strfrmt != '%')
+ if (*strfrmt != ESC)
luaL_putchar(&b, *strfrmt++);
- else if (*++strfrmt == '%')
+ else if (*++strfrmt == ESC)
luaL_putchar(&b, *strfrmt++); /* %% */
else { /* format item */
char form[MAX_FORMAT]; /* to store the format (`%...') */
@@ -746,6 +757,7 @@ static int str_format (lua_State *L) {
static const luaL_reg strlib[] = {
{"len", str_len},
{"sub", str_sub},
+ {"reverse", str_reverse},
{"lower", str_lower},
{"upper", str_upper},
{"char", str_char},
diff --git a/src/lib/ltablib.c b/src/lib/ltablib.c
index c9bb2d1b..c38da36f 100644
--- a/src/lib/ltablib.c
+++ b/src/lib/ltablib.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltablib.c,v 1.21 2003/04/03 13:35:34 roberto Exp $
+** $Id: ltablib.c,v 1.22 2003/10/07 20:13:41 roberto Exp $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
@@ -24,7 +24,7 @@ static int luaB_foreachi (lua_State *L) {
luaL_checktype(L, 2, LUA_TFUNCTION);
for (i=1; i<=n; i++) {
lua_pushvalue(L, 2); /* function */
- lua_pushnumber(L, (lua_Number)i); /* 1st argument */
+ lua_pushinteger(L, i); /* 1st argument */
lua_rawgeti(L, 1, i); /* 2nd argument */
lua_call(L, 2, 1);
if (!lua_isnil(L, -1))
@@ -54,7 +54,7 @@ static int luaB_foreach (lua_State *L) {
static int luaB_getn (lua_State *L) {
- lua_pushnumber(L, (lua_Number)aux_getn(L, 1));
+ lua_pushinteger(L, aux_getn(L, 1));
return 1;
}
diff --git a/src/llex.c b/src/llex.c
index 045e9994..647e77f2 100644
--- a/src/llex.c
+++ b/src/llex.c
@@ -1,5 +1,5 @@
/*
-** $Id: llex.c,v 1.119 2003/03/24 12:39:34 roberto Exp $
+** $Id: llex.c,v 2.2 2004/03/12 19:53:56 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -22,9 +22,19 @@
-#define next(LS) (LS->current = zgetc(LS->z))
+#define next(ls) (ls->current = zgetc(ls->z))
+#define save(ls,c) { \
+ Mbuffer *b = ls->buff; \
+ if (b->n + 1 > b->buffsize) \
+ luaZ_resizebuffer(ls->L, b, ((b->buffsize*2) + LUA_MINBUFFER)); \
+ b->buffer[b->n++] = cast(char, c); }
+
+
+
+#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
+
/* ORDER RESERVED */
static const char *const token2string [] = {
@@ -51,85 +61,75 @@ void luaX_init (lua_State *L) {
#define MAXSRC 80
-void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) {
- if (val > limit) {
- msg = luaO_pushfstring(ls->L, "too many %s (limit=%d)", msg, limit);
- luaX_syntaxerror(ls, msg);
+const char *luaX_token2str (LexState *ls, int token) {
+ if (token < FIRST_RESERVED) {
+ lua_assert(token == (unsigned char)token);
+ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) :
+ luaO_pushfstring(ls->L, "%c", token);
}
+ else
+ return token2string[token-FIRST_RESERVED];
}
-void luaX_errorline (LexState *ls, const char *s, const char *token, int line) {
- lua_State *L = ls->L;
- char buff[MAXSRC];
- luaO_chunkid(buff, getstr(ls->source), MAXSRC);
- luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, line, s, token);
- luaD_throw(L, LUA_ERRSYNTAX);
-}
-
-
-static void luaX_error (LexState *ls, const char *s, const char *token) {
- luaX_errorline(ls, s, token, ls->linenumber);
-}
-
-
-void luaX_syntaxerror (LexState *ls, const char *msg) {
- const char *lasttoken;
- switch (ls->t.token) {
+static const char *txtToken (LexState *ls, int token) {
+ switch (token) {
case TK_NAME:
- lasttoken = getstr(ls->t.seminfo.ts);
- break;
case TK_STRING:
case TK_NUMBER:
- lasttoken = luaZ_buffer(ls->buff);
- break;
+ save(ls, '\0');
+ return luaZ_buffer(ls->buff);
default:
- lasttoken = luaX_token2str(ls, ls->t.token);
- break;
+ return luaX_token2str(ls, token);
}
- luaX_error(ls, msg, lasttoken);
}
-const char *luaX_token2str (LexState *ls, int token) {
- if (token < FIRST_RESERVED) {
- lua_assert(token == (unsigned char)token);
- return luaO_pushfstring(ls->L, "%c", token);
- }
- else
- return token2string[token-FIRST_RESERVED];
+void luaX_lexerror (LexState *ls, const char *msg, int token) {
+ char buff[MAXSRC];
+ luaO_chunkid(buff, getstr(ls->source), MAXSRC);
+ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
+ if (token)
+ luaO_pushfstring(ls->L, "%s near `%s'", msg, txtToken(ls, token));
+ luaD_throw(ls->L, LUA_ERRSYNTAX);
}
-static void luaX_lexerror (LexState *ls, const char *s, int token) {
- if (token == TK_EOS)
- luaX_error(ls, s, luaX_token2str(ls, token));
- else
- luaX_error(ls, s, luaZ_buffer(ls->buff));
+void luaX_syntaxerror (LexState *ls, const char *msg) {
+ luaX_lexerror(ls, msg, ls->t.token);
}
-static void inclinenumber (LexState *LS) {
- next(LS); /* skip `\n' */
- ++LS->linenumber;
- luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk");
+TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
+ lua_State *L = ls->L;
+ TString *ts = luaS_newlstr(L, str, l);
+ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */
+ if (ttisnil(o))
+ setbvalue(o, 1); /* make sure `str' will not be collected */
+ return ts;
}
-void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
- LS->L = L;
- LS->lookahead.token = TK_EOS; /* no look-ahead token */
- LS->z = z;
- LS->fs = NULL;
- LS->linenumber = 1;
- LS->lastline = 1;
- LS->source = source;
- next(LS); /* read first char */
- if (LS->current == '#') {
- do { /* skip first line */
- next(LS);
- } while (LS->current != '\n' && LS->current != EOZ);
- }
+static void inclinenumber (LexState *ls) {
+ int old = ls->current;
+ lua_assert(currIsNewline(ls));
+ next(ls); /* skip `\n' or `\r' */
+ if (currIsNewline(ls) && ls->current != old)
+ next(ls); /* skip `\n\r' or `\r\n' */
+ if (++ls->linenumber >= MAX_INT)
+ luaX_syntaxerror(ls, "chunk has too many lines");
+}
+
+
+void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
+ ls->L = L;
+ ls->lookahead.token = TK_EOS; /* no look-ahead token */
+ ls->z = z;
+ ls->fs = NULL;
+ ls->linenumber = 1;
+ ls->lastline = 1;
+ ls->source = source;
+ next(ls); /* read first char */
}
@@ -141,242 +141,229 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
*/
-/* use buffer to store names, literal strings and numbers */
-/* extra space to allocate when growing buffer */
-#define EXTRABUFF 32
-
-/* maximum number of chars that can be read without checking buffer size */
-#define MAXNOCHECK 5
-
-#define checkbuffer(LS, len) \
- if (((len)+MAXNOCHECK)*sizeof(char) > luaZ_sizebuffer((LS)->buff)) \
- luaZ_openspace((LS)->L, (LS)->buff, (len)+EXTRABUFF)
-
-#define save(LS, c, l) \
- (luaZ_buffer((LS)->buff)[l++] = cast(char, c))
-#define save_and_next(LS, l) (save(LS, LS->current, l), next(LS))
-
-
-static size_t readname (LexState *LS) {
- size_t l = 0;
- checkbuffer(LS, l);
- do {
- checkbuffer(LS, l);
- save_and_next(LS, l);
- } while (isalnum(LS->current) || LS->current == '_');
- save(LS, '\0', l);
- return l-1;
+static void save_and_next (LexState *ls) {
+ save(ls, ls->current);
+ next(ls);
}
+
/* LUA_NUMBER */
-static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
- size_t l = 0;
- checkbuffer(LS, l);
- if (comma) save(LS, '.', l);
- while (isdigit(LS->current)) {
- checkbuffer(LS, l);
- save_and_next(LS, l);
+static void read_numeral (LexState *ls, SemInfo *seminfo) {
+ while (isdigit(ls->current)) {
+ save_and_next(ls);
}
- if (LS->current == '.') {
- save_and_next(LS, l);
- if (LS->current == '.') {
- save_and_next(LS, l);
- save(LS, '\0', l);
- luaX_lexerror(LS,
+ if (ls->current == '.') {
+ save_and_next(ls);
+ if (ls->current == '.') {
+ save_and_next(ls);
+ luaX_lexerror(ls,
"ambiguous syntax (decimal point x string concatenation)",
TK_NUMBER);
}
}
- while (isdigit(LS->current)) {
- checkbuffer(LS, l);
- save_and_next(LS, l);
+ while (isdigit(ls->current)) {
+ save_and_next(ls);
}
- if (LS->current == 'e' || LS->current == 'E') {
- save_and_next(LS, l); /* read `E' */
- if (LS->current == '+' || LS->current == '-')
- save_and_next(LS, l); /* optional exponent sign */
- while (isdigit(LS->current)) {
- checkbuffer(LS, l);
- save_and_next(LS, l);
+ if (ls->current == 'e' || ls->current == 'E') {
+ save_and_next(ls); /* read `E' */
+ if (ls->current == '+' || ls->current == '-')
+ save_and_next(ls); /* optional exponent sign */
+ while (isdigit(ls->current)) {
+ save_and_next(ls);
}
}
- save(LS, '\0', l);
- if (!luaO_str2d(luaZ_buffer(LS->buff), &seminfo->r))
- luaX_lexerror(LS, "malformed number", TK_NUMBER);
+ save(ls, '\0');
+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))
+ luaX_lexerror(ls, "malformed number", TK_NUMBER);
}
-static void read_long_string (LexState *LS, SemInfo *seminfo) {
+static int skip_ast (LexState *ls) {
+ int count = 0;
+ int s = ls->current;
+ lua_assert(s == '[' || s == ']');
+ save_and_next(ls);
+ while (ls->current == '*') {
+ save_and_next(ls);
+ count++;
+ }
+ return (ls->current == s) ? count : (-count) - 1;
+}
+
+
+static void read_long_string (LexState *ls, SemInfo *seminfo, int ast) {
int cont = 0;
- size_t l = 0;
- checkbuffer(LS, l);
- save(LS, '[', l); /* save first `[' */
- save_and_next(LS, l); /* pass the second `[' */
- if (LS->current == '\n') /* string starts with a newline? */
- inclinenumber(LS); /* skip it */
+ save_and_next(ls); /* skip 2nd `[' */
+ if (currIsNewline(ls)) /* string starts with a newline? */
+ inclinenumber(ls); /* skip it */
for (;;) {
- checkbuffer(LS, l);
- switch (LS->current) {
+ switch (ls->current) {
case EOZ:
- save(LS, '\0', l);
- luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
+ luaX_lexerror(ls, (seminfo) ? "unfinished long string" :
"unfinished long comment", TK_EOS);
break; /* to avoid warnings */
case '[':
- save_and_next(LS, l);
- if (LS->current == '[') {
+ if (skip_ast(ls) == ast) {
+ save_and_next(ls); /* skip 2nd `[' */
cont++;
- save_and_next(LS, l);
}
continue;
case ']':
- save_and_next(LS, l);
- if (LS->current == ']') {
- if (cont == 0) goto endloop;
- cont--;
- save_and_next(LS, l);
+ if (skip_ast(ls) == ast) {
+ save_and_next(ls); /* skip 2nd `]' */
+ if (cont-- == 0) goto endloop;
}
continue;
case '\n':
- save(LS, '\n', l);
- inclinenumber(LS);
- if (!seminfo) l = 0; /* reset buffer to avoid wasting space */
+ case '\r':
+ save(ls, '\n');
+ inclinenumber(ls);
+ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
continue;
default:
- save_and_next(LS, l);
+ if (seminfo) save_and_next(ls);
+ else next(ls);
}
} endloop:
- save_and_next(LS, l); /* skip the second `]' */
- save(LS, '\0', l);
if (seminfo)
- seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5);
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + ast),
+ luaZ_bufflen(ls->buff) - 2*(2 + ast));
}
-static void read_string (LexState *LS, int del, SemInfo *seminfo) {
- size_t l = 0;
- checkbuffer(LS, l);
- save_and_next(LS, l);
- while (LS->current != del) {
- checkbuffer(LS, l);
- switch (LS->current) {
+static void read_string (LexState *ls, int del, SemInfo *seminfo) {
+ save_and_next(ls);
+ while (ls->current != del) {
+ switch (ls->current) {
case EOZ:
- save(LS, '\0', l);
- luaX_lexerror(LS, "unfinished string", TK_EOS);
- break; /* to avoid warnings */
+ luaX_lexerror(ls, "unfinished string", TK_EOS);
+ continue; /* to avoid warnings */
case '\n':
- save(LS, '\0', l);
- luaX_lexerror(LS, "unfinished string", TK_STRING);
- break; /* to avoid warnings */
- case '\\':
- next(LS); /* do not save the `\' */
- switch (LS->current) {
- case 'a': save(LS, '\a', l); next(LS); break;
- case 'b': save(LS, '\b', l); next(LS); break;
- case 'f': save(LS, '\f', l); next(LS); break;
- case 'n': save(LS, '\n', l); next(LS); break;
- case 'r': save(LS, '\r', l); next(LS); break;
- case 't': save(LS, '\t', l); next(LS); break;
- case 'v': save(LS, '\v', l); next(LS); break;
- case '\n': save(LS, '\n', l); inclinenumber(LS); break;
- case EOZ: break; /* will raise an error next loop */
+ case '\r':
+ luaX_lexerror(ls, "unfinished string", TK_STRING);
+ continue; /* to avoid warnings */
+ case '\\': {
+ int c;
+ next(ls); /* do not save the `\' */
+ switch (ls->current) {
+ case 'a': c = '\a'; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ case '\n': /* go through */
+ case '\r': save(ls, '\n'); inclinenumber(ls); continue;
+ case EOZ: continue; /* will raise an error next loop */
default: {
- if (!isdigit(LS->current))
- save_and_next(LS, l); /* handles \\, \", \', and \? */
+ if (!isdigit(ls->current))
+ save_and_next(ls); /* handles \\, \", \', and \? */
else { /* \xxx */
- int c = 0;
int i = 0;
+ c = 0;
do {
- c = 10*c + (LS->current-'0');
- next(LS);
- } while (++i<3 && isdigit(LS->current));
- if (c > UCHAR_MAX) {
- save(LS, '\0', l);
- luaX_lexerror(LS, "escape sequence too large", TK_STRING);
- }
- save(LS, c, l);
+ c = 10*c + (ls->current-'0');
+ next(ls);
+ } while (++i<3 && isdigit(ls->current));
+ if (c > UCHAR_MAX)
+ luaX_lexerror(ls, "escape sequence too large", TK_STRING);
+ save(ls, c);
}
+ continue;
}
}
- break;
+ save(ls, c);
+ next(ls);
+ continue;
+ }
default:
- save_and_next(LS, l);
+ save_and_next(ls);
}
}
- save_and_next(LS, l); /* skip delimiter */
- save(LS, '\0', l);
- seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3);
+ save_and_next(ls); /* skip delimiter */
+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
+ luaZ_bufflen(ls->buff) - 2);
}
-int luaX_lex (LexState *LS, SemInfo *seminfo) {
+int luaX_lex (LexState *ls, SemInfo *seminfo) {
+ luaZ_resetbuffer(ls->buff);
for (;;) {
- switch (LS->current) {
-
- case '\n': {
- inclinenumber(LS);
+ switch (ls->current) {
+ case '\n':
+ case '\r': {
+ inclinenumber(ls);
continue;
}
case '-': {
- next(LS);
- if (LS->current != '-') return '-';
+ next(ls);
+ if (ls->current != '-') return '-';
/* else is a comment */
- next(LS);
- if (LS->current == '[' && (next(LS), LS->current == '['))
- read_long_string(LS, NULL); /* long comment */
- else /* short comment */
- while (LS->current != '\n' && LS->current != EOZ)
- next(LS);
+ next(ls);
+ if (ls->current == '[') {
+ int ast = skip_ast(ls);
+ luaZ_resetbuffer(ls->buff); /* `skip_ast' may dirty the buffer */
+ if (ast >= 0) {
+ read_long_string(ls, NULL, ast); /* long comment */
+ luaZ_resetbuffer(ls->buff);
+ continue;
+ }
+ }
+ /* else short comment */
+ while (!currIsNewline(ls) && ls->current != EOZ)
+ next(ls);
continue;
}
case '[': {
- next(LS);
- if (LS->current != '[') return '[';
- else {
- read_long_string(LS, seminfo);
+ int ast = skip_ast(ls);
+ if (ast >= 0) {
+ read_long_string(ls, seminfo, ast);
return TK_STRING;
}
+ else if (ast == -1) return '[';
+ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
}
case '=': {
- next(LS);
- if (LS->current != '=') return '=';
- else { next(LS); return TK_EQ; }
+ next(ls);
+ if (ls->current != '=') return '=';
+ else { next(ls); return TK_EQ; }
}
case '<': {
- next(LS);
- if (LS->current != '=') return '<';
- else { next(LS); return TK_LE; }
+ next(ls);
+ if (ls->current != '=') return '<';
+ else { next(ls); return TK_LE; }
}
case '>': {
- next(LS);
- if (LS->current != '=') return '>';
- else { next(LS); return TK_GE; }
+ next(ls);
+ if (ls->current != '=') return '>';
+ else { next(ls); return TK_GE; }
}
case '~': {
- next(LS);
- if (LS->current != '=') return '~';
- else { next(LS); return TK_NE; }
+ next(ls);
+ if (ls->current != '=') return '~';
+ else { next(ls); return TK_NE; }
}
case '"':
case '\'': {
- read_string(LS, LS->current, seminfo);
+ read_string(ls, ls->current, seminfo);
return TK_STRING;
}
case '.': {
- next(LS);
- if (LS->current == '.') {
- next(LS);
- if (LS->current == '.') {
- next(LS);
+ save_and_next(ls);
+ if (ls->current == '.') {
+ next(ls);
+ if (ls->current == '.') {
+ next(ls);
return TK_DOTS; /* ... */
}
else return TK_CONCAT; /* .. */
}
- else if (!isdigit(LS->current)) return '.';
+ else if (!isdigit(ls->current)) return '.';
else {
- read_numeral(LS, 1, seminfo);
+ read_numeral(ls, seminfo);
return TK_NUMBER;
}
}
@@ -384,29 +371,33 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
return TK_EOS;
}
default: {
- if (isspace(LS->current)) {
- next(LS);
+ if (isspace(ls->current)) {
+ lua_assert(!currIsNewline(ls));
+ next(ls);
continue;
}
- else if (isdigit(LS->current)) {
- read_numeral(LS, 0, seminfo);
+ else if (isdigit(ls->current)) {
+ read_numeral(ls, seminfo);
return TK_NUMBER;
}
- else if (isalpha(LS->current) || LS->current == '_') {
+ else if (isalpha(ls->current) || ls->current == '_') {
/* identifier or reserved word */
- size_t l = readname(LS);
- TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l);
+ TString *ts;
+ do {
+ save_and_next(ls);
+ } while (isalnum(ls->current) || ls->current == '_');
+ ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
+ luaZ_bufflen(ls->buff));
if (ts->tsv.reserved > 0) /* reserved word? */
return ts->tsv.reserved - 1 + FIRST_RESERVED;
- seminfo->ts = ts;
- return TK_NAME;
+ else {
+ seminfo->ts = ts;
+ return TK_NAME;
+ }
}
else {
- int c = LS->current;
- if (iscntrl(c))
- luaX_error(LS, "invalid control char",
- luaO_pushfstring(LS->L, "char(%d)", c));
- next(LS);
+ int c = ls->current;
+ next(ls);
return c; /* single-char tokens (+ - / ...) */
}
}
diff --git a/src/llex.h b/src/llex.h
index 740e3f6b..6cfc3fdd 100644
--- a/src/llex.h
+++ b/src/llex.h
@@ -1,5 +1,5 @@
/*
-** $Id: llex.h,v 1.47 2003/02/28 17:19:47 roberto Exp $
+** $Id: llex.h,v 1.50 2004/03/12 19:53:56 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -65,10 +65,10 @@ typedef struct LexState {
void luaX_init (lua_State *L);
void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source);
+TString *luaX_newstring (LexState *LS, const char *str, size_t l);
int luaX_lex (LexState *LS, SemInfo *seminfo);
-void luaX_checklimit (LexState *ls, int val, int limit, const char *msg);
+void luaX_lexerror (LexState *ls, const char *msg, int token);
void luaX_syntaxerror (LexState *ls, const char *s);
-void luaX_errorline (LexState *ls, const char *s, const char *token, int line);
const char *luaX_token2str (LexState *ls, int token);
diff --git a/src/llimits.h b/src/llimits.h
index 343c9226..6a2e00bd 100644
--- a/src/llimits.h
+++ b/src/llimits.h
@@ -1,5 +1,5 @@
/*
-** $Id: llimits.h,v 1.52 2003/02/20 19:33:23 roberto Exp $
+** $Id: llimits.h,v 1.57 2003/12/01 16:33:30 roberto Exp $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -22,15 +22,13 @@
/* avoid overflows in comparison */
#if INT_MAX-20 < 32760
#define BITS_INT 16
-#else
-#if INT_MAX > 2147483640L
+#elif INT_MAX > 2147483640L
/* machine has at least 32 bits */
#define BITS_INT 32
#else
#error "you must define BITS_INT with number of bits in an integer"
#endif
#endif
-#endif
/*
@@ -40,20 +38,43 @@
** any machine, but may not be optimal.
*/
-/* an unsigned integer to hold hash values */
-typedef unsigned int lu_hash;
-/* its signed equivalent */
-typedef int ls_hash;
-/* an unsigned integer big enough to count the total memory used by Lua; */
-/* it should be at least as large as size_t */
-typedef unsigned long lu_mem;
+/*
+** an unsigned integer with at least 32 bits
+*/
+#ifndef LUA_UINT32
+#define LUA_UINT32 unsigned long
+#endif
+
+typedef LUA_UINT32 lu_int32;
+
+
+/*
+** a signed integer with at least 32 bits
+*/
+#ifndef LUA_INT32
+#define LUA_INT32 long
+#define LUA_MAXINT32 LONG_MAX
+#endif
+
+typedef LUA_INT32 l_int32;
+
-#define MAX_LUMEM ULONG_MAX
+/*
+** an unsigned integer big enough to count the total memory used by Lua;
+** it should be at least as large as `size_t'
+*/
+typedef lu_int32 lu_mem;
+
+
+/*
+** a signed integer big enough to count the total memory used by Lua;
+** it should be at least as large as `size_t'
+*/
+typedef l_int32 l_mem;
+#define MAXLMEM LUA_MAXINT32
-/* an integer big enough to count the number of strings in use */
-typedef long ls_nstr;
/* chars used as small naturals (so that `char' is reserved for characters) */
typedef unsigned char lu_byte;
@@ -69,7 +90,7 @@ typedef unsigned char lu_byte;
** this is for hashing only; there is no problem if the integer
** cannot hold the whole pointer value
*/
-#define IntPoint(p) ((lu_hash)(p))
+#define IntPoint(p) ((unsigned int)(p))
@@ -114,7 +135,7 @@ typedef LUA_UACNUMBER l_uacNumber;
** type for virtual-machine instructions
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
*/
-typedef unsigned long Instruction;
+typedef lu_int32 Instruction;
/* maximum depth for calls (unsigned short) */
@@ -133,7 +154,7 @@ typedef unsigned long Instruction;
#endif
-/* maximum size for the C stack */
+/* maximum size for the virtual stack of a C function */
#ifndef LUA_MAXCSTACK
#define LUA_MAXCSTACK 2048
#endif
@@ -145,19 +166,13 @@ typedef unsigned long Instruction;
/* maximum number of variables declared in a function */
#ifndef MAXVARS
-#define MAXVARS 200 /* arbitrary limit (<MAXSTACK) */
+#define MAXVARS 200 /* <MAXSTACK */
#endif
/* maximum number of upvalues per function */
#ifndef MAXUPVALUES
-#define MAXUPVALUES 32
-#endif
-
-
-/* maximum number of parameters in a function */
-#ifndef MAXPARAMS
-#define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */
+#define MAXUPVALUES 32 /* <MAXSTACK */
#endif
diff --git a/src/lmem.c b/src/lmem.c
index f977770a..75b274c9 100644
--- a/src/lmem.c
+++ b/src/lmem.c
@@ -1,11 +1,11 @@
/*
-** $Id: lmem.c,v 1.61 2002/12/04 17:38:31 roberto Exp $
+** $Id: lmem.c,v 1.63 2003/11/27 18:18:37 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
-#include <stdlib.h>
+#include <stddef.h>
#define lmem_c
@@ -20,21 +20,23 @@
/*
-** definition for realloc function. It must assure that l_realloc(NULL,
-** 0, x) allocates a new block (ANSI C assures that). (`os' is the old
-** block size; some allocators may use that.)
+** About the realloc function:
+** void * realloc (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'
+**
+** * 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
+** (which is equivalent to free(NULL) in ANSI C)
+**
+** realloc returns NULL if it cannot create or reallocate the area
+** (any reallocation to an equal or smaller size cannot fail!)
*/
-#ifndef l_realloc
-#define l_realloc(b,os,s) realloc(b,s)
-#endif
-/*
-** definition for free function. (`os' is the old block size; some
-** allocators may use that.)
-*/
-#ifndef l_free
-#define l_free(b,os) free(b)
-#endif
#define MINSIZEARRAY 4
@@ -43,13 +45,16 @@
void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
int limit, const char *errormsg) {
void *newblock;
- int newsize = (*size)*2;
- if (newsize < MINSIZEARRAY)
- newsize = MINSIZEARRAY; /* minimum size */
- else if (*size >= limit/2) { /* cannot double it? */
- if (*size < limit - MINSIZEARRAY) /* try something smaller... */
- newsize = limit; /* still have at least MINSIZEARRAY free places */
- else luaG_runerror(L, errormsg);
+ int newsize;
+ if (*size >= limit/2) { /* cannot double it? */
+ if (*size >= limit - MINSIZEARRAY) /* try something smaller... */
+ luaG_runerror(L, errormsg);
+ newsize = limit; /* still have at least MINSIZEARRAY free places */
+ }
+ else {
+ newsize = (*size)*2;
+ if (newsize < MINSIZEARRAY)
+ newsize = MINSIZEARRAY; /* minimum size */
}
newblock = luaM_realloc(L, block,
cast(lu_mem, *size)*cast(lu_mem, size_elems),
@@ -62,30 +67,17 @@ void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
/*
** generic allocation routine.
*/
-void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
- lua_assert((oldsize == 0) == (block == NULL));
- if (size == 0) {
- if (block != NULL) {
- l_free(block, oldsize);
- block = NULL;
- }
- else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */
- }
- else if (size >= MAX_SIZET)
+void *luaM_realloc (lua_State *L, void *block, lu_mem osize, lu_mem nsize) {
+ global_State *g = G(L);
+ lua_assert((osize == 0) == (block == NULL));
+ if (nsize >= MAX_SIZET)
luaG_runerror(L, "memory allocation error: block too big");
- else {
- block = l_realloc(block, oldsize, size);
- if (block == NULL) {
- if (L)
- luaD_throw(L, LUA_ERRMEM);
- else return NULL; /* error before creating state! */
- }
- }
- if (L) {
- lua_assert(G(L) != NULL && G(L)->nblocks > 0);
- G(L)->nblocks -= oldsize;
- G(L)->nblocks += size;
- }
+ block = (*g->realloc)(g->ud, block, osize, nsize);
+ if (block == NULL && nsize > 0)
+ luaD_throw(L, LUA_ERRMEM);
+ lua_assert((nsize == 0) == (block == NULL));
+ g->nblocks -= osize;
+ g->nblocks += nsize;
return block;
}
diff --git a/src/lobject.c b/src/lobject.c
index 9522b6e8..f273796b 100644
--- a/src/lobject.c
+++ b/src/lobject.c
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.c,v 1.97 2003/04/03 13:35:34 roberto Exp $
+** $Id: lobject.c,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -27,7 +27,7 @@
#endif
-const TObject luaO_nilobject = {LUA_TNIL, {NULL}};
+const TValue luaO_nilobject = {LUA_TNIL, {NULL}};
/*
@@ -45,33 +45,24 @@ int luaO_int2fb (unsigned int x) {
int luaO_log2 (unsigned int x) {
- static const lu_byte log_8[255] = {
- 0,
- 1,1,
- 2,2,2,2,
- 3,3,3,3,3,3,3,3,
- 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ static const lu_byte log_2[256] = {
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
};
- if (x >= 0x00010000) {
- if (x >= 0x01000000) return log_8[((x>>24) & 0xff) - 1]+24;
- else return log_8[((x>>16) & 0xff) - 1]+16;
- }
- else {
- if (x >= 0x00000100) return log_8[((x>>8) & 0xff) - 1]+8;
- else if (x) return log_8[(x & 0xff) - 1];
- return -1; /* special `log' for 0 */
- }
+ int l = -1;
+ while (x >= 256) { l += 8; x >>= 8; }
+ return l + log_2[x];
+
}
-int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
+int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
if (ttype(t1) != ttype(t2)) return 0;
else switch (ttype(t1)) {
case LUA_TNIL:
@@ -102,7 +93,7 @@ int luaO_str2d (const char *s, lua_Number *result) {
static void pushstr (lua_State *L, const char *str) {
- setsvalue2s(L->top, luaS_new(L, str));
+ setsvalue2s(L, L->top, luaS_new(L, str));
incr_top(L);
}
@@ -114,7 +105,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
- setsvalue2s(L->top, luaS_newlstr(L, fmt, e-fmt));
+ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
incr_top(L);
switch (*(e+1)) {
case 's':
@@ -138,7 +129,14 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
case '%':
pushstr(L, "%");
break;
- default: lua_assert(0);
+ default: {
+ char buff[3];
+ buff[0] = '%';
+ buff[1] = *(e+1);
+ buff[2] = '\0';
+ pushstr(L, buff);
+ break;
+ }
}
n += 2;
fmt = e+2;
diff --git a/src/lobject.h b/src/lobject.h
index 321a7e06..d5176a23 100644
--- a/src/lobject.h
+++ b/src/lobject.h
@@ -1,13 +1,17 @@
/*
-** $Id: lobject.h,v 1.159 2003/03/18 12:50:04 roberto Exp $
+** $Id: lobject.h,v 2.4 2004/03/15 21:04:33 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
+
#ifndef lobject_h
#define lobject_h
+#include <stdarg.h>
+
+
#include "llimits.h"
#include "lua.h"
@@ -58,12 +62,12 @@ typedef union {
/*
-** Lua values (or `tagged objects')
+** Tagged Values
*/
-typedef struct lua_TObject {
+typedef struct lua_TValue {
int tt;
Value value;
-} TObject;
+} TValue;
/* Macros to test type */
@@ -82,8 +86,10 @@ typedef struct lua_TObject {
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
-#define tsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
-#define uvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
+#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
+#define tsvalue(o) (&rawtsvalue(o)->tsv)
+#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
+#define uvalue(o) (&rawuvalue(o)->uv)
#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
@@ -91,59 +97,69 @@ typedef struct lua_TObject {
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
+/*
+** for internal debug only
+*/
+#define checkconsistency(obj) \
+ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
+
+#define checkliveness(g,obj) \
+ lua_assert(!iscollectable(obj) || \
+ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
+
+
/* Macros to set values */
+#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+
#define setnvalue(obj,x) \
- { TObject *i_o=(obj); i_o->tt=LUA_TNUMBER; i_o->value.n=(x); }
+ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
#define chgnvalue(obj,x) \
check_exp(ttype(obj)==LUA_TNUMBER, (obj)->value.n=(x))
#define setpvalue(obj,x) \
- { TObject *i_o=(obj); i_o->tt=LUA_TLIGHTUSERDATA; i_o->value.p=(x); }
+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
#define setbvalue(obj,x) \
- { TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); }
+ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }
-#define setsvalue(obj,x) \
- { TObject *i_o=(obj); i_o->tt=LUA_TSTRING; \
- i_o->value.gc=cast(GCObject *, (x)); \
- lua_assert(i_o->value.gc->gch.tt == LUA_TSTRING); }
+#define setsvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
+ checkliveness(G(L),i_o); }
-#define setuvalue(obj,x) \
- { TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; \
- i_o->value.gc=cast(GCObject *, (x)); \
- lua_assert(i_o->value.gc->gch.tt == LUA_TUSERDATA); }
+#define setuvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
+ checkliveness(G(L),i_o); }
-#define setthvalue(obj,x) \
- { TObject *i_o=(obj); i_o->tt=LUA_TTHREAD; \
- i_o->value.gc=cast(GCObject *, (x)); \
- lua_assert(i_o->value.gc->gch.tt == LUA_TTHREAD); }
+#define setthvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
+ checkliveness(G(L),i_o); }
-#define setclvalue(obj,x) \
- { TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; \
- i_o->value.gc=cast(GCObject *, (x)); \
- lua_assert(i_o->value.gc->gch.tt == LUA_TFUNCTION); }
+#define setclvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
+ checkliveness(G(L),i_o); }
-#define sethvalue(obj,x) \
- { TObject *i_o=(obj); i_o->tt=LUA_TTABLE; \
- i_o->value.gc=cast(GCObject *, (x)); \
- lua_assert(i_o->value.gc->gch.tt == LUA_TTABLE); }
-
-#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
+#define sethvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
+ checkliveness(G(L),i_o); }
+#define setptvalue(L,obj,x) \
+ { TValue *i_o=(obj); \
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
+ checkliveness(G(L),i_o); }
-/*
-** for internal debug only
-*/
-#define checkconsistency(obj) \
- lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
-#define setobj(obj1,obj2) \
- { const TObject *o2=(obj2); TObject *o1=(obj1); \
- checkconsistency(o2); \
- o1->tt=o2->tt; o1->value = o2->value; }
+#define setobj(L,obj1,obj2) \
+ { const TValue *o2=(obj2); TValue *o1=(obj1); \
+ o1->tt=o2->tt; o1->value = o2->value; \
+ checkliveness(G(L),o1); }
/*
@@ -155,6 +171,8 @@ typedef struct lua_TObject {
/* to stack (not from same stack) */
#define setobj2s setobj
#define setsvalue2s setsvalue
+#define sethvalue2s sethvalue
+#define setptvalue2s setptvalue
/* from table to same table */
#define setobjt2t setobj
/* to table */
@@ -170,7 +188,7 @@ typedef struct lua_TObject {
-typedef TObject *StkId; /* index to stack elements */
+typedef TValue *StkId; /* index to stack elements */
/*
@@ -181,7 +199,7 @@ typedef union TString {
struct {
CommonHeader;
lu_byte reserved;
- lu_hash hash;
+ unsigned int hash;
size_t len;
} tsv;
} TString;
@@ -209,7 +227,7 @@ typedef union Udata {
*/
typedef struct Proto {
CommonHeader;
- TObject *k; /* constants used by the function */
+ TValue *k; /* constants used by the function */
Instruction *code;
struct Proto **p; /* functions defined inside the function */
int *lineinfo; /* map from opcodes to source lines */
@@ -245,8 +263,8 @@ typedef struct LocVar {
typedef struct UpVal {
CommonHeader;
- TObject *v; /* points to stack or to its own value */
- TObject value; /* the value (when closed) */
+ TValue *v; /* points to stack or to its own value */
+ TValue value; /* the value (when closed) */
} UpVal;
@@ -260,14 +278,14 @@ typedef struct UpVal {
typedef struct CClosure {
ClosureHeader;
lua_CFunction f;
- TObject upvalue[1];
+ TValue upvalue[1];
} CClosure;
typedef struct LClosure {
ClosureHeader;
struct Proto *p;
- TObject g; /* global table for this closure */
+ TValue g; /* global table for this closure */
UpVal *upvals[1];
} LClosure;
@@ -287,8 +305,8 @@ typedef union Closure {
*/
typedef struct Node {
- TObject i_key;
- TObject i_val;
+ TValue i_key;
+ TValue i_val;
struct Node *next; /* for chaining */
} Node;
@@ -298,7 +316,7 @@ typedef struct Table {
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
struct Table *metatable;
- TObject *array; /* array part */
+ TValue *array; /* array part */
Node *node;
Node *firstfree; /* this position is free; all positions after it are full */
GCObject *gclist;
@@ -319,13 +337,13 @@ typedef struct Table {
-extern const TObject luaO_nilobject;
+extern const TValue luaO_nilobject;
int luaO_log2 (unsigned int x);
int luaO_int2fb (unsigned int x);
#define fb2int(x) (((x) & 7) << ((x) >> 3))
-int luaO_rawequalObj (const TObject *t1, const TObject *t2);
+int luaO_rawequalObj (const TValue *t1, const TValue *t2);
int luaO_str2d (const char *s, lua_Number *result);
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp);
diff --git a/src/lopcodes.c b/src/lopcodes.c
index 993e426d..3ffda71a 100644
--- a/src/lopcodes.c
+++ b/src/lopcodes.c
@@ -1,7 +1,5 @@
/*
-** $Id: lopcodes.c,v 1.22 2002/12/04 17:38:31 roberto Exp $
-** extracted automatically from lopcodes.h by mkprint.lua
-** DO NOT EDIT
+** $Id: lopcodes.c,v 1.25 2003/05/14 21:09:53 roberto Exp $
** See Copyright Notice in lua.h
*/
@@ -14,9 +12,11 @@
#include "lopcodes.h"
+/* ORDER OP */
+
#ifdef LUA_OPNAMES
-const char *const luaP_opnames[] = {
+const char *const luaP_opnames[NUM_OPCODES] = {
"MOVE",
"LOADK",
"LOADBOOL",
@@ -46,6 +46,7 @@ const char *const luaP_opnames[] = {
"TAILCALL",
"RETURN",
"FORLOOP",
+ "FORPREP",
"TFORLOOP",
"TFORPREP",
"SETLIST",
@@ -56,47 +57,45 @@ const char *const luaP_opnames[] = {
#endif
-#define opmode(t,b,bk,ck,sa,k,m) (((t)<<OpModeT) | \
- ((b)<<OpModeBreg) | ((bk)<<OpModeBrk) | ((ck)<<OpModeCrk) | \
- ((sa)<<OpModesetA) | ((k)<<OpModeK) | (m))
-
+#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
const lu_byte luaP_opmodes[NUM_OPCODES] = {
-/* T B Bk Ck sA K mode opcode */
- opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_MOVE */
- ,opmode(0, 0, 0, 0, 1, 1, iABx) /* OP_LOADK */
- ,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_LOADBOOL */
- ,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_LOADNIL */
- ,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_GETUPVAL */
- ,opmode(0, 0, 0, 0, 1, 1, iABx) /* OP_GETGLOBAL */
- ,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_GETTABLE */
- ,opmode(0, 0, 0, 0, 0, 1, iABx) /* OP_SETGLOBAL */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */
- ,opmode(0, 0, 1, 1, 0, 0, iABC) /* OP_SETTABLE */
- ,opmode(0, 0, 0, 0, 1, 0, iABC) /* OP_NEWTABLE */
- ,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_SELF */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_ADD */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_SUB */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_MUL */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_DIV */
- ,opmode(0, 0, 1, 1, 1, 0, iABC) /* OP_POW */
- ,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_UNM */
- ,opmode(0, 1, 0, 0, 1, 0, iABC) /* OP_NOT */
- ,opmode(0, 1, 0, 1, 1, 0, iABC) /* OP_CONCAT */
- ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_JMP */
- ,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_EQ */
- ,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_LT */
- ,opmode(1, 0, 1, 1, 0, 0, iABC) /* OP_LE */
- ,opmode(1, 1, 0, 0, 1, 0, iABC) /* OP_TEST */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_CALL */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_TAILCALL */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_RETURN */
- ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_FORLOOP */
- ,opmode(1, 0, 0, 0, 0, 0, iABC) /* OP_TFORLOOP */
- ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_TFORPREP */
- ,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLIST */
- ,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLISTO */
- ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_CLOSE */
- ,opmode(0, 0, 0, 0, 1, 0, iABx) /* OP_CLOSURE */
+/* T A B C mode opcode */
+ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
+ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
+ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
+ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
+ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
+ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */
+ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_TFORPREP */
+ ,opmode(0, 0, OpArgU, OpArgN, iABx) /* OP_SETLIST */
+ ,opmode(0, 0, OpArgU, OpArgN, iABx) /* OP_SETLISTO */
+ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
+ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
};
diff --git a/src/lopcodes.h b/src/lopcodes.h
index 0b6b58f3..28df697d 100644
--- a/src/lopcodes.h
+++ b/src/lopcodes.h
@@ -1,5 +1,5 @@
/*
-** $Id: lopcodes.h,v 1.102 2002/08/21 18:56:09 roberto Exp $
+** $Id: lopcodes.h,v 1.106 2003/05/15 19:46:03 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -134,7 +134,7 @@ name args description
------------------------------------------------------------------------*/
OP_MOVE,/* A B R(A) := R(B) */
OP_LOADK,/* A Bx R(A) := Kst(Bx) */
-OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) PC++ */
+OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
@@ -159,7 +159,7 @@ OP_NOT,/* A B R(A) := not R(B) */
OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
-OP_JMP,/* sBx PC += sBx */
+OP_JMP,/* sBx pc+=sBx */
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
@@ -171,12 +171,13 @@ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
-OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBx */
+OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then pc+=sBx */
+OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
OP_TFORLOOP,/* A C R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
if R(A+2) ~= nil then pc++ */
OP_TFORPREP,/* A sBx if type(R(A)) == table then R(A+1):=R(A), R(A):=next;
- PC += sBx */
+ pc+=sBx */
OP_SETLIST,/* A Bx R(A)[Bx-Bx%FPF+i] := R(A+i), 1 <= i <= Bx%FPF+1 */
OP_SETLISTO,/* A Bx */
@@ -205,29 +206,31 @@ OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
/*
-** masks for instruction properties
+** masks for instruction properties. The format is:
+** bits 0-1: op mode
+** bits 2-3: C arg mode
+** bits 4-5: B arg mode
+** bit 6: instruction set register A
+** bit 7: operator is a test
*/
-enum OpModeMask {
- OpModeBreg = 2, /* B is a register */
- OpModeBrk, /* B is a register/constant */
- OpModeCrk, /* C is a register/constant */
- OpModesetA, /* instruction set register A */
- OpModeK, /* Bx is a constant */
- OpModeT /* operator is a test */
-
-};
+enum OpArgMask {
+ OpArgN, /* argument is not used */
+ OpArgU, /* argument is used */
+ OpArgR, /* argument is a register or a jump offset */
+ OpArgK /* argument is a constant or register/constant */
+};
extern const lu_byte luaP_opmodes[NUM_OPCODES];
-#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
-#define testOpMode(m, b) (luaP_opmodes[m] & (1 << (b)))
+#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
+#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
+#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
+#define testAMode(m) (luaP_opmodes[m] & (1 << 6))
+#define testTMode(m) (luaP_opmodes[m] & (1 << 7))
-#ifdef LUA_OPNAMES
-extern const char *const luaP_opnames[]; /* opcode names */
-#endif
-
+extern const char *const luaP_opnames[NUM_OPCODES]; /* opcode names */
/* number of list items to accumulate before a SETLIST instruction */
diff --git a/src/lparser.c b/src/lparser.c
index 99bd3020..a8dafb6f 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 1.208a 2003/04/03 13:35:34 roberto Exp $
+** $Id: lparser.c,v 2.2 2004/03/12 19:53:56 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -13,6 +13,7 @@
#include "lcode.h"
#include "ldebug.h"
+#include "ldo.h"
#include "lfunc.h"
#include "llex.h"
#include "lmem.h"
@@ -27,9 +28,10 @@
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
+#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m)
-#define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \
- luaX_syntaxerror(ls, "too many syntax levels");
+#define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \
+ luaX_lexerror(ls, "chunk has too many syntax levels", 0)
#define leavelevel(ls) ((ls)->nestlevel--)
@@ -39,9 +41,9 @@
typedef struct BlockCnt {
struct BlockCnt *previous; /* chain */
int breaklist; /* list of jumps out of this loop */
- int nactvar; /* # active local variables outside the breakable structure */
- int upval; /* true if some variable in the block is an upvalue */
- int isbreakable; /* true if `block' is a loop */
+ lu_byte nactvar; /* # active locals outside the breakable structure */
+ lu_byte upval; /* true if some variable in the block is an upvalue */
+ lu_byte isbreakable; /* true if `block' is a loop */
} BlockCnt;
@@ -71,12 +73,29 @@ static void lookahead (LexState *ls) {
}
+static void anchor_token (LexState *ls) {
+ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
+ TString *ts = ls->t.seminfo.ts;
+ luaX_newstring(ls, getstr(ts), ts->tsv.len);
+ }
+}
+
+
static void error_expected (LexState *ls, int token) {
luaX_syntaxerror(ls,
luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token)));
}
+static void luaY_errorlimit (FuncState *fs, int limit, const char *what) {
+ const char *msg = (fs->f->lineDefined == 0) ?
+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
+ fs->f->lineDefined, limit, what);
+ luaX_lexerror(fs->ls, msg, 0);
+}
+
+
static int testnext (LexState *ls, int c) {
if (ls->t.token == c) {
next(ls);
@@ -138,17 +157,25 @@ static void checkname(LexState *ls, expdesc *e) {
static int luaI_registerlocalvar (LexState *ls, TString *varname) {
FuncState *fs = ls->fs;
Proto *f = fs->f;
+ int oldsize = f->sizelocvars;
luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
- LocVar, MAX_INT, "");
+ LocVar, USHRT_MAX, "too many local variables");
+ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
f->locvars[fs->nlocvars].varname = varname;
+ luaC_objbarrier(ls->L, f, varname);
return fs->nlocvars++;
}
+#define new_localvarliteral(ls,v,n) \
+ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
+
+
static void new_localvar (LexState *ls, TString *name, int n) {
FuncState *fs = ls->fs;
- luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "local variables");
- fs->actvar[fs->nactvar+n] = luaI_registerlocalvar(ls, name);
+ luaY_checklimit(fs, fs->nactvar+n+1, MAXVARS, "local variables");
+ fs->actvar[fs->nactvar+n] = cast(unsigned short,
+ luaI_registerlocalvar(ls, name));
}
@@ -168,32 +195,26 @@ static void removevars (LexState *ls, int tolevel) {
}
-static void new_localvarstr (LexState *ls, const char *name, int n) {
- new_localvar(ls, luaS_new(ls->L, name), n);
-}
-
-
-static void create_local (LexState *ls, const char *name) {
- new_localvarstr(ls, name, 0);
- adjustlocalvars(ls, 1);
-}
-
-
static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
int i;
Proto *f = fs->f;
+ int oldsize = f->sizeupvalues;
for (i=0; i<f->nups; i++) {
if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) {
- lua_assert(fs->f->upvalues[i] == name);
+ lua_assert(f->upvalues[i] == name);
return i;
}
}
/* new one */
- luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues");
- luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues,
+ luaY_checklimit(fs, f->nups + 1, MAXUPVALUES, "upvalues");
+ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
TString *, MAX_INT, "");
- fs->f->upvalues[f->nups] = name;
- fs->upvalues[f->nups] = *v;
+ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;
+ f->upvalues[f->nups] = name;
+ luaC_objbarrier(fs->L, f, name);
+ lua_assert(v->k == VLOCAL || v->k == VUPVAL);
+ fs->upvalues[f->nups].k = cast(lu_byte, v->k);
+ fs->upvalues[f->nups].info = cast(lu_byte, v->info);
return f->nups++;
}
@@ -267,18 +288,6 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
}
-static void code_params (LexState *ls, int nparams, int dots) {
- FuncState *fs = ls->fs;
- adjustlocalvars(ls, nparams);
- luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters");
- fs->f->numparams = cast(lu_byte, fs->nactvar);
- fs->f->is_vararg = cast(lu_byte, dots);
- if (dots)
- create_local(ls, "arg");
- luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
-}
-
-
static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) {
bl->breaklist = NO_JUMP;
bl->isbreakable = isbreakable;
@@ -305,10 +314,13 @@ static void leaveblock (FuncState *fs) {
static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
FuncState *fs = ls->fs;
Proto *f = fs->f;
+ int oldsize = f->sizep;
int i;
luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
MAXARG_Bx, "constant table overflow");
+ while (oldsize < f->sizep) f->p[oldsize++] = NULL;
f->p[fs->np++] = func->f;
+ luaC_objbarrier(ls->L, f, func->f);
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
for (i=0; i<func->f->nups; i++) {
OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
@@ -318,24 +330,30 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
static void open_func (LexState *ls, FuncState *fs) {
- Proto *f = luaF_newproto(ls->L);
+ lua_State *L = ls->L;
+ Proto *f = luaF_newproto(L);
fs->f = f;
fs->prev = ls->fs; /* linked list of funcstates */
fs->ls = ls;
- fs->L = ls->L;
+ fs->L = L;
ls->fs = fs;
fs->pc = 0;
fs->lasttarget = 0;
fs->jpc = NO_JUMP;
fs->freereg = 0;
fs->nk = 0;
- fs->h = luaH_new(ls->L, 0, 0);
fs->np = 0;
fs->nlocvars = 0;
fs->nactvar = 0;
fs->bl = NULL;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
+ fs->h = luaH_new(L, 0, 0);
+ /* anchor table of constants and prototype (to avoid being collected) */
+ sethvalue2s(L, L->top, fs->h);
+ incr_top(L);
+ setptvalue2s(L, L->top, f);
+ incr_top(L);
}
@@ -349,7 +367,7 @@ static void close_func (LexState *ls) {
f->sizecode = fs->pc;
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
f->sizelineinfo = fs->pc;
- luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject);
+ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
f->sizek = fs->nk;
luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
f->sizep = fs->np;
@@ -360,15 +378,18 @@ static void close_func (LexState *ls) {
lua_assert(luaG_checkcode(f));
lua_assert(fs->bl == NULL);
ls->fs = fs->prev;
+ L->top -= 2; /* remove table and prototype from the stack */
+ /* last token read was anchored in defunct function; must reanchor it */
+ if (fs) anchor_token(ls);
}
-Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
struct LexState lexstate;
struct FuncState funcstate;
lexstate.buff = buff;
lexstate.nestlevel = 0;
- luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z)));
+ luaX_setinput(L, &lexstate, z, luaS_new(L, name));
open_func(&lexstate, &funcstate);
next(&lexstate); /* read first token */
chunk(&lexstate);
@@ -377,6 +398,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
lua_assert(funcstate.prev == NULL);
lua_assert(funcstate.f->nups == 0);
lua_assert(lexstate.nestlevel == 0);
+ lua_assert(lexstate.fs == NULL);
return funcstate.f;
}
@@ -429,7 +451,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
int reg = ls->fs->freereg;
expdesc key, val;
if (ls->t.token == TK_NAME) {
- luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor");
+ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
cc->nh++;
checkname(ls, &key);
}
@@ -473,7 +495,7 @@ static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
static void listfield (LexState *ls, struct ConsControl *cc) {
expr(ls, &cc->v);
- luaX_checklimit(ls, cc->na, MAXARG_Bx, "items in a constructor");
+ luaY_checklimit(ls->fs, cc->na, MAXARG_Bx, "items in a constructor");
cc->na++;
cc->tostore++;
}
@@ -527,18 +549,35 @@ static void constructor (LexState *ls, expdesc *t) {
static void parlist (LexState *ls) {
/* parlist -> [ param { `,' param } ] */
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f;
int nparams = 0;
- int dots = 0;
+ f->is_vararg = 0;
if (ls->t.token != ')') { /* is `parlist' not empty? */
do {
switch (ls->t.token) {
- case TK_DOTS: dots = 1; next(ls); break;
- case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break;
+ case TK_NAME: { /* param -> NAME [ `=' `...' ] */
+ new_localvar(ls, str_checkname(ls), nparams++);
+ if (testnext(ls, '=')) {
+ check(ls, TK_DOTS);
+ f->is_vararg = 1;
+ }
+ break;
+ }
+ case TK_DOTS: { /* param -> `...' */
+ next(ls);
+ /* use `arg' as default name */
+ new_localvarliteral(ls, "arg", nparams++);
+ f->is_vararg = 1;
+ break;
+ }
default: luaX_syntaxerror(ls, "<name> or `...' expected");
}
- } while (!dots && testnext(ls, ','));
+ } while (!f->is_vararg && testnext(ls, ','));
}
- code_params(ls, nparams, dots);
+ adjustlocalvars(ls, nparams);
+ f->numparams = fs->nactvar - f->is_vararg;
+ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
}
@@ -548,8 +587,10 @@ static void body (LexState *ls, expdesc *e, int needself, int line) {
open_func(ls, &new_fs);
new_fs.f->lineDefined = line;
check(ls, '(');
- if (needself)
- create_local(ls, "self");
+ if (needself) {
+ new_localvarliteral(ls, "self", 0);
+ adjustlocalvars(ls, 1);
+ }
parlist(ls);
check(ls, ')');
chunk(ls);
@@ -645,18 +686,6 @@ static void prefixexp (LexState *ls, expdesc *v) {
singlevar(ls, v, 1);
return;
}
-#ifdef LUA_COMPATUPSYNTAX
- case '%': { /* for compatibility only */
- TString *varname;
- int line = ls->linenumber;
- next(ls); /* skip `%' */
- varname = singlevar(ls, v, 1);
- if (v->k != VUPVAL)
- luaX_errorline(ls, "global upvalues are obsolete",
- getstr(varname), line);
- return;
- }
-#endif
default: {
luaX_syntaxerror(ls, "unexpected symbol");
return;
@@ -796,7 +825,7 @@ static const struct {
** subexpr -> (simplexep | unop subexpr) { binop subexpr }
** where `binop' is any binary operator with a priority higher than `limit'
*/
-static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
+static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
BinOpr op;
UnOpr uop;
enterlevel(ls);
@@ -809,13 +838,13 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
else simpleexp(ls, v);
/* expand while operators have priorities higher than `limit' */
op = getbinopr(ls->t.token);
- while (op != OPR_NOBINOPR && cast(int, priority[op].left) > limit) {
+ while (op != OPR_NOBINOPR && priority[op].left > limit) {
expdesc v2;
BinOpr nextop;
next(ls);
luaK_infix(ls->fs, op, v);
/* read sub-expression with higher priority */
- nextop = subexpr(ls, &v2, cast(int, priority[op].right));
+ nextop = subexpr(ls, &v2, priority[op].right);
luaK_posfix(ls->fs, op, v, &v2);
op = nextop;
}
@@ -825,7 +854,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
static void expr (LexState *ls, expdesc *v) {
- subexpr(ls, v, -1);
+ subexpr(ls, v, 0);
}
/* }==================================================================== */
@@ -931,12 +960,14 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
}
-static void cond (LexState *ls, expdesc *v) {
+static int cond (LexState *ls) {
/* cond -> exp */
- expr(ls, v); /* read condition */
- if (v->k == VNIL) v->k = VFALSE; /* `falses' are all equal here */
- luaK_goiftrue(ls->fs, v);
- luaK_patchtohere(ls->fs, v->t);
+ expdesc v;
+ expr(ls, &v); /* read condition */
+ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
+ luaK_goiftrue(ls->fs, &v);
+ luaK_patchtohere(ls->fs, v.t);
+ return v.f;
}
@@ -1004,14 +1035,14 @@ static void repeatstat (LexState *ls, int line) {
/* repeatstat -> REPEAT block UNTIL cond */
FuncState *fs = ls->fs;
int repeat_init = luaK_getlabel(fs);
- expdesc v;
+ int flist;
BlockCnt bl;
enterblock(fs, &bl, 1);
next(ls);
block(ls);
check_match(ls, TK_UNTIL, TK_REPEAT, line);
- cond(ls, &v);
- luaK_patchlist(fs, v.f, repeat_init);
+ flist = cond(ls);
+ luaK_patchlist(fs, flist, repeat_init);
leaveblock(fs);
}
@@ -1027,30 +1058,34 @@ static int exp1 (LexState *ls) {
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
+ /* forbody -> DO block */
BlockCnt bl;
FuncState *fs = ls->fs;
int prep, endfor;
- adjustlocalvars(ls, nvars); /* scope for all variables */
+ adjustlocalvars(ls, 3); /* control variables */
check(ls, TK_DO);
- enterblock(fs, &bl, 1); /* loop block */
- prep = luaK_getlabel(fs);
+ prep = luaK_codeAsBx(fs, (isnum ? OP_FORPREP : OP_TFORPREP), base, NO_JUMP);
+ enterblock(fs, &bl, 0); /* scope for declared variables */
+ adjustlocalvars(ls, nvars);
+ luaK_reserveregs(fs, nvars);
block(ls);
- luaK_patchtohere(fs, prep-1);
+ leaveblock(fs); /* end of scope for declared variables */
+ luaK_patchtohere(fs, prep);
endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
- luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
+ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
- luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep);
- leaveblock(fs);
+ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
}
static void fornum (LexState *ls, TString *varname, int line) {
- /* fornum -> NAME = exp1,exp1[,exp1] DO body */
+ /* fornum -> NAME = exp1,exp1[,exp1] forbody */
FuncState *fs = ls->fs;
int base = fs->freereg;
- new_localvar(ls, varname, 0);
- new_localvarstr(ls, "(for limit)", 1);
- new_localvarstr(ls, "(for step)", 2);
+ new_localvarliteral(ls, "(for index)", 0);
+ new_localvarliteral(ls, "(for limit)", 1);
+ new_localvarliteral(ls, "(for step)", 2);
+ new_localvar(ls, varname, 3);
check(ls, '=');
exp1(ls); /* initial value */
check(ls, ',');
@@ -1061,39 +1096,39 @@ static void fornum (LexState *ls, TString *varname, int line) {
luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
luaK_reserveregs(fs, 1);
}
- luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
- luaK_jump(fs);
- forbody(ls, base, line, 3, 1);
+ forbody(ls, base, line, 1, 1);
}
static void forlist (LexState *ls, TString *indexname) {
- /* forlist -> NAME {,NAME} IN explist1 DO body */
+ /* forlist -> NAME {,NAME} IN explist1 forbody */
FuncState *fs = ls->fs;
expdesc e;
int nvars = 0;
int line;
int base = fs->freereg;
- new_localvarstr(ls, "(for generator)", nvars++);
- new_localvarstr(ls, "(for state)", nvars++);
+ /* create control variables */
+ new_localvarliteral(ls, "(for generator)", nvars++);
+ new_localvarliteral(ls, "(for state)", nvars++);
+ new_localvarliteral(ls, "(for control)", nvars++);
+ /* create declared variables */
new_localvar(ls, indexname, nvars++);
while (testnext(ls, ','))
new_localvar(ls, str_checkname(ls), nvars++);
check(ls, TK_IN);
line = ls->linenumber;
- adjust_assign(ls, nvars, explist1(ls, &e), &e);
+ adjust_assign(ls, 3, explist1(ls, &e), &e);
luaK_checkstack(fs, 3); /* extra space to call generator */
- luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP);
- forbody(ls, base, line, nvars, 0);
+ forbody(ls, base, line, nvars - 3, 0);
}
static void forstat (LexState *ls, int line) {
- /* forstat -> fornum | forlist */
+ /* forstat -> FOR (fornum | forlist) END */
FuncState *fs = ls->fs;
TString *varname;
BlockCnt bl;
- enterblock(fs, &bl, 0); /* block to control variable scope */
+ enterblock(fs, &bl, 1); /* scope for loop and control variables */
next(ls); /* skip `for' */
varname = str_checkname(ls); /* first variable name */
switch (ls->t.token) {
@@ -1102,38 +1137,40 @@ static void forstat (LexState *ls, int line) {
default: luaX_syntaxerror(ls, "`=' or `in' expected");
}
check_match(ls, TK_END, TK_FOR, line);
- leaveblock(fs);
+ leaveblock(fs); /* loop scope (`break' jumps to this point) */
}
-static void test_then_block (LexState *ls, expdesc *v) {
+static int test_then_block (LexState *ls) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */
+ int flist;
next(ls); /* skip IF or ELSEIF */
- cond(ls, v);
+ flist = cond(ls);
check(ls, TK_THEN);
block(ls); /* `then' part */
+ return flist;
}
static void ifstat (LexState *ls, int line) {
/* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
FuncState *fs = ls->fs;
- expdesc v;
+ int flist;
int escapelist = NO_JUMP;
- test_then_block(ls, &v); /* IF cond THEN block */
+ flist = test_then_block(ls); /* IF cond THEN block */
while (ls->t.token == TK_ELSEIF) {
luaK_concat(fs, &escapelist, luaK_jump(fs));
- luaK_patchtohere(fs, v.f);
- test_then_block(ls, &v); /* ELSEIF cond THEN block */
+ luaK_patchtohere(fs, flist);
+ flist = test_then_block(ls); /* ELSEIF cond THEN block */
}
if (ls->t.token == TK_ELSE) {
luaK_concat(fs, &escapelist, luaK_jump(fs));
- luaK_patchtohere(fs, v.f);
+ luaK_patchtohere(fs, flist);
next(ls); /* skip ELSE (after patch, for correct line info) */
block(ls); /* `else' part */
}
else
- luaK_concat(fs, &escapelist, v.f);
+ luaK_concat(fs, &escapelist, flist);
luaK_patchtohere(fs, escapelist);
check_match(ls, TK_END, TK_IF, line);
}
@@ -1324,7 +1361,8 @@ static void chunk (LexState *ls) {
while (!islast && !block_follow(ls->t.token)) {
islast = statement(ls);
testnext(ls, ';');
- lua_assert(ls->fs->freereg >= ls->fs->nactvar);
+ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
+ ls->fs->freereg >= ls->fs->nactvar);
ls->fs->freereg = ls->fs->nactvar; /* free registers */
}
leavelevel(ls);
diff --git a/src/lparser.h b/src/lparser.h
index d6aaaf0e..b4652040 100644
--- a/src/lparser.h
+++ b/src/lparser.h
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.h,v 1.47 2003/02/11 10:46:24 roberto Exp $
+** $Id: lparser.h,v 1.50 2003/08/25 19:51:54 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -41,6 +41,12 @@ typedef struct expdesc {
} expdesc;
+typedef struct upvaldesc {
+ lu_byte k;
+ lu_byte info;
+} upvaldesc;
+
+
struct BlockCnt; /* defined in lparser.c */
@@ -59,13 +65,13 @@ typedef struct FuncState {
int nk; /* number of elements in `k' */
int np; /* number of elements in `p' */
int nlocvars; /* number of elements in `locvars' */
- int nactvar; /* number of active local variables */
- expdesc upvalues[MAXUPVALUES]; /* upvalues */
- int actvar[MAXVARS]; /* declared-variable stack */
+ lu_byte nactvar; /* number of active local variables */
+ upvaldesc upvalues[MAXUPVALUES]; /* upvalues */
+ unsigned short actvar[MAXVARS]; /* declared-variable stack */
} FuncState;
-Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff);
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name);
#endif
diff --git a/src/lstate.c b/src/lstate.c
index b593658d..d1494b58 100644
--- a/src/lstate.c
+++ b/src/lstate.c
@@ -1,11 +1,11 @@
/*
-** $Id: lstate.c,v 1.123 2003/04/03 13:35:34 roberto Exp $
+** $Id: lstate.c,v 2.5 2004/03/23 12:57:12 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
-#include <stdlib.h>
+#include <stddef.h>
#define lstate_c
@@ -34,41 +34,28 @@ union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;};
#endif
+#define state_size(x) (sizeof(x) + EXTRASPACE)
+#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + EXTRASPACE))
+#define fromstate(l) (cast(lu_byte *, (l)) - EXTRASPACE)
+
/*
-** you can change this function through the official API:
-** call `lua_setpanicf'
+** Main thread combines a thread state and the global state
*/
-static int default_panic (lua_State *L) {
- UNUSED(L);
- return 0;
-}
-
-
-static lua_State *mallocstate (lua_State *L) {
- lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE);
- if (block == NULL) return NULL;
- else {
- block += EXTRASPACE;
- return cast(lua_State *, block);
- }
-}
-
-
-static void freestate (lua_State *L, lua_State *L1) {
- luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE,
- sizeof(lua_State) + EXTRASPACE);
-}
+typedef struct LG {
+ lua_State l;
+ global_State g;
+} LG;
+
static void stack_init (lua_State *L1, lua_State *L) {
- L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
+ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
L1->top = L1->stack;
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
L1->ci = L1->base_ci;
- L1->ci->state = CI_C; /* not a Lua function */
setnilvalue(L1->top++); /* `function' entry for this `ci' */
L1->base = L1->ci->base = L1->top;
L1->ci->top = L1->top + LUA_MINSTACK;
@@ -79,7 +66,7 @@ static void stack_init (lua_State *L1, lua_State *L) {
static void freestack (lua_State *L, lua_State *L1) {
luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
- luaM_freearray(L, L1->stack, L1->stacksize, TObject);
+ luaM_freearray(L, L1->stack, L1->stacksize, TValue);
}
@@ -87,54 +74,42 @@ 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) {
- /* create a new global state */
- global_State *g = luaM_new(NULL, global_State);
+ Udata *u; /* head of udata list */
UNUSED(ud);
- if (g == NULL) luaD_throw(L, LUA_ERRMEM);
- L->l_G = g;
- g->mainthread = L;
- g->GCthreshold = 0; /* mark it as unfinished state */
- g->strt.size = 0;
- g->strt.nuse = 0;
- g->strt.hash = NULL;
- setnilvalue(defaultmeta(L));
- setnilvalue(registry(L));
- luaZ_initbuffer(L, &g->buff);
- g->panic = default_panic;
- g->rootgc = NULL;
- g->rootudata = NULL;
- g->tmudata = NULL;
- setnilvalue(gkey(g->dummynode));
- setnilvalue(gval(g->dummynode));
- g->dummynode->next = NULL;
- g->nblocks = sizeof(lua_State) + sizeof(global_State);
+ u = cast(Udata *, luaM_malloc(L, sizeudata(0)));
+ u->uv.len = 0;
+ u->uv.metatable = NULL;
+ G(L)->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 */
- /* create default meta table with a dummy table, and then close the loop */
- defaultmeta(L)->tt = LUA_TTABLE;
- sethvalue(defaultmeta(L), luaH_new(L, 0, 0));
- hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L));
- sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */
- sethvalue(registry(L), luaH_new(L, 4, 4)); /* registry */
+ sethvalue(L, gt(L), luaH_new(L, 0, 4)); /* table of globals */
+ sethvalue(L, registry(L), luaH_new(L, 4, 4)); /* 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(L)->nblocks;
+ G(L)->GCthreshold = 4*G(L)->nblocks;
}
-static void preinit_state (lua_State *L) {
+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;
L->hook = NULL;
- L->hookmask = L->hookinit = 0;
+ L->hookmask = 0;
L->basehookcount = 0;
L->allowhook = 1;
resethookcount(L);
L->openupval = NULL;
L->size_ci = 0;
L->nCcalls = 0;
+ L->isSuspended = 0;
L->base_ci = L->ci = NULL;
L->errfunc = 0;
setnilvalue(gt(L));
@@ -142,30 +117,26 @@ static void preinit_state (lua_State *L) {
static void close_state (lua_State *L) {
+ global_State *g = G(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */
- if (G(L)) { /* close global state */
- luaC_sweep(L, 1); /* collect all elements */
- lua_assert(G(L)->rootgc == NULL);
- lua_assert(G(L)->rootudata == NULL);
- luaS_freeall(L);
- luaZ_freebuffer(L, &G(L)->buff);
- }
+ luaC_sweepall(L); /* collect all elements */
+ lua_assert(g->rootgc == obj2gco(L));
+ luaS_freeall(L);
+ luaZ_freebuffer(L, &g->buff);
freestack(L, L);
- if (G(L)) {
- lua_assert(G(L)->nblocks == sizeof(lua_State) + sizeof(global_State));
- luaM_freelem(NULL, G(L));
- }
- freestate(NULL, L);
+ lua_assert(g->nblocks == sizeof(LG));
+ (*g->realloc)(g->ud, fromstate(L), state_size(LG), 0);
}
lua_State *luaE_newthread (lua_State *L) {
- lua_State *L1 = mallocstate(L);
- luaC_link(L, valtogco(L1), LUA_TTHREAD);
- preinit_state(L1);
- L1->l_G = L->l_G;
+ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
+ L1->next = L->next; /* link new thread after `L' */
+ L->next = obj2gco(L1);
+ preinit_state(L1, G(L));
stack_init(L1, L); /* init stack */
- setobj2n(gt(L1), gt(L)); /* share table of globals */
+ setobj2n(L, gt(L1), gt(L)); /* share table of globals */
+ lua_assert(iswhite(obj2gco(L1)));
return L1;
}
@@ -174,23 +145,47 @@ void luaE_freethread (lua_State *L, lua_State *L1) {
luaF_close(L1, L1->stack); /* close all upvalues for this thread */
lua_assert(L1->openupval == NULL);
freestack(L, L1);
- freestate(L, L1);
+ luaM_free(L, fromstate(L1), state_size(lua_State));
}
-LUA_API lua_State *lua_open (void) {
- lua_State *L = mallocstate(NULL);
- if (L) { /* allocation OK? */
- L->tt = LUA_TTHREAD;
- L->marked = 0;
- L->next = L->gclist = NULL;
- preinit_state(L);
- L->l_G = NULL;
- if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
- /* memory allocation error: free partial state */
- close_state(L);
- L = NULL;
- }
+LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
+ lua_State *L;
+ global_State *g;
+ void *l = (*f)(ud, NULL, 0, state_size(LG));
+ if (l == NULL) return NULL;
+ L = tostate(l);
+ g = &((LG *)L)->g;
+ L->next = NULL;
+ g->currentwhite = bitmask(WHITE0BIT);
+ preinit_state(L, g);
+ g->realloc = f;
+ g->ud = ud;
+ g->mainthread = L;
+ g->GCthreshold = 0; /* mark it as unfinished state */
+ g->strt.size = 0;
+ g->strt.nuse = 0;
+ g->strt.hash = NULL;
+ setnilvalue(registry(L));
+ luaZ_initbuffer(L, &g->buff);
+ g->panic = NULL;
+ g->gcstate = GCSfinalize;
+ 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));
+ g->dummynode->next = NULL;
+ g->nblocks = sizeof(LG);
+ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
+ /* memory allocation error: free partial state */
+ close_state(L);
+ L = NULL;
}
lua_userstateopen(L);
return L;
@@ -207,7 +202,7 @@ LUA_API void lua_close (lua_State *L) {
lua_lock(L);
L = G(L)->mainthread; /* only the main thread can be closed */
luaF_close(L, L->stack); /* close all upvalues for this thread */
- luaC_separateudata(L); /* separate udata that have GC metamethods */
+ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
L->errfunc = 0; /* no error function during GC metamethods */
do { /* repeat until no more errors */
L->ci = L->base_ci;
diff --git a/src/lstate.h b/src/lstate.h
index 5422f1b1..ab01d169 100644
--- a/src/lstate.h
+++ b/src/lstate.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.h,v 1.109 2003/02/27 11:52:30 roberto Exp $
+** $Id: lstate.h,v 2.2 2004/03/23 17:02:58 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -42,9 +42,6 @@
struct lua_longjmp; /* defined in ldo.c */
-/* default meta table (both for tables and udata) */
-#define defaultmeta(L) (&G(L)->_defaultmeta)
-
/* table of globals */
#define gt(L) (&L->_gt)
@@ -64,7 +61,7 @@ struct lua_longjmp; /* defined in ldo.c */
typedef struct stringtable {
GCObject **hash;
- ls_nstr nuse; /* number of elements */
+ lu_int32 nuse; /* number of elements */
int size;
} stringtable;
@@ -75,11 +72,9 @@ typedef struct stringtable {
typedef struct CallInfo {
StkId base; /* base for called function */
StkId top; /* top for this function */
- int state; /* bit fields; see below */
union {
struct { /* for Lua functions */
const Instruction *savedpc;
- const Instruction **pc; /* points to `pc' variable in `luaV_execute' */
int tailcalls; /* number of tail calls lost under this entry */
} l;
struct { /* for C functions */
@@ -89,20 +84,11 @@ typedef struct CallInfo {
} CallInfo;
-/*
-** bit fields for `CallInfo.state'
-*/
-#define CI_C (1<<0) /* 1 if function is a C function */
-/* 1 if (Lua) function has an active `luaV_execute' running it */
-#define CI_HASFRAME (1<<1)
-/* 1 if Lua function is calling another Lua function (and therefore its
- `pc' is being used by the other, and therefore CI_SAVEDPC is 1 too) */
-#define CI_CALLING (1<<2)
-#define CI_SAVEDPC (1<<3) /* 1 if `savedpc' is updated */
-#define CI_YIELD (1<<4) /* 1 if thread is suspended */
-
+#define curr_func(L) (clvalue(L->base - 1))
#define ci_func(ci) (clvalue((ci)->base - 1))
+#define f_isLua(ci) (!ci_func(ci)->c.isC)
+#define isLua(ci) (ttisfunction((ci)->base - 1) && f_isLua(ci))
/*
@@ -110,15 +96,23 @@ typedef struct CallInfo {
*/
typedef struct global_State {
stringtable strt; /* hash table for strings */
- GCObject *rootgc; /* list of (almost) all collectable objects */
- GCObject *rootudata; /* (separated) list of all userdata */
+ lua_Alloc realloc; /* function to reallocate memory */
+ void *ud; /* auxiliary data to `realloc' */
+ int currentwhite;
+ 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 */
+ int gcstate; /* state of garbage collector */
Mbuffer buff; /* temporary buffer for string concatentation */
lu_mem GCthreshold;
lu_mem nblocks; /* number of `bytes' currently allocated */
lua_CFunction panic; /* to be called in unprotected errors */
- TObject _registry;
- TObject _defaultmeta;
+ TValue _registry;
struct lua_State *mainthread;
Node dummynode[1]; /* common node array for all empty tables */
TString *tmname[TM_N]; /* array with tag-method names */
@@ -143,11 +137,11 @@ struct lua_State {
unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask;
lu_byte allowhook;
- lu_byte hookinit;
+ lu_byte isSuspended;
int basehookcount;
int hookcount;
lua_Hook hook;
- TObject _gt; /* table of globals */
+ TValue _gt; /* table of globals */
GCObject *openupval; /* list of open upvalues in this stack */
GCObject *gclist;
struct lua_longjmp *errorJmp; /* current error recover point */
@@ -174,18 +168,20 @@ union GCObject {
/* macros to convert a GCObject into a specific value */
-#define gcotots(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
-#define gcotou(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
-#define gcotocl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
-#define gcotoh(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
-#define gcotop(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
-#define gcotouv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
+#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
+#define gco2ts(o) (&rawgco2ts(o)->tsv)
+#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
+#define gco2u(o) (&rawgco2u(o)->uv)
+#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
+#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
+#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
+#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define ngcotouv(o) \
check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
-#define gcototh(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
+#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
-/* macro to convert any value into a GCObject */
-#define valtogco(v) (cast(GCObject *, (v)))
+/* macro to convert any Lua object into a GCObject */
+#define obj2gco(v) (cast(GCObject *, (v)))
lua_State *luaE_newthread (lua_State *L);
diff --git a/src/lstring.c b/src/lstring.c
index 8cbddbd2..9a26cf03 100644
--- a/src/lstring.c
+++ b/src/lstring.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.c,v 1.78 2002/12/04 17:38:31 roberto Exp $
+** $Id: lstring.c,v 2.1 2003/12/10 12:13:36 roberto Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -25,16 +25,19 @@ void luaS_freeall (lua_State *L) {
void luaS_resize (lua_State *L, int newsize) {
- GCObject **newhash = luaM_newvector(L, newsize, GCObject *);
- stringtable *tb = &G(L)->strt;
+ GCObject **newhash;
+ stringtable *tb;
int i;
+ if (G(L)->sweepstrgc > 0) return; /* cannot resize during GC traverse */
+ newhash = luaM_newvector(L, newsize, GCObject *);
+ tb = &G(L)->strt;
for (i=0; i<newsize; i++) newhash[i] = NULL;
/* rehash */
for (i=0; i<tb->size; i++) {
GCObject *p = tb->hash[i];
while (p) { /* for each node in the list */
GCObject *next = p->gch.next; /* save next */
- lu_hash h = gcotots(p)->tsv.hash;
+ unsigned int h = gco2ts(p)->hash;
int h1 = lmod(h, newsize); /* new position */
lua_assert(cast(int, h%newsize) == lmod(h, newsize));
p->gch.next = newhash[h1]; /* chain it */
@@ -48,12 +51,13 @@ void luaS_resize (lua_State *L, int newsize) {
}
-static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
+static TString *newlstr (lua_State *L, const char *str, size_t l,
+ unsigned int h) {
TString *ts = cast(TString *, luaM_malloc(L, sizestring(l)));
stringtable *tb;
ts->tsv.len = l;
ts->tsv.hash = h;
- ts->tsv.marked = 0;
+ ts->tsv.marked = luaC_white(G(L));
ts->tsv.tt = LUA_TSTRING;
ts->tsv.reserved = 0;
memcpy(ts+1, str, l*sizeof(char));
@@ -61,9 +65,9 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
tb = &G(L)->strt;
h = lmod(h, tb->size);
ts->tsv.next = tb->hash[h]; /* chain new entry */
- tb->hash[h] = valtogco(ts);
+ tb->hash[h] = obj2gco(ts);
tb->nuse++;
- if (tb->nuse > cast(ls_nstr, tb->size) && tb->size <= MAX_INT/2)
+ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
return ts;
}
@@ -71,7 +75,7 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
GCObject *o;
- lu_hash h = (lu_hash)l; /* seed */
+ unsigned int h = cast(unsigned int, l); /* seed */
size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
for (l1=l; l1>=step; l1-=step) /* compute hash */
@@ -79,9 +83,12 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
o != NULL;
o = o->gch.next) {
- TString *ts = gcotots(o);
- if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0))
+ TString *ts = rawgco2ts(o);
+ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
+ /* string may be dead */
+ if (isdead(G(L), o)) changewhite(o);
return ts;
+ }
}
return newlstr(L, str, l, h); /* not found */
}
@@ -90,13 +97,13 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
Udata *luaS_newudata (lua_State *L, size_t s) {
Udata *u;
u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
- u->uv.marked = (1<<1); /* is not finalized */
+ u->uv.marked = luaC_white(G(L)); /* is not finalized */
u->uv.tt = LUA_TUSERDATA;
u->uv.len = s;
- u->uv.metatable = hvalue(defaultmeta(L));
+ u->uv.metatable = NULL;
/* chain it on udata list */
- u->uv.next = G(L)->rootudata;
- G(L)->rootudata = valtogco(u);
+ u->uv.next = G(L)->firstudata->uv.next;
+ G(L)->firstudata->uv.next = obj2gco(u);
return u;
}
diff --git a/src/lstring.h b/src/lstring.h
index be5a1e37..2ca352c4 100644
--- a/src/lstring.h
+++ b/src/lstring.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.h,v 1.37 2002/08/16 14:45:55 roberto Exp $
+** $Id: lstring.h,v 1.38 2003/11/17 19:50:05 roberto Exp $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -8,11 +8,11 @@
#define lstring_h
+#include "lgc.h"
#include "lobject.h"
#include "lstate.h"
-
#define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \
(cast(lu_mem, l)+1)*sizeof(char))
@@ -22,7 +22,7 @@
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s)/sizeof(char))-1))
-#define luaS_fix(s) ((s)->tsv.marked |= (1<<4))
+#define luaS_fix(s) setbit((s)->tsv.marked, FIXEDBIT)
void luaS_resize (lua_State *L, int newsize);
Udata *luaS_newudata (lua_State *L, size_t s);
diff --git a/src/ltable.c b/src/ltable.c
index 0c64adb1..9fc508ba 100644
--- a/src/ltable.c
+++ b/src/ltable.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.c,v 1.132 2003/04/03 13:35:34 roberto Exp $
+** $Id: ltable.c,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -15,10 +15,7 @@
** A main invariant of these tables is that, if an element is not
** in its main position (i.e. the `original' position that its hash gives
** to it), then the colliding element is in its own main position.
-** In other words, there are collisions only when two elements have the
-** same main position (i.e. the same hash values for that table size).
-** Because of that, the load factor of these tables can be 100% without
-** performance penalties.
+** Hence even when the load factor reaches 100%, performance remains good.
*/
#include <string.h>
@@ -45,9 +42,7 @@
#define MAXBITS (BITS_INT-2)
#endif
-/* check whether `x' < 2^MAXBITS */
-#define toobig(x) ((((x)-1) >> MAXBITS) != 0)
-
+#define MAXASIZE (1 << MAXBITS)
/* function to convert a lua_Number to int (with any rounding method) */
#ifndef lua_number2int
@@ -87,7 +82,7 @@ static Node *hashnum (const Table *t, lua_Number n) {
lua_assert(sizeof(a) <= sizeof(n));
memcpy(a, &n, sizeof(a));
for (i = 1; i < numints; i++) a[0] += a[i];
- return hashmod(t, cast(lu_hash, a[0]));
+ return hashmod(t, a[0]);
}
@@ -96,12 +91,12 @@ static Node *hashnum (const Table *t, lua_Number n) {
** returns the `main' position of an element in a table (that is, the index
** of its hash value)
*/
-Node *luaH_mainposition (const Table *t, const TObject *key) {
+Node *luaH_mainposition (const Table *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TNUMBER:
return hashnum(t, nvalue(key));
case LUA_TSTRING:
- return hashstr(t, tsvalue(key));
+ return hashstr(t, rawtsvalue(key));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA:
@@ -116,11 +111,13 @@ Node *luaH_mainposition (const Table *t, const TObject *key) {
** returns the index for `key' if `key' is an appropriate key to live in
** the array part of the table, -1 otherwise.
*/
-static int arrayindex (const TObject *key) {
+static int arrayindex (const TValue *key, lua_Number lim) {
if (ttisnumber(key)) {
+ lua_Number n = nvalue(key);
int k;
- lua_number2int(k, (nvalue(key)));
- if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k))
+ if (n <= 0 || n > lim) return -1; /* out of range? */
+ lua_number2int(k, n);
+ if (cast(lua_Number, k) == nvalue(key))
return k;
}
return -1; /* `key' did not match some condition */
@@ -135,12 +132,12 @@ static int arrayindex (const TObject *key) {
static int luaH_index (lua_State *L, Table *t, StkId key) {
int i;
if (ttisnil(key)) return -1; /* first iteration */
- i = arrayindex(key);
- if (0 <= i && i <= t->sizearray) { /* is `key' inside array part? */
+ i = arrayindex(key, t->sizearray);
+ if (0 <= i) { /* is `key' inside array part? */
return i-1; /* yes; that's the index (corrected to C) */
}
else {
- const TObject *v = luaH_get(t, key);
+ const TValue *v = luaH_get(t, key);
if (v == &luaO_nilobject)
luaG_runerror(L, "invalid key for `next'");
i = cast(int, (cast(const lu_byte *, v) -
@@ -155,14 +152,14 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
for (i++; i < t->sizearray; i++) { /* try first array part */
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
setnvalue(key, cast(lua_Number, i+1));
- setobj2s(key+1, &t->array[i]);
+ setobj2s(L, key+1, &t->array[i]);
return 1;
}
}
for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */
- setobj2s(key, gkey(gnode(t, i)));
- setobj2s(key+1, gval(gnode(t, i)));
+ setobj2s(L, key, gkey(gnode(t, i)));
+ setobj2s(L, key+1, gval(gnode(t, i)));
return 1;
}
}
@@ -202,6 +199,7 @@ static void numuse (const Table *t, int *narray, int *nhash) {
int nums[MAXBITS+1];
int i, lg;
int totaluse = 0;
+ lua_Number sizelimit; /* an upper bound for the array size */
/* 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 */
@@ -221,10 +219,13 @@ static void numuse (const Table *t, int *narray, int *nhash) {
*narray = totaluse; /* all previous uses were in array part */
/* count elements in hash part */
i = sizenode(t);
+ /* array part cannot be larger than twice the maximum number of elements */
+ sizelimit = cast(lua_Number, totaluse + i) * 2;
+ if (sizelimit >= MAXASIZE) sizelimit = MAXASIZE;
while (i--) {
Node *n = &t->node[i];
if (!ttisnil(gval(n))) {
- int k = arrayindex(gkey(n));
+ int k = arrayindex(gkey(n), sizelimit);
if (k >= 0) { /* is `key' an appropriate array index? */
nums[luaO_log2(k-1)+1]++; /* count as such */
(*narray)++;
@@ -238,7 +239,7 @@ static void numuse (const Table *t, int *narray, int *nhash) {
static void setarrayvector (lua_State *L, Table *t, int size) {
int i;
- luaM_reallocvector(L, t->array, t->sizearray, size, TObject);
+ luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
for (i=t->sizearray; i<size; i++)
setnilvalue(&t->array[i]);
t->sizearray = size;
@@ -295,16 +296,16 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
/* re-insert elements from vanishing slice */
for (i=nasize; i<oldasize; i++) {
if (!ttisnil(&t->array[i]))
- setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]);
+ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
}
/* shrink array */
- luaM_reallocvector(L, t->array, oldasize, nasize, TObject);
+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
}
/* re-insert elements in hash part */
for (i = twoto(oldhsize) - 1; i >= 0; i--) {
Node *old = nold+i;
if (!ttisnil(gval(old)))
- setobjt2t(luaH_set(L, t, gkey(old)), gval(old));
+ setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old));
}
if (oldhsize)
luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
@@ -326,8 +327,8 @@ static void rehash (lua_State *L, Table *t) {
Table *luaH_new (lua_State *L, int narray, int lnhash) {
Table *t = luaM_new(L, Table);
- luaC_link(L, valtogco(t), LUA_TTABLE);
- t->metatable = hvalue(defaultmeta(L));
+ luaC_link(L, obj2gco(t), LUA_TTABLE);
+ t->metatable = NULL;
t->flags = cast(lu_byte, ~0);
/* temporary values (kept only if some malloc fails) */
t->array = NULL;
@@ -343,7 +344,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) {
void luaH_free (lua_State *L, Table *t) {
if (t->lsizenode)
luaM_freearray(L, t->node, sizenode(t), Node);
- luaM_freearray(L, t->array, t->sizearray, TObject);
+ luaM_freearray(L, t->array, t->sizearray, TValue);
luaM_freelem(L, t);
}
@@ -376,8 +377,8 @@ void luaH_remove (Table *t, Node *e) {
** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position.
*/
-static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
- TObject *val;
+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? */
Node *othern = luaH_mainposition(t, gkey(mp)); /* `mp' of colliding node */
@@ -397,7 +398,8 @@ static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
mp = n;
}
}
- setobj2t(gkey(mp), key); /* write barrier */
+ setobj2t(L, gkey(mp), key);
+ luaC_barrier(L, t, key);
lua_assert(ttisnil(gval(mp)));
for (;;) { /* correct `firstfree' */
if (ttisnil(gkey(t->firstfree)))
@@ -408,7 +410,7 @@ static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
/* no more free places; must create one */
setbvalue(gval(mp), 0); /* avoid new key being removed */
rehash(L, t); /* grow table */
- val = cast(TObject *, luaH_get(t, key)); /* get new position */
+ val = cast(TValue *, luaH_get(t, key)); /* get new position */
lua_assert(ttisboolean(val));
setnilvalue(val);
return val;
@@ -418,23 +420,22 @@ static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
/*
** generic search function
*/
-static const TObject *luaH_getany (Table *t, const TObject *key) {
- if (ttisnil(key)) return &luaO_nilobject;
- else {
+static const TValue *luaH_getany (Table *t, const TValue *key) {
+ if (!ttisnil(key)) {
Node *n = luaH_mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */
if (luaO_rawequalObj(gkey(n), key)) return gval(n); /* that's it */
else n = n->next;
} while (n);
- return &luaO_nilobject;
}
+ return &luaO_nilobject;
}
/*
** search function for integers
*/
-const TObject *luaH_getnum (Table *t, int key) {
+const TValue *luaH_getnum (Table *t, int key) {
if (1 <= key && key <= t->sizearray)
return &t->array[key-1];
else {
@@ -453,10 +454,10 @@ const TObject *luaH_getnum (Table *t, int key) {
/*
** search function for strings
*/
-const TObject *luaH_getstr (Table *t, TString *key) {
+const TValue *luaH_getstr (Table *t, TString *key) {
Node *n = hashstr(t, key);
do { /* check whether `key' is somewhere in the chain */
- if (ttisstring(gkey(n)) && tsvalue(gkey(n)) == key)
+ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
return gval(n); /* that's it */
else n = n->next;
} while (n);
@@ -467,9 +468,9 @@ const TObject *luaH_getstr (Table *t, TString *key) {
/*
** main search function
*/
-const TObject *luaH_get (Table *t, const TObject *key) {
+const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
- case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
case LUA_TNUMBER: {
int k;
lua_number2int(k, (nvalue(key)));
@@ -482,11 +483,11 @@ const TObject *luaH_get (Table *t, const TObject *key) {
}
-TObject *luaH_set (lua_State *L, Table *t, const TObject *key) {
- const TObject *p = luaH_get(t, key);
+TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
+ const TValue *p = luaH_get(t, key);
t->flags = 0;
if (p != &luaO_nilobject)
- return cast(TObject *, p);
+ return cast(TValue *, p);
else {
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
else if (ttisnumber(key) && nvalue(key) != nvalue(key))
@@ -496,14 +497,26 @@ TObject *luaH_set (lua_State *L, Table *t, const TObject *key) {
}
-TObject *luaH_setnum (lua_State *L, Table *t, int key) {
- const TObject *p = luaH_getnum(t, key);
+TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+ const TValue *p = luaH_getnum(t, key);
if (p != &luaO_nilobject)
- return cast(TObject *, p);
+ return cast(TValue *, p);
else {
- TObject k;
+ TValue k;
setnvalue(&k, cast(lua_Number, key));
return newkey(L, t, &k);
}
}
+
+TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
+ const TValue *p = luaH_getstr(t, key);
+ if (p != &luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+ setsvalue(L, &k, key);
+ return newkey(L, t, &k);
+ }
+}
+
diff --git a/src/ltable.h b/src/ltable.h
index 3d4d753c..566d7cd4 100644
--- a/src/ltable.h
+++ b/src/ltable.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.h,v 1.44 2003/03/18 12:50:04 roberto Exp $
+** $Id: ltable.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -15,17 +15,18 @@
#define gval(n) (&(n)->i_val)
-const TObject *luaH_getnum (Table *t, int key);
-TObject *luaH_setnum (lua_State *L, Table *t, int key);
-const TObject *luaH_getstr (Table *t, TString *key);
-const TObject *luaH_get (Table *t, const TObject *key);
-TObject *luaH_set (lua_State *L, Table *t, const TObject *key);
+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);
+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_free (lua_State *L, Table *t);
int luaH_next (lua_State *L, Table *t, StkId key);
/* exported only for debugging */
-Node *luaH_mainposition (const Table *t, const TObject *key);
+Node *luaH_mainposition (const Table *t, const TValue *key);
#endif
diff --git a/src/ltm.c b/src/ltm.c
index 1b3e515e..de4bb7af 100644
--- a/src/ltm.c
+++ b/src/ltm.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.c,v 1.106 2003/04/03 13:35:34 roberto Exp $
+** $Id: ltm.c,v 2.2 2004/02/16 19:09:52 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -21,7 +21,8 @@
const char *const luaT_typenames[] = {
"nil", "boolean", "userdata", "number",
- "string", "table", "function", "userdata", "thread"
+ "string", "table", "function", "userdata", "thread",
+ "proto", "upval"
};
@@ -45,8 +46,8 @@ void luaT_init (lua_State *L) {
** function to be used with macro "fasttm": optimized for absence of
** tag methods
*/
-const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
- const TObject *tm = luaH_getstr(events, ename);
+const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
+ const TValue *tm = luaH_getstr(events, ename);
lua_assert(event <= TM_EQ);
if (ttisnil(tm)) { /* no tag method? */
events->flags |= cast(lu_byte, 1u<<event); /* cache this fact */
@@ -56,15 +57,18 @@ const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
}
-const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event) {
- TString *ename = G(L)->tmname[event];
+const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
+ Table *mt;
switch (ttype(o)) {
case LUA_TTABLE:
- return luaH_getstr(hvalue(o)->metatable, ename);
+ mt = hvalue(o)->metatable;
+ break;
case LUA_TUSERDATA:
- return luaH_getstr(uvalue(o)->uv.metatable, ename);
+ mt = uvalue(o)->metatable;
+ break;
default:
- return &luaO_nilobject;
+ mt = NULL;
}
+ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : &luaO_nilobject);
}
diff --git a/src/ltm.h b/src/ltm.h
index 8eebfd3d..226feb75 100644
--- a/src/ltm.h
+++ b/src/ltm.h
@@ -1,5 +1,5 @@
/*
-** $Id: ltm.h,v 1.41 2002/11/14 11:51:50 roberto Exp $
+** $Id: ltm.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -36,14 +36,14 @@ typedef enum {
-#define gfasttm(g,et,e) \
- (((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
+#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
+ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
#define fasttm(l,et,e) gfasttm(G(l), et, e)
-const TObject *luaT_gettm (Table *events, TMS event, TString *ename);
-const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event);
+const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
+const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event);
void luaT_init (lua_State *L);
extern const char *const luaT_typenames[];
diff --git a/src/lua/RCS b/src/lua/RCS
new file mode 120000
index 00000000..1ae38936
--- /dev/null
+++ b/src/lua/RCS
@@ -0,0 +1 @@
+../RCS \ No newline at end of file
diff --git a/src/lua/README b/src/lua/README
index febd229a..fca1e900 100644
--- a/src/lua/README
+++ b/src/lua/README
@@ -2,7 +2,7 @@ This is lua, a sample Lua interpreter.
It can be used as a batch interpreter and also interactively.
There are man pages for it in both nroff and html in ../../doc.
-Usage: ./lua [options] [script [args]]. Available options are:
+Usage: lua [options] [script [args]]. Available options are:
- execute stdin as a file
-e stat execute string `stat'
-i enter interactive mode after executing `script'
diff --git a/src/lua/lua.c b/src/lua/lua.c
index 28c84cb6..4e669c07 100644
--- a/src/lua/lua.c
+++ b/src/lua/lua.c
@@ -1,5 +1,5 @@
/*
-** $Id: lua.c,v 1.122 2003/04/03 13:34:42 roberto Exp $
+** $Id: lua.c,v 1.124 2003/10/23 18:06:22 roberto Exp $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -117,10 +117,9 @@ static void l_message (const char *pname, const char *msg) {
static int report (int status) {
- const char *msg;
- if (status) {
- msg = lua_tostring(L, -1);
- if (msg == NULL) msg = "(error with no message)";
+ if (status && !lua_isnil(L, -1)) {
+ const char *msg = lua_tostring(L, -1);
+ if (msg == NULL) msg = "(error object is not a string)";
l_message(progname, msg);
lua_pop(L, 1);
}
@@ -155,10 +154,6 @@ static void getargs (char *argv[], int n) {
lua_pushstring(L, argv[i]);
lua_rawset(L, -3);
}
- /* arg.n = maximum index in table `arg' */
- lua_pushliteral(L, "n");
- lua_pushnumber(L, i-n-1);
- lua_rawset(L, -3);
}
diff --git a/src/luac/Makefile b/src/luac/Makefile
index 9e772b41..a6c7d38f 100644
--- a/src/luac/Makefile
+++ b/src/luac/Makefile
@@ -12,8 +12,8 @@ T= $(BIN)/luac
all: $T
-$T: $(OBJS) $(LIB)/liblua.a $(LIB)/liblualib.a
- $(CC) -o $@ $(MYLDFLAGS) $(OBJS) -L$(LIB) -llua -llualib $(EXTRA_LIBS) $(DLLIB)
+$T: $(OBJS) $(LIB)/liblua.a ../lib/lauxlib.o
+ $(CC) -o $@ $(MYLDFLAGS) $(OBJS) ../lib/lauxlib.o -L$(LIB) -llua $(EXTRA_LIBS)
# print.c needs opcode names from lopcodes.c
lopcodes.o: ../lopcodes.c ../lopcodes.h
@@ -22,8 +22,8 @@ lopcodes.o: ../lopcodes.c ../lopcodes.h
$(LIB)/liblua.a:
cd ..; $(MAKE)
-$(LIB)/liblualib.a:
- cd ../lib; $(MAKE)
+../lib/lauxlib.o:
+ cd ../lib; $(MAKE) lauxlib.o
clean:
rm -f $(OBJS) $T
diff --git a/src/luac/RCS b/src/luac/RCS
new file mode 120000
index 00000000..1ae38936
--- /dev/null
+++ b/src/luac/RCS
@@ -0,0 +1 @@
+../RCS \ No newline at end of file
diff --git a/src/luac/README b/src/luac/README
index ada7bc4b..140d9457 100644
--- a/src/luac/README
+++ b/src/luac/README
@@ -6,7 +6,7 @@ The main advantages of pre-compiling chunks are: faster loading, protecting
source code from user changes, and off-line syntax error detection.
luac can also be used to learn about the Lua virtual machine.
-Usage: /l/luac/luac [options] [filenames]. Available options are:
+Usage: luac [options] [filenames]. Available options are:
- process stdin
-l list
-o name output to file `name' (default is "luac.out")
diff --git a/src/luac/luac.c b/src/luac/luac.c
index 1aff0bd9..f634d5f9 100644
--- a/src/luac/luac.c
+++ b/src/luac/luac.c
@@ -1,9 +1,10 @@
/*
-** $Id: luac.c,v 1.44a 2003/04/07 20:34:20 lhf Exp $
+** $Id: luac.c,v 1.47 2004/03/24 00:25:08 lhf Exp $
** Lua compiler (saves bytecodes to files; also list bytecodes)
** See Copyright Notice in lua.h
*/
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -11,6 +12,7 @@
#include "lua.h"
#include "lauxlib.h"
+#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
@@ -18,21 +20,19 @@
#include "lstring.h"
#include "lundump.h"
-#ifndef LUA_DEBUG
-#define luaB_opentests(L)
-#endif
-
#ifndef PROGNAME
-#define PROGNAME "luac" /* program name */
+#define PROGNAME "luac" /* default program name */
#endif
+#ifndef OUTPUT
#define OUTPUT "luac.out" /* default output file */
+#endif
static int listing=0; /* list bytecodes? */
static int dumping=1; /* dump bytecodes? */
static int stripping=0; /* strip debug information? */
static char Output[]={ OUTPUT }; /* default output file name */
-static const char* output=Output; /* output file name */
+static const char* output=Output; /* actual output file name */
static const char* progname=PROGNAME; /* actual program name */
static void fatal(const char* message)
@@ -41,29 +41,30 @@ static void fatal(const char* message)
exit(EXIT_FAILURE);
}
-static void cannot(const char* name, const char* what, const char* mode)
+static void cannot(const char* what)
{
- fprintf(stderr,"%s: cannot %s %sput file ",progname,what,mode);
- perror(name);
+ fprintf(stderr,"%s: cannot %s output file %s: %s\n",
+ progname,what,output,strerror(errno));
exit(EXIT_FAILURE);
}
-static void usage(const char* message, const char* arg)
+static void usage(const char* message)
{
- if (message!=NULL)
- {
- fprintf(stderr,"%s: ",progname); fprintf(stderr,message,arg); fprintf(stderr,"\n");
- }
+ if (*message=='-')
+ fprintf(stderr,"%s: unrecognized option `%s'\n",progname,message);
+ else
+ fprintf(stderr,"%s: %s\n",progname,message);
fprintf(stderr,
- "usage: %s [options] [filenames]. Available options are:\n"
+ "usage: %s [options] [filenames].\n"
+ "Available options are:\n"
" - process stdin\n"
" -l list\n"
- " -o name output to file `name' (default is \"" OUTPUT "\")\n"
+ " -o name output to file `name' (default is \"%s\")\n"
" -p parse only\n"
" -s strip debug information\n"
" -v show version information\n"
" -- stop handling options\n",
- progname);
+ progname,Output);
exit(EXIT_FAILURE);
}
@@ -89,7 +90,7 @@ static int doargs(int argc, char* argv[])
else if (IS("-o")) /* output file */
{
output=argv[++i];
- if (output==NULL || *output==0) usage("`-o' needs argument",NULL);
+ if (output==NULL || *output==0) usage("`-o' needs argument");
}
else if (IS("-p")) /* parse only */
dumping=0;
@@ -101,7 +102,7 @@ static int doargs(int argc, char* argv[])
if (argc==2) exit(EXIT_SUCCESS);
}
else /* unknown option */
- usage("unrecognized option `%s'",argv[i]);
+ usage(argv[i]);
}
if (i==argc && (listing || !dumping))
{
@@ -125,6 +126,7 @@ static Proto* combine(lua_State* L, int n)
{
int i,pc=0;
Proto* f=luaF_newproto(L);
+ setptvalue2s(L,L->top,f); incr_top(L);
f->source=luaS_newliteral(L,"=(" PROGNAME ")");
f->maxstacksize=1;
f->p=luaM_newvector(L,n,Proto*);
@@ -142,23 +144,17 @@ static Proto* combine(lua_State* L, int n)
}
}
-static void strip(lua_State* L, Proto* f)
+static int writer(lua_State* L, const void* p, size_t size, void* u)
{
- int i,n=f->sizep;
- luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
- luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
- luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
- f->lineinfo=NULL; f->sizelineinfo=0;
- f->locvars=NULL; f->sizelocvars=0;
- f->upvalues=NULL; f->sizeupvalues=0;
- f->source=luaS_newliteral(L,"=(none)");
- for (i=0; i<n; i++) strip(L,f->p[i]);
+ UNUSED(L);
+ return fwrite(p,size,1,(FILE*)u)==1;
}
-static int writer(lua_State* L, const void* p, size_t size, void* u)
+static int panic(lua_State *L)
{
UNUSED(L);
- return fwrite(p,size,1,(FILE*)u)==1;
+ fatal("not enough memory!");
+ return 0;
}
int main(int argc, char* argv[])
@@ -167,9 +163,11 @@ int main(int argc, char* argv[])
Proto* f;
int i=doargs(argc,argv);
argc-=i; argv+=i;
- if (argc<=0) usage("no input files given",NULL);
+ if (argc<=0) usage("no input files given");
L=lua_open();
- luaB_opentests(L);
+ if (L==NULL) fatal("not enough memory for state");
+ lua_atpanic(L,panic);
+ if (!lua_checkstack(L,argc)) fatal("too many input files");
for (i=0; i<argc; i++)
{
const char* filename=IS("-") ? NULL : argv[i];
@@ -180,14 +178,13 @@ int main(int argc, char* argv[])
if (dumping)
{
FILE* D=fopen(output,"wb");
- if (D==NULL) cannot(output,"open","out");
- if (stripping) strip(L,f);
+ if (D==NULL) cannot("open");
lua_lock(L);
- luaU_dump(L,f,writer,D);
+ luaU_dump(L,f,writer,D,stripping);
lua_unlock(L);
- if (ferror(D)) cannot(output,"write","out");
- fclose(D);
+ if (ferror(D)) cannot("write");
+ if (fclose(D)) cannot("close");
}
lua_close(L);
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/src/luac/print.c b/src/luac/print.c
index d0b5efb2..2f9e7d12 100644
--- a/src/luac/print.c
+++ b/src/luac/print.c
@@ -1,12 +1,12 @@
/*
-** $Id: print.c,v 1.44 2003/04/07 20:34:20 lhf Exp $
+** $Id: print.c,v 1.46 2004/03/24 00:25:08 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
#include <stdio.h>
-#if 0
+#if 1
#define DEBUG_PRINT
#endif
@@ -46,7 +46,7 @@ static void PrintString(const Proto* f, int n)
static void PrintConstant(const Proto* f, int i)
{
- const TObject* o=&f->k[i];
+ const TValue* o=&f->k[i];
switch (ttype(o))
{
case LUA_TNUMBER:
@@ -75,8 +75,8 @@ static void PrintCode(const Proto* f)
int a=GETARG_A(i);
int b=GETARG_B(i);
int c=GETARG_C(i);
- int bc=GETARG_Bx(i);
- int sbc=GETARG_sBx(i);
+ int bx=GETARG_Bx(i);
+ int sbx=GETARG_sBx(i);
int line=getline(f,pc);
#if 0
printf("%0*lX",Sizeof(i)*2,i);
@@ -86,14 +86,24 @@ static void PrintCode(const Proto* f)
printf("%-9s\t",luaP_opnames[o]);
switch (getOpMode(o))
{
- case iABC: printf("%d %d %d",a,b,c); break;
- case iABx: printf("%d %d",a,bc); break;
- case iAsBx: printf("%d %d",a,sbc); break;
+ case iABC:
+ printf("%d",a);
+ if (getBMode(o)!=OpArgN)
+ { if (b>=MAXSTACK) printf(" #%d",b-MAXSTACK); else printf(" %d",b); }
+ if (getCMode(o)!=OpArgN)
+ { if (c>=MAXSTACK) printf(" #%d",c-MAXSTACK); else printf(" %d",c); }
+ break;
+ case iABx:
+ if (getBMode(o)==OpArgK) printf("%d #%d",a,bx); else printf("%d %d",a,bx);
+ break;
+ case iAsBx:
+ if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
+ break;
}
switch (o)
{
case OP_LOADK:
- printf("\t; "); PrintConstant(f,bc);
+ printf("\t; "); PrintConstant(f,bx);
break;
case OP_GETUPVAL:
case OP_SETUPVAL:
@@ -101,7 +111,7 @@ static void PrintCode(const Proto* f)
break;
case OP_GETGLOBAL:
case OP_SETGLOBAL:
- printf("\t; %s",svalue(&f->k[bc]));
+ printf("\t; %s",svalue(&f->k[bx]));
break;
case OP_GETTABLE:
case OP_SELF:
@@ -121,16 +131,17 @@ static void PrintCode(const Proto* f)
printf("\t; ");
if (b>=MAXSTACK) PrintConstant(f,b-MAXSTACK); else printf("-");
printf(" ");
- if (c>=MAXSTACK) PrintConstant(f,c-MAXSTACK);
+ if (c>=MAXSTACK) PrintConstant(f,c-MAXSTACK); else printf("-");
}
break;
case OP_JMP:
case OP_FORLOOP:
+ case OP_FORPREP:
case OP_TFORPREP:
- printf("\t; to %d",sbc+pc+2);
+ printf("\t; to %d",sbx+pc+2);
break;
case OP_CLOSURE:
- printf("\t; %p",VOID(f->p[bc]));
+ printf("\t; %p",VOID(f->p[bx]));
break;
default:
break;
@@ -187,7 +198,7 @@ static void PrintLocals(const Proto* f)
for (i=0; i<n; i++)
{
printf("\t%d\t%s\t%d\t%d\n",
- i,getstr(f->locvars[i].varname),f->locvars[i].startpc,f->locvars[i].endpc);
+ i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
}
}
diff --git a/src/lundump.c b/src/lundump.c
index 151a8507..d79dd898 100644
--- a/src/lundump.c
+++ b/src/lundump.c
@@ -1,14 +1,18 @@
/*
-** $Id: lundump.c,v 1.49 2003/04/07 20:34:20 lhf Exp $
+** $Id: lundump.c,v 1.51 2004/03/24 00:25:08 lhf Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
+#include <stdarg.h>
+#include <stddef.h>
+
#define lundump_c
#include "lua.h"
#include "ldebug.h"
+#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lopcodes.h"
@@ -26,22 +30,28 @@ typedef struct {
const char* name;
} LoadState;
-static void unexpectedEOZ (LoadState* S)
+static void error (LoadState* S, const char* fmt, ...)
{
- luaG_runerror(S->L,"unexpected end of file in %s",S->name);
+ const char *msg;
+ va_list argp;
+ va_start(argp,fmt);
+ msg=luaO_pushvfstring(S->L,fmt,argp);
+ va_end(argp);
+ luaO_pushfstring(S->L,"%s: %s",S->name,msg);
+ luaD_throw(S->L,LUA_ERRSYNTAX);
}
static int ezgetc (LoadState* S)
{
int c=zgetc(S->Z);
- if (c==EOZ) unexpectedEOZ(S);
+ if (c==EOZ) error(S,"unexpected end of file");
return c;
}
static void ezread (LoadState* S, void* b, int n)
{
int r=luaZ_read(S->Z,b,n);
- if (r!=0) unexpectedEOZ(S);
+ if (r!=0) error(S,"unexpected end of file");
}
static void LoadBlock (LoadState* S, void* b, size_t size)
@@ -77,7 +87,7 @@ static int LoadInt (LoadState* S)
{
int x;
LoadBlock(S,&x,sizeof(x));
- if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name);
+ if (x<0) error(S,"bad integer");
return x;
}
@@ -113,7 +123,7 @@ static void LoadCode (LoadState* S, Proto* f)
int size=LoadInt(S);
f->code=luaM_newvector(S->L,size,Instruction);
f->sizecode=size;
- LoadVector(S,f->code,size,sizeof(*f->code));
+ LoadVector(S,f->code,size,sizeof(Instruction));
}
static void LoadLocals (LoadState* S, Proto* f)
@@ -122,6 +132,7 @@ static void LoadLocals (LoadState* S, Proto* f)
n=LoadInt(S);
f->locvars=luaM_newvector(S->L,n,LocVar);
f->sizelocvars=n;
+ for (i=0; i<n; i++) f->locvars[i].varname=NULL;
for (i=0; i<n; i++)
{
f->locvars[i].varname=LoadString(S);
@@ -135,18 +146,18 @@ static void LoadLines (LoadState* S, Proto* f)
int size=LoadInt(S);
f->lineinfo=luaM_newvector(S->L,size,int);
f->sizelineinfo=size;
- LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo));
+ LoadVector(S,f->lineinfo,size,sizeof(int));
}
static void LoadUpvalues (LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
- if (n!=0 && n!=f->nups)
- luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d",
- S->name,n,f->nups);
+ if (n!=0 && n!=f->nups)
+ error(S,"bad nupvalues (read %d; expected %d)",n,f->nups);
f->upvalues=luaM_newvector(S->L,n,TString*);
f->sizeupvalues=n;
+ for (i=0; i<n; i++) f->upvalues[i]=NULL;
for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
}
@@ -156,11 +167,12 @@ static void LoadConstants (LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
- f->k=luaM_newvector(S->L,n,TObject);
+ f->k=luaM_newvector(S->L,n,TValue);
f->sizek=n;
+ for (i=0; i<n; i++) setnilvalue(&f->k[i]);
for (i=0; i<n; i++)
{
- TObject* o=&f->k[i];
+ TValue* o=&f->k[i];
int t=LoadByte(S);
switch (t)
{
@@ -168,25 +180,27 @@ static void LoadConstants (LoadState* S, Proto* f)
setnvalue(o,LoadNumber(S));
break;
case LUA_TSTRING:
- setsvalue2n(o,LoadString(S));
+ setsvalue2n(S->L,o,LoadString(S));
break;
case LUA_TNIL:
setnilvalue(o);
break;
default:
- luaG_runerror(S->L,"bad constant type (%d) in %s",t,S->name);
+ error(S,"bad constant type (%d)",t);
break;
}
}
n=LoadInt(S);
f->p=luaM_newvector(S->L,n,Proto*);
f->sizep=n;
+ for (i=0; i<n; i++) f->p[i]=NULL;
for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
}
static Proto* LoadFunction (LoadState* S, TString* p)
{
Proto* f=luaF_newproto(S->L);
+ setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
f->source=LoadString(S); if (f->source==NULL) f->source=p;
f->lineDefined=LoadInt(S);
f->nups=LoadByte(S);
@@ -199,8 +213,9 @@ static Proto* LoadFunction (LoadState* S, TString* p)
LoadConstants(S,f);
LoadCode(S,f);
#ifndef TRUST_BINARIES
- if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name);
+ if (!luaG_checkcode(f)) error(S,"bad code");
#endif
+ S->L->top--;
return f;
}
@@ -209,18 +224,16 @@ static void LoadSignature (LoadState* S)
const char* s=LUA_SIGNATURE;
while (*s!=0 && ezgetc(S)==*s)
++s;
- if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name);
+ if (*s!=0) error(S,"bad signature");
}
static void TestSize (LoadState* S, int s, const char* what)
{
int r=LoadByte(S);
if (r!=s)
- luaG_runerror(S->L,"virtual machine mismatch in %s: "
- "size of %s is %d but read %d",S->name,what,s,r);
+ error(S,"bad size of %s (read %d; expected %d)",what,r,s);
}
-#define TESTSIZE(s,w) TestSize(S,s,w)
#define V(v) v/16,v%16
static void LoadHeader (LoadState* S)
@@ -230,40 +243,27 @@ static void LoadHeader (LoadState* S)
LoadSignature(S);
version=LoadByte(S);
if (version>VERSION)
- luaG_runerror(S->L,"%s too new: "
- "read version %d.%d; expected at most %d.%d",
- S->name,V(version),V(VERSION));
+ error(S,"bad version (read %d.%d; expected at %s %d.%d)",
+ V(version),"most",V(VERSION));
if (version<VERSION0) /* check last major change */
- luaG_runerror(S->L,"%s too old: "
- "read version %d.%d; expected at least %d.%d",
- S->name,V(version),V(VERSION0));
+ error(S,"bad version (read %d.%d; expected at %s %d.%d)",
+ V(version),"least",V(VERSION0));
S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */
- TESTSIZE(sizeof(int),"int");
- TESTSIZE(sizeof(size_t), "size_t");
- TESTSIZE(sizeof(Instruction), "Instruction");
- TESTSIZE(SIZE_OP, "OP");
- TESTSIZE(SIZE_A, "A");
- TESTSIZE(SIZE_B, "B");
- TESTSIZE(SIZE_C, "C");
- TESTSIZE(sizeof(lua_Number), "number");
+ TestSize(S,sizeof(int),"int");
+ TestSize(S,sizeof(size_t),"size_t");
+ TestSize(S,sizeof(Instruction),"instruction");
+ TestSize(S,sizeof(lua_Number),"number");
x=LoadNumber(S);
if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */
- luaG_runerror(S->L,"unknown number format in %s",S->name);
-}
-
-static Proto* LoadChunk (LoadState* S)
-{
- LoadHeader(S);
- return LoadFunction(S,NULL);
+ error(S,"unknown number format");
}
/*
** load precompiled chunk
*/
-Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff)
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* s)
{
LoadState S;
- const char* s=zname(Z);
if (*s=='@' || *s=='=')
S.name=s+1;
else if (*s==LUA_SIGNATURE[0])
@@ -273,7 +273,8 @@ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff)
S.L=L;
S.Z=Z;
S.b=buff;
- return LoadChunk(&S);
+ LoadHeader(&S);
+ return LoadFunction(&S,NULL);
}
/*
diff --git a/src/lundump.h b/src/lundump.h
index c7e6959b..26c792a8 100644
--- a/src/lundump.h
+++ b/src/lundump.h
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.h,v 1.30 2003/04/07 20:34:20 lhf Exp $
+** $Id: lundump.h,v 1.32 2003/12/09 19:22:19 lhf Exp $
** load pre-compiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -11,21 +11,20 @@
#include "lzio.h"
/* load one chunk; from lundump.c */
-Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff);
+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char *name);
/* find byte order; from lundump.c */
int luaU_endianness (void);
/* dump one chunk; from ldump.c */
-void luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data);
+int luaU_dump (lua_State* L, const Proto* Main, lua_Chunkwriter w, void* data, int strip);
/* print one chunk; from print.c */
void luaU_print (const Proto* Main);
/* definitions for headers of binary files */
-#define LUA_SIGNATURE "\033Lua" /* binary files start with "<esc>Lua" */
-#define VERSION 0x50 /* last format change was in 5.0 */
-#define VERSION0 0x50 /* last major change was in 5.0 */
+#define VERSION 0x51 /* last format change was in 5.1 */
+#define VERSION0 0x51 /* last major change was in 5.1 */
/* a multiple of PI for testing native format */
/* multiplying by 1E7 gives non-trivial integer values */
diff --git a/src/lvm.c b/src/lvm.c
index 94e2802d..bfbe8bf2 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -1,11 +1,10 @@
/*
-** $Id: lvm.c,v 1.284b 2003/04/03 13:35:34 roberto Exp $
+** $Id: lvm.c,v 2.2 2004/03/16 12:31:40 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
-#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@@ -40,7 +39,7 @@
#define MAXTAGLOOP 100
-const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
+const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
lua_Number num;
if (ttisnumber(obj)) return obj;
if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
@@ -58,15 +57,18 @@ int luaV_tostring (lua_State *L, StkId obj) {
else {
char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */
lua_number2str(s, nvalue(obj));
- setsvalue2s(obj, luaS_new(L, s));
+ setsvalue2s(L, obj, luaS_new(L, s));
return 1;
}
}
-static void traceexec (lua_State *L) {
+static void traceexec (lua_State *L, const Instruction *pc) {
lu_byte mask = L->hookmask;
- if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */
+ CallInfo *ci = L->ci;
+ const Instruction *oldpc = ci->u.l.savedpc;
+ ci->u.l.savedpc = pc;
+ if (mask > LUA_MASKLINE) { /* instruction-hook set? */
if (L->hookcount == 0) {
resethookcount(L);
luaD_callhook(L, LUA_HOOKCOUNT, -1);
@@ -74,108 +76,82 @@ static void traceexec (lua_State *L) {
}
}
if (mask & LUA_MASKLINE) {
- CallInfo *ci = L->ci;
Proto *p = ci_func(ci)->l.p;
- int newline = getline(p, pcRel(*ci->u.l.pc, p));
- if (!L->hookinit) {
- luaG_inithooks(L);
- return;
- }
- lua_assert(ci->state & CI_HASFRAME);
- if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */
- ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */
- /* calls linehook when enters a new line or jumps back (loop) */
- if (*ci->u.l.pc <= ci->u.l.savedpc ||
- newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
+ int npc = pcRel(pc, p);
+ int newline = getline(p, npc);
+ /* call linehook when enter a new function, when jump back (loop),
+ or when enter a new line */
+ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
luaD_callhook(L, LUA_HOOKLINE, newline);
- ci = L->ci; /* previous call may reallocate `ci' */
- }
- ci->u.l.savedpc = *ci->u.l.pc;
}
}
-static void callTMres (lua_State *L, const TObject *f,
- const TObject *p1, const TObject *p2) {
- setobj2s(L->top, f); /* push function */
- setobj2s(L->top+1, p1); /* 1st argument */
- setobj2s(L->top+2, p2); /* 2nd argument */
- luaD_checkstack(L, 3); /* cannot check before (could invalidate p1, p2) */
+static void prepTMcall (lua_State *L, const TValue *f,
+ const TValue *p1, const TValue *p2) {
+ setobj2s(L, L->top, f); /* push function */
+ setobj2s(L, L->top+1, p1); /* 1st argument */
+ setobj2s(L, L->top+2, p2); /* 2nd argument */
+}
+
+
+static void callTMres (lua_State *L, StkId res) {
+ ptrdiff_t result = savestack(L, res);
+ luaD_checkstack(L, 3);
L->top += 3;
luaD_call(L, L->top - 3, 1);
- L->top--; /* result will be in L->top */
+ res = restorestack(L, result);
+ L->top--;
+ setobjs2s(L, res, L->top);
}
-static void callTM (lua_State *L, const TObject *f,
- const TObject *p1, const TObject *p2, const TObject *p3) {
- setobj2s(L->top, f); /* push function */
- setobj2s(L->top+1, p1); /* 1st argument */
- setobj2s(L->top+2, p2); /* 2nd argument */
- setobj2s(L->top+3, p3); /* 3th argument */
- luaD_checkstack(L, 4); /* cannot check before (could invalidate p1...p3) */
+static void callTM (lua_State *L) {
+ luaD_checkstack(L, 4);
L->top += 4;
luaD_call(L, L->top - 4, 0);
}
-static const TObject *luaV_index (lua_State *L, const TObject *t,
- TObject *key, int loop) {
- const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);
- if (tm == NULL) return &luaO_nilobject; /* no TM */
- if (ttisfunction(tm)) {
- callTMres(L, tm, t, key);
- return L->top;
- }
- else return luaV_gettable(L, tm, key, loop);
-}
-
-static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
- TObject *key, int loop) {
- const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX);
- if (ttisnil(tm))
- luaG_typeerror(L, t, "index");
- if (ttisfunction(tm)) {
- callTMres(L, tm, t, key);
- return L->top;
- }
- else return luaV_gettable(L, tm, key, loop);
-}
-
-
-/*
-** Function to index a table.
-** Receives the table at `t' and the key at `key'.
-** leaves the result at `res'.
-*/
-const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
- int loop) {
- if (loop > MAXTAGLOOP)
- luaG_runerror(L, "loop in gettable");
- if (ttistable(t)) { /* `t' is a table? */
- Table *h = hvalue(t);
- const TObject *v = luaH_get(h, key); /* do a primitive get */
- if (!ttisnil(v)) return v;
- else return luaV_index(L, t, key, loop+1);
+void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ 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 */
+ if (!ttisnil(res) || /* result is no nil? */
+ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
+ setobj2s(L, val, res);
+ return;
+ }
+ /* else will try the tag method */
+ }
+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
+ luaG_typeerror(L, t, "index");
+ if (ttisfunction(tm)) {
+ prepTMcall(L, tm, t, key);
+ callTMres(L, val);
+ return;
+ }
+ t = tm; /* else repeat with `tm' */
}
- else return luaV_getnotable(L, t, key, loop+1);
+ luaG_runerror(L, "loop in gettable");
}
-/*
-** Receives table at `t', key at `key' and value at `val'.
-*/
-void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
- const TObject *tm;
- int loop = 0;
- do {
+void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+ int loop;
+ for (loop = 0; loop < MAXTAGLOOP; loop++) {
+ const TValue *tm;
if (ttistable(t)) { /* `t' is a table? */
Table *h = hvalue(t);
- TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
+ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
if (!ttisnil(oldval) || /* result is no nil? */
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
- setobj2t(oldval, val); /* write barrier */
+ setobj2t(L, oldval, val);
+ luaC_barrier(L, h, val);
return;
}
/* else will try the tag method */
@@ -183,33 +159,33 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index");
if (ttisfunction(tm)) {
- callTM(L, tm, t, key, val);
+ prepTMcall(L, tm, t, key);
+ setobj2s(L, L->top+3, val); /* 3th argument */
+ callTM(L);
return;
}
t = tm; /* else repeat with `tm' */
- } while (++loop <= MAXTAGLOOP);
+ }
luaG_runerror(L, "loop in settable");
}
-static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
+static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
StkId res, TMS event) {
- ptrdiff_t result = savestack(L, res);
- const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
if (ttisnil(tm))
tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
if (!ttisfunction(tm)) return 0;
- callTMres(L, tm, p1, p2);
- res = restorestack(L, result); /* previous call may change stack */
- setobjs2s(res, L->top);
+ prepTMcall(L, tm, p1, p2);
+ callTMres(L, res);
return 1;
}
-static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,
+static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,
TMS event) {
- const TObject *tm1 = fasttm(L, mt1, event);
- const TObject *tm2;
+ const TValue *tm1 = fasttm(L, mt1, event);
+ const TValue *tm2;
if (tm1 == NULL) return NULL; /* no metamethod */
if (mt1 == mt2) return tm1; /* same metatables => same metamethods */
tm2 = fasttm(L, mt2, event);
@@ -220,15 +196,16 @@ static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,
}
-static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2,
+static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
TMS event) {
- const TObject *tm1 = luaT_gettmbyobj(L, p1, event);
- const TObject *tm2;
+ const TValue *tm1 = luaT_gettmbyobj(L, p1, event);
+ const TValue *tm2;
if (ttisnil(tm1)) return -1; /* no metamethod? */
tm2 = luaT_gettmbyobj(L, p2, event);
if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
return -1;
- callTMres(L, tm1, p1, p2);
+ prepTMcall(L, tm1, p1, p2);
+ callTMres(L, L->top);
return !l_isfalse(L->top);
}
@@ -255,28 +232,28 @@ static int luaV_strcmp (const TString *ls, const TString *rs) {
}
-int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
+int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int res;
if (ttype(l) != ttype(r))
return luaG_ordererror(L, l, r);
else if (ttisnumber(l))
return nvalue(l) < nvalue(r);
else if (ttisstring(l))
- return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
+ return luaV_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
return res;
return luaG_ordererror(L, l, r);
}
-static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
+static int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
int res;
if (ttype(l) != ttype(r))
return luaG_ordererror(L, l, r);
else if (ttisnumber(l))
return nvalue(l) <= nvalue(r);
else if (ttisstring(l))
- return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
+ return luaV_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
return res;
else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
@@ -285,8 +262,8 @@ static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
}
-int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
- const TObject *tm;
+int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
+ const TValue *tm;
lua_assert(ttype(t1) == ttype(t2));
switch (ttype(t1)) {
case LUA_TNIL: return 1;
@@ -295,7 +272,7 @@ int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
case LUA_TUSERDATA: {
if (uvalue(t1) == uvalue(t2)) return 1;
- tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable,
+ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
TM_EQ);
break; /* will try TM */
}
@@ -307,7 +284,8 @@ int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
default: return gcvalue(t1) == gcvalue(t2);
}
if (tm == NULL) return 0; /* no TM? */
- callTMres(L, tm, t1, t2); /* call TM */
+ prepTMcall(L, tm, t1, t2);
+ callTMres(L, L->top); /* call TM */
return !l_isfalse(L->top);
}
@@ -319,25 +297,25 @@ void luaV_concat (lua_State *L, int total, int last) {
if (!tostring(L, top-2) || !tostring(L, top-1)) {
if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
luaG_concaterror(L, top-2, top-1);
- } else if (tsvalue(top-1)->tsv.len > 0) { /* if len=0, do nothing */
+ } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */
/* at least two string values; get as many as possible */
- lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) +
- cast(lu_mem, tsvalue(top-2)->tsv.len);
+ lu_mem tl = cast(lu_mem, tsvalue(top-1)->len) +
+ cast(lu_mem, tsvalue(top-2)->len);
char *buffer;
int i;
while (n < total && tostring(L, top-n-1)) { /* collect total length */
- tl += tsvalue(top-n-1)->tsv.len;
+ tl += tsvalue(top-n-1)->len;
n++;
}
if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0;
for (i=n; i>0; i--) { /* concat all strings */
- size_t l = tsvalue(top-i)->tsv.len;
+ size_t l = tsvalue(top-i)->len;
memcpy(buffer+tl, svalue(top-i), l);
tl += l;
}
- setsvalue2s(top-n, luaS_newlstr(L, buffer, tl));
+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
}
total -= n-1; /* got `n' strings to create 1 new */
last -= n-1;
@@ -345,10 +323,11 @@ void luaV_concat (lua_State *L, int total, int last) {
}
-static void Arith (lua_State *L, StkId ra,
- const TObject *rb, const TObject *rc, TMS op) {
- TObject tempb, tempc;
- const TObject *b, *c;
+static StkId Arith (lua_State *L, StkId ra, const TValue *rb,
+ const TValue *rc, TMS op, const Instruction *pc) {
+ TValue tempb, tempc;
+ const TValue *b, *c;
+ L->ci->u.l.savedpc = pc;
if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
(c = luaV_tonumber(rc, &tempc)) != NULL) {
switch (op) {
@@ -357,13 +336,11 @@ static void Arith (lua_State *L, StkId ra,
case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break;
case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break;
case TM_POW: {
- const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]);
- ptrdiff_t res = savestack(L, ra);
+ 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");
- callTMres(L, f, b, c);
- ra = restorestack(L, res); /* previous call may change stack */
- setobjs2s(ra, L->top);
+ prepTMcall(L, f, b, c);
+ callTMres(L, ra);
break;
}
default: lua_assert(0); break;
@@ -371,6 +348,7 @@ static void Arith (lua_State *L, StkId ra,
}
else if (!call_binTM(L, rb, rc, ra, op))
luaG_aritherror(L, rb, rc);
+ return L->base;
}
@@ -383,63 +361,58 @@ static void Arith (lua_State *L, StkId ra,
#define RA(i) (base+GETARG_A(i))
/* to be used after possible stack reallocation */
-#define XRA(i) (L->base+GETARG_A(i))
-#define RB(i) (base+GETARG_B(i))
-#define RKB(i) ((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK)
-#define RC(i) (base+GETARG_C(i))
-#define RKC(i) ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)
-#define KBx(i) (k+GETARG_Bx(i))
+#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
+#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
+#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
+ (GETARG_B(i) < MAXSTACK) ? base+GETARG_B(i) : k+GETARG_B(i)-MAXSTACK)
+#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
+ (GETARG_C(i) < MAXSTACK) ? base+GETARG_C(i) : k+GETARG_C(i)-MAXSTACK)
+#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))
#define dojump(pc, i) ((pc) += (i))
-StkId luaV_execute (lua_State *L) {
+StkId luaV_execute (lua_State *L, int nexeccalls) {
LClosure *cl;
- TObject *k;
+ TValue *k;
+ StkId base;
const Instruction *pc;
callentry: /* entry point when calling new functions */
- if (L->hookmask & LUA_MASKCALL) {
- L->ci->u.l.pc = &pc;
+ if (L->hookmask & LUA_MASKCALL)
luaD_callhook(L, LUA_HOOKCALL, -1);
- }
retentry: /* entry point when returning to old functions */
- L->ci->u.l.pc = &pc;
- lua_assert(L->ci->state == CI_SAVEDPC ||
- L->ci->state == (CI_SAVEDPC | CI_CALLING));
- L->ci->state = CI_HASFRAME; /* activate frame */
pc = L->ci->u.l.savedpc;
- cl = &clvalue(L->base - 1)->l;
+ base = L->base;
+ cl = &clvalue(base - 1)->l;
k = cl->p->k;
/* main loop of interpreter */
for (;;) {
const Instruction i = *pc++;
- StkId base, ra;
+ StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
- traceexec(L);
- if (L->ci->state & CI_YIELD) { /* did hook yield? */
+ traceexec(L, pc); /***/
+ if (L->isSuspended) { /* did hook yield? */
L->ci->u.l.savedpc = pc - 1;
- L->ci->state = CI_YIELD | CI_SAVEDPC;
return NULL;
}
+ base = L->base;
}
/* warning!! several calls may realloc the stack and invalidate `ra' */
- base = L->base;
ra = RA(i);
- lua_assert(L->ci->state & CI_HASFRAME);
- lua_assert(base == L->ci->base);
+ lua_assert(base == L->ci->base && base == L->base);
lua_assert(L->top <= L->stack + L->stacksize && L->top >= base);
lua_assert(L->top == L->ci->top ||
GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
switch (GET_OPCODE(i)) {
case OP_MOVE: {
- setobjs2s(ra, RB(i));
+ setobjs2s(L, ra, RB(i));
break;
}
case OP_LOADK: {
- setobj2s(ra, KBx(i));
+ setobj2s(L, ra, KBx(i));
break;
}
case OP_LOADBOOL: {
@@ -448,7 +421,7 @@ StkId luaV_execute (lua_State *L) {
break;
}
case OP_LOADNIL: {
- TObject *rb = RB(i);
+ TValue *rb = RB(i);
do {
setnilvalue(rb--);
} while (rb >= ra);
@@ -456,122 +429,115 @@ StkId luaV_execute (lua_State *L) {
}
case OP_GETUPVAL: {
int b = GETARG_B(i);
- setobj2s(ra, cl->upvals[b]->v);
+ setobj2s(L, ra, cl->upvals[b]->v);
break;
}
case OP_GETGLOBAL: {
- TObject *rb = KBx(i);
- const TObject *v;
+ TValue *rb = KBx(i);
lua_assert(ttisstring(rb) && ttistable(&cl->g));
- v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
- if (!ttisnil(v)) { setobj2s(ra, v); }
- else
- setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0));
+ L->ci->u.l.savedpc = pc;
+ luaV_gettable(L, &cl->g, rb, ra); /***/
+ base = L->base;
break;
}
case OP_GETTABLE: {
- StkId rb = RB(i);
- TObject *rc = RKC(i);
- if (ttistable(rb)) {
- const TObject *v = luaH_get(hvalue(rb), rc);
- if (!ttisnil(v)) { setobj2s(ra, v); }
- else
- setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
- }
- else
- setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
+ L->ci->u.l.savedpc = pc;
+ luaV_gettable(L, RB(i), RKC(i), ra); /***/
+ base = L->base;
break;
}
case OP_SETGLOBAL: {
lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
- luaV_settable(L, &cl->g, KBx(i), ra);
+ L->ci->u.l.savedpc = pc;
+ luaV_settable(L, &cl->g, KBx(i), ra); /***/
+ base = L->base;
break;
}
case OP_SETUPVAL: {
- int b = GETARG_B(i);
- setobj(cl->upvals[b]->v, ra); /* write barrier */
+ UpVal *uv = cl->upvals[GETARG_B(i)];
+ setobj(L, uv->v, ra);
+ luaC_barrier(L, uv, ra);
break;
}
case OP_SETTABLE: {
- luaV_settable(L, ra, RKB(i), RKC(i));
+ L->ci->u.l.savedpc = pc;
+ luaV_settable(L, ra, RKB(i), RKC(i)); /***/
+ base = L->base;
break;
}
case OP_NEWTABLE: {
int b = GETARG_B(i);
b = fb2int(b);
- sethvalue(ra, luaH_new(L, b, GETARG_C(i)));
- luaC_checkGC(L);
+ sethvalue(L, ra, luaH_new(L, b, GETARG_C(i)));
+ L->ci->u.l.savedpc = pc;
+ luaC_checkGC(L); /***/
+ base = L->base;
break;
}
case OP_SELF: {
StkId rb = RB(i);
- TObject *rc = RKC(i);
- runtime_check(L, ttisstring(rc));
- setobjs2s(ra+1, rb);
- if (ttistable(rb)) {
- const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
- if (!ttisnil(v)) { setobj2s(ra, v); }
- else
- setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
- }
- else
- setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
+ setobjs2s(L, ra+1, rb);
+ L->ci->u.l.savedpc = pc;
+ luaV_gettable(L, rb, RKC(i), ra); /***/
+ base = L->base;
break;
}
case OP_ADD: {
- TObject *rb = RKB(i);
- TObject *rc = RKC(i);
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, nvalue(rb) + nvalue(rc));
}
else
- Arith(L, ra, rb, rc, TM_ADD);
+ base = Arith(L, ra, rb, rc, TM_ADD, pc); /***/
break;
}
case OP_SUB: {
- TObject *rb = RKB(i);
- TObject *rc = RKC(i);
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, nvalue(rb) - nvalue(rc));
}
else
- Arith(L, ra, rb, rc, TM_SUB);
+ base = Arith(L, ra, rb, rc, TM_SUB, pc); /***/
break;
}
case OP_MUL: {
- TObject *rb = RKB(i);
- TObject *rc = RKC(i);
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, nvalue(rb) * nvalue(rc));
}
else
- Arith(L, ra, rb, rc, TM_MUL);
+ base = Arith(L, ra, rb, rc, TM_MUL, pc); /***/
break;
}
case OP_DIV: {
- TObject *rb = RKB(i);
- TObject *rc = RKC(i);
+ TValue *rb = RKB(i);
+ TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
setnvalue(ra, nvalue(rb) / nvalue(rc));
}
else
- Arith(L, ra, rb, rc, TM_DIV);
+ base = Arith(L, ra, rb, rc, TM_DIV, pc); /***/
break;
}
case OP_POW: {
- Arith(L, ra, RKB(i), RKC(i), TM_POW);
+ base = Arith(L, ra, RKB(i), RKC(i), TM_POW, pc); /***/
break;
}
case OP_UNM: {
- const TObject *rb = RB(i);
- TObject temp;
+ const TValue *rb = RB(i);
+ TValue temp;
if (tonumber(rb, &temp)) {
setnvalue(ra, -nvalue(rb));
}
else {
setnilvalue(&temp);
- if (!call_binTM(L, RB(i), &temp, ra, TM_UNM))
+ L->ci->u.l.savedpc = pc;
+ if (!call_binTM(L, RB(i), &temp, ra, TM_UNM)) /***/
luaG_aritherror(L, RB(i), &temp);
+ base = L->base;
}
break;
}
@@ -583,10 +549,11 @@ StkId luaV_execute (lua_State *L) {
case OP_CONCAT: {
int b = GETARG_B(i);
int c = GETARG_C(i);
- luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */
+ L->ci->u.l.savedpc = pc;
+ luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */ /***/
+ luaC_checkGC(L); /***/
base = L->base;
- setobjs2s(RA(i), base+b);
- luaC_checkGC(L);
+ setobjs2s(L, RA(i), base+b);
break;
}
case OP_JMP: {
@@ -594,42 +561,46 @@ StkId luaV_execute (lua_State *L) {
break;
}
case OP_EQ: {
- if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
+ L->ci->u.l.savedpc = pc;
+ if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
else dojump(pc, GETARG_sBx(*pc) + 1);
+ base = L->base;
break;
}
case OP_LT: {
- if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
+ L->ci->u.l.savedpc = pc;
+ if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
else dojump(pc, GETARG_sBx(*pc) + 1);
+ base = L->base;
break;
}
case OP_LE: {
- if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
+ L->ci->u.l.savedpc = pc;
+ if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++; /***/
else dojump(pc, GETARG_sBx(*pc) + 1);
+ base = L->base;
break;
}
case OP_TEST: {
- TObject *rb = RB(i);
+ TValue *rb = RB(i);
if (l_isfalse(rb) == GETARG_C(i)) pc++;
else {
- setobjs2s(ra, rb);
+ setobjs2s(L, ra, rb);
dojump(pc, GETARG_sBx(*pc) + 1);
}
break;
}
case OP_CALL:
- case OP_TAILCALL: {
+ case OP_TAILCALL: { /***/
StkId firstResult;
int b = GETARG_B(i);
- int nresults;
if (b != 0) L->top = ra+b; /* else previous instruction set top */
- nresults = GETARG_C(i) - 1;
+ L->ci->u.l.savedpc = pc;
firstResult = luaD_precall(L, ra);
if (firstResult) {
+ int nresults = GETARG_C(i) - 1;
if (firstResult > L->top) { /* yield? */
- lua_assert(L->ci->state == (CI_C | CI_YIELD));
(L->ci - 1)->u.l.savedpc = pc;
- (L->ci - 1)->state = CI_SAVEDPC;
return NULL;
}
/* it was a C function (`precall' called it); adjust results */
@@ -637,45 +608,37 @@ StkId luaV_execute (lua_State *L) {
if (nresults >= 0) L->top = L->ci->top;
}
else { /* it is a Lua function */
- if (GET_OPCODE(i) == OP_CALL) { /* regular call? */
- (L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */
- (L->ci-1)->state = (CI_SAVEDPC | CI_CALLING);
- }
+ if (GET_OPCODE(i) == OP_CALL) /* regular call? */
+ nexeccalls++;
else { /* tail call: put new frame in place of previous one */
int aux;
base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */
ra = RA(i);
if (L->openupval) luaF_close(L, base);
for (aux = 0; ra+aux < L->top; aux++) /* move frame down */
- setobjs2s(base+aux-1, ra+aux);
+ setobjs2s(L, base+aux-1, ra+aux);
(L->ci - 1)->top = L->top = base+aux; /* correct top */
- lua_assert(L->ci->state & CI_SAVEDPC);
(L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
(L->ci - 1)->u.l.tailcalls++; /* one more call lost */
- (L->ci - 1)->state = CI_SAVEDPC;
L->ci--; /* remove new frame */
L->base = L->ci->base;
}
goto callentry;
}
+ base = L->base;
break;
}
case OP_RETURN: {
CallInfo *ci = L->ci - 1; /* previous function frame */
int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
- lua_assert(L->ci->state & CI_HASFRAME);
if (L->openupval) luaF_close(L, base);
- L->ci->state = CI_SAVEDPC; /* deactivate current function */
L->ci->u.l.savedpc = pc;
- /* previous function was running `here'? */
- if (!(ci->state & CI_CALLING)) {
- lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc);
+ if (--nexeccalls == 0) /* was previous function running `here'? */
return ra; /* no: return */
- }
else { /* yes: continue its execution */
int nresults;
- lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC));
+ lua_assert(isLua(ci));
lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
luaD_poscall(L, nresults, ra);
@@ -684,49 +647,54 @@ StkId luaV_execute (lua_State *L) {
}
}
case OP_FORLOOP: {
- lua_Number step, idx, limit;
- const TObject *plimit = ra+1;
- const TObject *pstep = ra+2;
- if (!ttisnumber(ra))
- luaG_runerror(L, "`for' initial value must be a number");
- if (!tonumber(plimit, ra+1))
- luaG_runerror(L, "`for' limit must be a number");
- if (!tonumber(pstep, ra+2))
- luaG_runerror(L, "`for' step must be a number");
- step = nvalue(pstep);
- idx = nvalue(ra) + step; /* increment index */
- limit = nvalue(plimit);
+ lua_Number step = nvalue(ra+2);
+ lua_Number idx = nvalue(ra) + step; /* increment index */
+ lua_Number limit = nvalue(ra+1);
if (step > 0 ? idx <= limit : idx >= limit) {
dojump(pc, GETARG_sBx(i)); /* jump back */
- chgnvalue(ra, idx); /* update index */
+ setnvalue(ra, idx); /* update internal index... */
+ setnvalue(ra+3, idx); /* ...and external index */
}
break;
}
+ case OP_FORPREP: { /***/
+ const TValue *init = ra;
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+ L->ci->u.l.savedpc = pc;
+ if (!tonumber(init, ra))
+ luaG_runerror(L, "`for' initial value must be a number");
+ else if (!tonumber(plimit, ra+1))
+ 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));
+ dojump(pc, GETARG_sBx(i));
+ break;
+ }
case OP_TFORLOOP: {
- int nvar = GETARG_C(i) + 1;
- StkId cb = ra + nvar + 2; /* call base */
- setobjs2s(cb, ra);
- setobjs2s(cb+1, ra+1);
- setobjs2s(cb+2, ra+2);
+ StkId cb = ra + 3; /* call base */
+ setobjs2s(L, cb+2, ra+2);
+ setobjs2s(L, cb+1, ra+1);
+ setobjs2s(L, cb, ra);
L->top = cb+3; /* func. + 2 args (state and index) */
- luaD_call(L, cb, nvar);
+ L->ci->u.l.savedpc = pc;
+ luaD_call(L, cb, GETARG_C(i)); /***/
L->top = L->ci->top;
- ra = XRA(i) + 2; /* final position of first result */
- cb = ra + nvar;
- do { /* move results to proper positions */
- nvar--;
- setobjs2s(ra+nvar, cb+nvar);
- } while (nvar > 0);
- if (ttisnil(ra)) /* break loop? */
+ base = L->base;
+ cb = RA(i) + 3; /* previous call may change the stack */
+ if (ttisnil(cb)) /* break loop? */
pc++; /* skip jump (break loop) */
- else
+ else {
+ setobjs2s(L, cb-1, cb); /* save control variable */
dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */
+ }
break;
}
case OP_TFORPREP: { /* for compatibility only */
if (ttistable(ra)) {
- setobjs2s(ra+1, ra);
- setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
+ setobjs2s(L, ra+1, ra);
+ setobj2s(L, ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
}
dojump(pc, GETARG_sBx(i));
break;
@@ -746,8 +714,11 @@ StkId luaV_execute (lua_State *L) {
L->top = L->ci->top;
}
bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */
- for (; n > 0; n--)
- setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */
+ for (; n > 0; n--) {
+ TValue *val = ra+n;
+ setobj2t(L, luaH_setnum(L, h, bc+n), val);
+ luaC_barrier(L, h, val);
+ }
break;
}
case OP_CLOSE: {
@@ -770,12 +741,13 @@ StkId luaV_execute (lua_State *L) {
ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
}
}
- setclvalue(ra, ncl);
- luaC_checkGC(L);
+ setclvalue(L, ra, ncl);
+ L->ci->u.l.savedpc = pc;
+ luaC_checkGC(L); /***/
+ base = L->base;
break;
}
}
}
}
-
diff --git a/src/lvm.h b/src/lvm.h
index 19cce200..64bba128 100644
--- a/src/lvm.h
+++ b/src/lvm.h
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.h,v 1.47 2002/11/14 16:16:21 roberto Exp $
+** $Id: lvm.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -22,14 +22,13 @@
(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
-int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
-int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2);
-const TObject *luaV_tonumber (const TObject *obj, TObject *n);
+int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);
+const TValue *luaV_tonumber (const TValue *obj, TValue *n);
int luaV_tostring (lua_State *L, StkId obj);
-const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
- int loop);
-void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val);
-StkId luaV_execute (lua_State *L);
+void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val);
+void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val);
+StkId luaV_execute (lua_State *L, int nexeccalls);
void luaV_concat (lua_State *L, int total, int last);
#endif
diff --git a/src/lzio.c b/src/lzio.c
index 3aeca1c5..f538ea75 100644
--- a/src/lzio.c
+++ b/src/lzio.c
@@ -1,5 +1,5 @@
/*
-** $Id: lzio.c,v 1.24 2003/03/20 16:00:56 roberto Exp $
+** $Id: lzio.c,v 1.28 2003/11/18 10:44:53 roberto Exp $
** a generic input stream interface
** See Copyright Notice in lua.h
*/
@@ -13,12 +13,17 @@
#include "llimits.h"
#include "lmem.h"
+#include "lstate.h"
#include "lzio.h"
int luaZ_fill (ZIO *z) {
size_t size;
- const char *buff = z->reader(NULL, z->data, &size);
+ lua_State *L = z->L;
+ const char *buff;
+ lua_unlock(L);
+ buff = z->reader(L, z->data, &size);
+ lua_lock(L);
if (buff == NULL || size == 0) return EOZ;
z->n = size - 1;
z->p = buff;
@@ -37,10 +42,10 @@ int luaZ_lookahead (ZIO *z) {
}
-void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name) {
+void luaZ_init (lua_State *L, ZIO *z, lua_Chunkreader reader, void *data) {
+ z->L = L;
z->reader = reader;
z->data = data;
- z->name = name;
z->n = 0;
z->p = NULL;
}
@@ -72,8 +77,7 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
if (n > buff->buffsize) {
if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
- luaM_reallocvector(L, buff->buffer, buff->buffsize, n, char);
- buff->buffsize = n;
+ luaZ_resizebuffer(L, buff, n);
}
return buff->buffer;
}
diff --git a/src/lzio.h b/src/lzio.h
index 5e73615c..4b64256e 100644
--- a/src/lzio.h
+++ b/src/lzio.h
@@ -1,5 +1,5 @@
/*
-** $Id: lzio.h,v 1.15 2003/03/20 16:00:56 roberto Exp $
+** $Id: lzio.h,v 1.19 2003/10/03 16:05:34 roberto Exp $
** Buffered streams
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,8 @@
#include "lua.h"
+#include "lmem.h"
+
#define EOZ (-1) /* end of stream */
@@ -20,9 +22,7 @@ typedef struct Zio ZIO;
#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z))
-#define zname(z) ((z)->name)
-
-void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name);
+void luaZ_init (lua_State *L, ZIO *z, lua_Chunkreader reader, void *data);
size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
int luaZ_lookahead (ZIO *z);
@@ -30,6 +30,7 @@ int luaZ_lookahead (ZIO *z);
typedef struct Mbuffer {
char *buffer;
+ size_t n;
size_t buffsize;
} Mbuffer;
@@ -38,8 +39,12 @@ char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
-#define luaZ_sizebuffer(buff) ((buff)->buffsize)
#define luaZ_buffer(buff) ((buff)->buffer)
+#define luaZ_sizebuffer(buff) ((buff)->buffsize)
+#define luaZ_bufflen(buff) ((buff)->n)
+
+#define luaZ_resetbuffer(buff) ((buff)->n = 0)
+
#define luaZ_resizebuffer(L, buff, size) \
(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
@@ -48,6 +53,7 @@ char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
+
/* --------- Private Part ------------------ */
struct Zio {
@@ -55,7 +61,7 @@ struct Zio {
const char *p; /* current position in buffer */
lua_Chunkreader reader;
void* data; /* additional data */
- const char *name;
+ lua_State *L; /* Lua state (for reader) */
};