mirror of
https://github.com/lua/lua.git
synced 2026-07-26 07:59:06 +00:00
Compare commits
128 Commits
v5.0-alpha
...
v5.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28021c5c66 | ||
|
|
73517e86b0 | ||
|
|
9e8face8d8 | ||
|
|
64864f094b | ||
|
|
9bd3fc1039 | ||
|
|
cc4a22ebe2 | ||
|
|
acf62ddfbe | ||
|
|
04f95ce879 | ||
|
|
27c6b4d422 | ||
|
|
0bb8eb5151 | ||
|
|
38da8c0d7d | ||
|
|
76de732745 | ||
|
|
90d7892007 | ||
|
|
041cb96992 | ||
|
|
c75c3cfd19 | ||
|
|
24471525d7 | ||
|
|
1f55dbc699 | ||
|
|
c194a46bc5 | ||
|
|
8954bdc706 | ||
|
|
5a228bb1d8 | ||
|
|
5f698f8b6f | ||
|
|
9b1c586b2f | ||
|
|
d9340154ac | ||
|
|
e47baca75a | ||
|
|
b8a680c114 | ||
|
|
709b27b456 | ||
|
|
dbc5451bea | ||
|
|
2d2d45976c | ||
|
|
0050d983fc | ||
|
|
04b143ddf9 | ||
|
|
007f229568 | ||
|
|
84488c5670 | ||
|
|
5142e630bf | ||
|
|
010bbd9d9c | ||
|
|
be00cd2a6b | ||
|
|
2e4e888de0 | ||
|
|
ddc144e4d2 | ||
|
|
b48c6e7680 | ||
|
|
aff97fffc4 | ||
|
|
1648674653 | ||
|
|
d404f0c276 | ||
|
|
48e42261ac | ||
|
|
be762f38bd | ||
|
|
c8a79057f7 | ||
|
|
642af82e81 | ||
|
|
636c629e56 | ||
|
|
96ba5d0bc2 | ||
|
|
f0185f7628 | ||
|
|
9bab2cf55d | ||
|
|
c4ae00a3d1 | ||
|
|
f4d3bc52f4 | ||
|
|
18765d900e | ||
|
|
43013b39cc | ||
|
|
94912d99fc | ||
|
|
b40c9f7a3c | ||
|
|
41fd639cab | ||
|
|
a845a46cc8 | ||
|
|
097edd3884 | ||
|
|
5c5d9b2703 | ||
|
|
43d1a6af12 | ||
|
|
3010eb0536 | ||
|
|
2f91f95d94 | ||
|
|
42dd080a2e | ||
|
|
9957f7d598 | ||
|
|
ac27b7a842 | ||
|
|
81e142fc14 | ||
|
|
63633c5b5f | ||
|
|
dff9be4224 | ||
|
|
118347d8c3 | ||
|
|
6820da5096 | ||
|
|
c3eb4675b9 | ||
|
|
7e0f880bc5 | ||
|
|
118e9cd843 | ||
|
|
de00d0d0ad | ||
|
|
1713b64065 | ||
|
|
671dc6eec2 | ||
|
|
e356a43dc0 | ||
|
|
f36038e42a | ||
|
|
96e15b8501 | ||
|
|
0fd91b1b08 | ||
|
|
a2b353e044 | ||
|
|
92a2ef9dca | ||
|
|
4fb9110a6e | ||
|
|
11886dc7b0 | ||
|
|
81bc5711a8 | ||
|
|
6a77a6b73f | ||
|
|
84e0b1bc97 | ||
|
|
6823a2f57f | ||
|
|
313b2fe902 | ||
|
|
425e5813b0 | ||
|
|
6505503b49 | ||
|
|
ec748fcb0a | ||
|
|
c196348717 | ||
|
|
669129a6d8 | ||
|
|
46b063ef59 | ||
|
|
e1d5153a33 | ||
|
|
b3d0682fb9 | ||
|
|
02afc892d5 | ||
|
|
fa2f1ec7ba | ||
|
|
829befcc41 | ||
|
|
d477e4ffd6 | ||
|
|
ce09af1e25 | ||
|
|
98d0b79613 | ||
|
|
e8f35fc4ff | ||
|
|
6fb0fd5063 | ||
|
|
565e6d74e1 | ||
|
|
f6bc7884be | ||
|
|
32a5d96dfc | ||
|
|
8dae071f42 | ||
|
|
afe1305b1a | ||
|
|
728fa167d2 | ||
|
|
1bdde38bd2 | ||
|
|
b2bc3b44b6 | ||
|
|
7c0ccdfd61 | ||
|
|
4964e7c8a0 | ||
|
|
2c670baf24 | ||
|
|
fdafd4f4a8 | ||
|
|
beeff4ccaf | ||
|
|
12c4e48506 | ||
|
|
c78aaa9a70 | ||
|
|
4d7a554921 | ||
|
|
fbc23d0245 | ||
|
|
81a8845e4f | ||
|
|
6c283b2f4f | ||
|
|
576bded513 | ||
|
|
ecc7769de2 | ||
|
|
da19c436cc | ||
|
|
0039feb9da |
17
bugs
17
bugs
@@ -286,3 +286,20 @@ Wed Jun 19 13:31:49 EST 2002
|
||||
>> (in function `parse_file')
|
||||
(by Alex Bilyk; since 4.0)
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
--- Version 5.0 alpha
|
||||
|
||||
** lgc.c
|
||||
Fri Aug 30 13:49:14 EST 2002
|
||||
>> GC metamethod stored in a weak metatable being collected together with
|
||||
>> userdata may not be cleared properly
|
||||
(by Roberto; since 5.0a)
|
||||
|
||||
** lparser.c
|
||||
Fri Dec 6 17:06:40 UTC 2002
|
||||
>> scope of generic for variables is not sound
|
||||
(by Gavin Wraith; since 5.0a)
|
||||
|
||||
|
||||
243
lapi.c
243
lapi.c
@@ -1,12 +1,15 @@
|
||||
/*
|
||||
** $Id: lapi.c,v 1.210 2002/08/07 14:24:24 roberto Exp roberto $
|
||||
** $Id: lapi.c,v 1.225 2002/12/04 17:28:27 roberto Exp roberto $
|
||||
** Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define lapi_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lapi.h"
|
||||
@@ -32,26 +35,26 @@ const char lua_ident[] =
|
||||
|
||||
|
||||
#ifndef api_check
|
||||
#define api_check(L, o) ((void)1)
|
||||
#define api_check(L, o) /*{ assert(o); }*/
|
||||
#endif
|
||||
|
||||
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->ci->base))
|
||||
#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_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
|
||||
|
||||
|
||||
|
||||
|
||||
static TObject *negindex (lua_State *L, int index) {
|
||||
if (index > LUA_REGISTRYINDEX) {
|
||||
api_check(L, index != 0 && -index <= L->top - L->ci->base);
|
||||
api_check(L, index != 0 && -index <= L->top - L->base);
|
||||
return L->top+index;
|
||||
}
|
||||
else switch (index) { /* pseudo-indices */
|
||||
case LUA_REGISTRYINDEX: return registry(L);
|
||||
case LUA_GLOBALSINDEX: return gt(L);
|
||||
default: {
|
||||
TObject *func = (L->ci->base - 1);
|
||||
TObject *func = (L->base - 1);
|
||||
index = LUA_GLOBALSINDEX - index;
|
||||
api_check(L, iscfunction(func) && index <= clvalue(func)->c.nupvalues);
|
||||
return &clvalue(func)->c.upvalue[index-1];
|
||||
@@ -60,16 +63,20 @@ static TObject *negindex (lua_State *L, int index) {
|
||||
}
|
||||
|
||||
|
||||
#define luaA_index(L, index) \
|
||||
( (index > 0) ? \
|
||||
(api_check(L, index <= L->top - L->ci->base), L->ci->base+index-1) : \
|
||||
negindex(L, index))
|
||||
static TObject *luaA_index (lua_State *L, int index) {
|
||||
if (index > 0) {
|
||||
api_check(L, index <= L->top - L->base);
|
||||
return L->base + index - 1;
|
||||
}
|
||||
else
|
||||
return negindex(L, index);
|
||||
}
|
||||
|
||||
|
||||
static TObject *luaA_indexAcceptable (lua_State *L, int index) {
|
||||
if (index > 0) {
|
||||
TObject *o = L->ci->base+(index-1);
|
||||
api_check(L, index <= L->stack_last - L->ci->base);
|
||||
TObject *o = L->base+(index-1);
|
||||
api_check(L, index <= L->stack_last - L->base);
|
||||
if (o >= L->top) return NULL;
|
||||
else return o;
|
||||
}
|
||||
@@ -79,7 +86,7 @@ static TObject *luaA_indexAcceptable (lua_State *L, int index) {
|
||||
|
||||
|
||||
void luaA_pushobject (lua_State *L, const TObject *o) {
|
||||
setobj(L->top, o);
|
||||
setobj2s(L->top, o);
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
@@ -87,7 +94,7 @@ void luaA_pushobject (lua_State *L, const TObject *o) {
|
||||
LUA_API int lua_checkstack (lua_State *L, int size) {
|
||||
int res;
|
||||
lua_lock(L);
|
||||
if ((L->top - L->ci->base + size) > LUA_MAXCSTACK)
|
||||
if ((L->top - L->base + size) > LUA_MAXCSTACK)
|
||||
res = 0; /* stack overflow */
|
||||
else {
|
||||
luaD_checkstack(L, size);
|
||||
@@ -100,6 +107,19 @@ 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;
|
||||
lua_lock(to);
|
||||
api_checknelems(from, n);
|
||||
from->top -= n;
|
||||
for (i = 0; i < n; i++) {
|
||||
setobj2s(to->top, from->top + i);
|
||||
api_incr_top(to);
|
||||
}
|
||||
lua_unlock(to);
|
||||
}
|
||||
|
||||
|
||||
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
|
||||
lua_CFunction old;
|
||||
lua_lock(L);
|
||||
@@ -110,26 +130,40 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API lua_State *lua_newthread (lua_State *L) {
|
||||
lua_State *L1;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
L1 = luaE_newthread(L);
|
||||
setthvalue(L->top, L1);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
lua_userstateopen(L1);
|
||||
return L1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** basic stack manipulation
|
||||
*/
|
||||
|
||||
|
||||
LUA_API int lua_gettop (lua_State *L) {
|
||||
return (L->top - L->ci->base);
|
||||
return (L->top - L->base);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_settop (lua_State *L, int index) {
|
||||
lua_lock(L);
|
||||
if (index >= 0) {
|
||||
api_check(L, index <= L->stack_last - L->ci->base);
|
||||
while (L->top < L->ci->base + index)
|
||||
api_check(L, index <= L->stack_last - L->base);
|
||||
while (L->top < L->base + index)
|
||||
setnilvalue(L->top++);
|
||||
L->top = L->ci->base + index;
|
||||
L->top = L->base + index;
|
||||
}
|
||||
else {
|
||||
api_check(L, -(index+1) <= (L->top - L->ci->base));
|
||||
api_check(L, -(index+1) <= (L->top - L->base));
|
||||
L->top += index+1; /* `subtract' index (index is negative) */
|
||||
}
|
||||
lua_unlock(L);
|
||||
@@ -140,7 +174,7 @@ LUA_API void lua_remove (lua_State *L, int index) {
|
||||
StkId p;
|
||||
lua_lock(L);
|
||||
p = luaA_index(L, index);
|
||||
while (++p < L->top) setobj(p-1, p);
|
||||
while (++p < L->top) setobjs2s(p-1, p);
|
||||
L->top--;
|
||||
lua_unlock(L);
|
||||
}
|
||||
@@ -151,8 +185,8 @@ LUA_API void lua_insert (lua_State *L, int index) {
|
||||
StkId q;
|
||||
lua_lock(L);
|
||||
p = luaA_index(L, index);
|
||||
for (q = L->top; q>p; q--) setobj(q, q-1);
|
||||
setobj(p, L->top);
|
||||
for (q = L->top; q>p; q--) setobjs2s(q, q-1);
|
||||
setobjs2s(p, L->top);
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
@@ -160,7 +194,7 @@ LUA_API void lua_insert (lua_State *L, int index) {
|
||||
LUA_API void lua_replace (lua_State *L, int index) {
|
||||
lua_lock(L);
|
||||
api_checknelems(L, 1);
|
||||
setobj(luaA_index(L, index), L->top - 1);
|
||||
setobj(luaA_index(L, index), L->top - 1); /* write barrier */
|
||||
L->top--;
|
||||
lua_unlock(L);
|
||||
}
|
||||
@@ -168,7 +202,7 @@ LUA_API void lua_replace (lua_State *L, int index) {
|
||||
|
||||
LUA_API void lua_pushvalue (lua_State *L, int index) {
|
||||
lua_lock(L);
|
||||
setobj(L->top, luaA_index(L, index));
|
||||
setobj2s(L->top, luaA_index(L, index));
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
@@ -211,6 +245,12 @@ LUA_API int lua_isstring (lua_State *L, int index) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_isuserdata (lua_State *L, int index) {
|
||||
const TObject *o = luaA_indexAcceptable(L, index);
|
||||
return (o != NULL && (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);
|
||||
@@ -272,6 +312,7 @@ LUA_API const char *lua_tostring (lua_State *L, int index) {
|
||||
const char *s;
|
||||
lua_lock(L); /* `luaV_tostring' may create a new string */
|
||||
s = (luaV_tostring(L, o) ? svalue(o) : NULL);
|
||||
luaC_checkGC(L);
|
||||
lua_unlock(L);
|
||||
return s;
|
||||
}
|
||||
@@ -311,6 +352,12 @@ LUA_API void *lua_touserdata (lua_State *L, int index) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API lua_State *lua_tothread (lua_State *L, int index) {
|
||||
StkId o = luaA_indexAcceptable(L, index);
|
||||
return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
|
||||
}
|
||||
|
||||
|
||||
LUA_API const void *lua_topointer (lua_State *L, int index) {
|
||||
StkId o = luaA_indexAcceptable(L, index);
|
||||
if (o == NULL) return NULL;
|
||||
@@ -351,7 +398,8 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
|
||||
|
||||
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
|
||||
lua_lock(L);
|
||||
setsvalue(L->top, luaS_newlstr(L, s, len));
|
||||
luaC_checkGC(L);
|
||||
setsvalue2s(L->top, luaS_newlstr(L, s, len));
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
@@ -369,6 +417,7 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
|
||||
va_list argp) {
|
||||
const char *ret;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
ret = luaO_pushvfstring(L, fmt, argp);
|
||||
lua_unlock(L);
|
||||
return ret;
|
||||
@@ -379,6 +428,7 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
|
||||
const char *ret;
|
||||
va_list argp;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
va_start(argp, fmt);
|
||||
ret = luaO_pushvfstring(L, fmt, argp);
|
||||
va_end(argp);
|
||||
@@ -390,12 +440,13 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
|
||||
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
|
||||
Closure *cl;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
api_checknelems(L, n);
|
||||
cl = luaF_newCclosure(L, n);
|
||||
cl->c.f = fn;
|
||||
L->top -= n;
|
||||
while (n--)
|
||||
setobj(&cl->c.upvalue[n], L->top+n);
|
||||
setobj2n(&cl->c.upvalue[n], L->top+n);
|
||||
setclvalue(L->top, cl);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
@@ -426,11 +477,9 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
|
||||
|
||||
LUA_API void lua_gettable (lua_State *L, int index) {
|
||||
StkId t;
|
||||
const TObject *v;
|
||||
lua_lock(L);
|
||||
t = luaA_index(L, index);
|
||||
v = luaV_gettable(L, t, L->top-1, 0);
|
||||
setobj(L->top - 1, v);
|
||||
setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0));
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
@@ -440,7 +489,7 @@ LUA_API void lua_rawget (lua_State *L, int index) {
|
||||
lua_lock(L);
|
||||
t = luaA_index(L, index);
|
||||
api_check(L, ttistable(t));
|
||||
setobj(L->top - 1, luaH_get(hvalue(t), L->top - 1));
|
||||
setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1));
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
@@ -450,7 +499,7 @@ LUA_API void lua_rawgeti (lua_State *L, int index, int n) {
|
||||
lua_lock(L);
|
||||
o = luaA_index(L, index);
|
||||
api_check(L, ttistable(o));
|
||||
setobj(L->top, luaH_getnum(hvalue(o), n));
|
||||
setobj2s(L->top, luaH_getnum(hvalue(o), n));
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
@@ -458,26 +507,13 @@ LUA_API void lua_rawgeti (lua_State *L, int index, int n) {
|
||||
|
||||
LUA_API void lua_newtable (lua_State *L) {
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
sethvalue(L->top, luaH_new(L, 0, 0));
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
||||
LUA_API const char *lua_getmode (lua_State *L, int index) {
|
||||
static const char *const modes[] = {"", "k", "v", "kv"};
|
||||
int mode = 0;
|
||||
TObject *t;
|
||||
lua_lock(L);
|
||||
t = luaA_index(L, index);
|
||||
api_check(L, ttistable(t));
|
||||
if (hvalue(t)->mode & WEAKKEY) mode += 1;
|
||||
if (hvalue(t)->mode & WEAKVALUE) mode += 2;
|
||||
lua_unlock(L);
|
||||
return modes[mode];
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_getmetatable (lua_State *L, int objindex) {
|
||||
StkId obj;
|
||||
Table *mt;
|
||||
@@ -510,7 +546,7 @@ LUA_API void lua_getglobals (lua_State *L, int index) {
|
||||
StkId o;
|
||||
lua_lock(L);
|
||||
o = luaA_index(L, index);
|
||||
setobj(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
|
||||
setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
@@ -538,7 +574,7 @@ LUA_API void lua_rawset (lua_State *L, int index) {
|
||||
api_checknelems(L, 2);
|
||||
t = luaA_index(L, index);
|
||||
api_check(L, ttistable(t));
|
||||
setobj(luaH_set(L, hvalue(t), L->top-2), L->top-1);
|
||||
setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */
|
||||
L->top -= 2;
|
||||
lua_unlock(L);
|
||||
}
|
||||
@@ -550,23 +586,12 @@ LUA_API void lua_rawseti (lua_State *L, int index, int n) {
|
||||
api_checknelems(L, 1);
|
||||
o = luaA_index(L, index);
|
||||
api_check(L, ttistable(o));
|
||||
setobj(luaH_setnum(L, hvalue(o), n), L->top-1);
|
||||
setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */
|
||||
L->top--;
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_setmode (lua_State *L, int index, const char *mode) {
|
||||
TObject *t;
|
||||
lua_lock(L);
|
||||
t = luaA_index(L, index);
|
||||
api_check(L, ttistable(t));
|
||||
hvalue(t)->mode &= ~(WEAKKEY | WEAKVALUE); /* clear bits */
|
||||
if (strchr(mode, 'k')) hvalue(t)->mode |= WEAKKEY;
|
||||
if (strchr(mode, 'v')) hvalue(t)->mode |= WEAKVALUE;
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
LUA_API int lua_setmetatable (lua_State *L, int objindex) {
|
||||
TObject *obj, *mt;
|
||||
int res = 1;
|
||||
@@ -577,11 +602,11 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
|
||||
api_check(L, ttistable(mt));
|
||||
switch (ttype(obj)) {
|
||||
case LUA_TTABLE: {
|
||||
hvalue(obj)->metatable = hvalue(mt);
|
||||
hvalue(obj)->metatable = hvalue(mt); /* write barrier */
|
||||
break;
|
||||
}
|
||||
case LUA_TUSERDATA: {
|
||||
uvalue(obj)->uv.metatable = hvalue(mt);
|
||||
uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -626,12 +651,66 @@ LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Execute a protected call.
|
||||
*/
|
||||
struct CallS { /* data to `f_call' */
|
||||
StkId func;
|
||||
int nresults;
|
||||
};
|
||||
|
||||
|
||||
static void f_call (lua_State *L, void *ud) {
|
||||
struct CallS *c = cast(struct CallS *, ud);
|
||||
luaD_call(L, c->func, c->nresults);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
|
||||
struct CallS c;
|
||||
int status;
|
||||
ptrdiff_t func;
|
||||
lua_lock(L);
|
||||
func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
|
||||
status = luaD_pcall(L, nargs, nresults, func);
|
||||
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);
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Execute a protected C call.
|
||||
*/
|
||||
struct CCallS { /* data to `f_Ccall' */
|
||||
lua_CFunction func;
|
||||
void *ud;
|
||||
};
|
||||
|
||||
|
||||
static void f_Ccall (lua_State *L, void *ud) {
|
||||
struct CCallS *c = cast(struct CCallS *, ud);
|
||||
Closure *cl;
|
||||
cl = luaF_newCclosure(L, 0);
|
||||
cl->c.f = c->func;
|
||||
setclvalue(L->top, cl); /* push function */
|
||||
incr_top(L);
|
||||
setpvalue(L->top, c->ud); /* push only argument */
|
||||
incr_top(L);
|
||||
luaD_call(L, L->top - 2, 0);
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
|
||||
struct CCallS c;
|
||||
int status;
|
||||
lua_lock(L);
|
||||
c.func = func;
|
||||
c.ud = ud;
|
||||
status = luaD_pcall(L, &f_Ccall, &c, savestack(L, L->top), 0);
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
@@ -652,12 +731,30 @@ 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;
|
||||
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;
|
||||
}
|
||||
else
|
||||
status = 0;
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Garbage-collection functions
|
||||
*/
|
||||
|
||||
/* GC values are expressed in Kbytes: #bytes/2^10 */
|
||||
#define GCscale(x) (cast(int, (x)>>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) {
|
||||
@@ -678,7 +775,7 @@ LUA_API int lua_getgccount (lua_State *L) {
|
||||
|
||||
LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
|
||||
lua_lock(L);
|
||||
if (newthreshold > GCscale(ULONG_MAX))
|
||||
if (cast(lu_mem, newthreshold) > GCscalel(ULONG_MAX))
|
||||
G(L)->GCthreshold = ULONG_MAX;
|
||||
else
|
||||
G(L)->GCthreshold = GCunscale(newthreshold);
|
||||
@@ -692,6 +789,11 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
|
||||
*/
|
||||
|
||||
|
||||
LUA_API const char *lua_version (void) {
|
||||
return LUA_VERSION;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_error (lua_State *L) {
|
||||
lua_lock(L);
|
||||
api_checknelems(L, 1);
|
||||
@@ -720,14 +822,14 @@ LUA_API int lua_next (lua_State *L, int index) {
|
||||
|
||||
LUA_API void lua_concat (lua_State *L, int n) {
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
api_checknelems(L, n);
|
||||
if (n >= 2) {
|
||||
luaV_concat(L, n, L->top - L->ci->base - 1);
|
||||
luaV_concat(L, n, L->top - L->base - 1);
|
||||
L->top -= (n-1);
|
||||
luaC_checkGC(L);
|
||||
}
|
||||
else if (n == 0) { /* push empty string */
|
||||
setsvalue(L->top, luaS_newlstr(L, NULL, 0));
|
||||
setsvalue2s(L->top, luaS_newlstr(L, NULL, 0));
|
||||
api_incr_top(L);
|
||||
}
|
||||
/* else n == 1; nothing to do */
|
||||
@@ -738,6 +840,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
|
||||
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);
|
||||
api_incr_top(L);
|
||||
@@ -750,12 +853,12 @@ LUA_API int lua_pushupvalues (lua_State *L) {
|
||||
Closure *func;
|
||||
int n, i;
|
||||
lua_lock(L);
|
||||
api_check(L, iscfunction(L->ci->base - 1));
|
||||
func = clvalue(L->ci->base - 1);
|
||||
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++) {
|
||||
setobj(L->top, &func->c.upvalue[i]);
|
||||
setobj2s(L->top, &func->c.upvalue[i]);
|
||||
L->top++;
|
||||
}
|
||||
lua_unlock(L);
|
||||
|
||||
144
lauxlib.c
144
lauxlib.c
@@ -1,25 +1,23 @@
|
||||
/*
|
||||
** $Id: lauxlib.c,v 1.82 2002/08/06 18:01:50 roberto Exp roberto $
|
||||
** $Id: lauxlib.c,v 1.90 2002/11/14 15:41:38 roberto Exp roberto $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef lua_filerror
|
||||
#include <errno.h>
|
||||
#define lua_fileerror (strerror(errno))
|
||||
#endif
|
||||
|
||||
|
||||
/* This file uses only the official API of Lua.
|
||||
** Any function declared here could be written as an application function.
|
||||
*/
|
||||
|
||||
#define lauxlib_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
@@ -81,8 +79,7 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
|
||||
luaL_where(L, 1);
|
||||
lua_pushvfstring(L, fmt, argp);
|
||||
va_end(argp);
|
||||
lua_pushliteral(L, "\n");
|
||||
lua_concat(L, 3);
|
||||
lua_concat(L, 2);
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
@@ -98,25 +95,25 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *mes) {
|
||||
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
|
||||
if (!lua_checkstack(L, space))
|
||||
luaL_error(L, "stack overflow (%s)", mes);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_check_type (lua_State *L, int narg, int t) {
|
||||
LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
|
||||
if (lua_type(L, narg) != t)
|
||||
tag_error(L, narg, t);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_check_any (lua_State *L, int narg) {
|
||||
LUALIB_API void luaL_checkany (lua_State *L, int narg) {
|
||||
if (lua_type(L, narg) == LUA_TNONE)
|
||||
luaL_argerror(L, narg, "value expected");
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) {
|
||||
LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
|
||||
const char *s = lua_tostring(L, narg);
|
||||
if (!s) tag_error(L, narg, LUA_TSTRING);
|
||||
if (len) *len = lua_strlen(L, narg);
|
||||
@@ -124,17 +121,18 @@ LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) {
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API const char *luaL_opt_lstr (lua_State *L, int narg, const char *def, size_t *len) {
|
||||
LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
|
||||
const char *def, size_t *len) {
|
||||
if (lua_isnoneornil(L, narg)) {
|
||||
if (len)
|
||||
*len = (def ? strlen(def) : 0);
|
||||
return def;
|
||||
}
|
||||
else return luaL_check_lstr(L, narg, len);
|
||||
else return luaL_checklstring(L, narg, len);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API lua_Number luaL_check_number (lua_State *L, int narg) {
|
||||
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
|
||||
lua_Number d = lua_tonumber(L, narg);
|
||||
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
|
||||
tag_error(L, narg, LUA_TNUMBER);
|
||||
@@ -142,13 +140,13 @@ LUALIB_API lua_Number luaL_check_number (lua_State *L, int narg) {
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API lua_Number luaL_opt_number (lua_State *L, int narg, lua_Number def) {
|
||||
LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
|
||||
if (lua_isnoneornil(L, narg)) return def;
|
||||
else return luaL_check_number(L, narg);
|
||||
else return luaL_checknumber(L, narg);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
|
||||
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);
|
||||
@@ -157,13 +155,30 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
|
||||
lua_pop(L, 2); /* remove metatable and metafield */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
|
||||
if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
|
||||
return 0;
|
||||
lua_pushvalue(L, obj);
|
||||
lua_call(L, 1, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_openlib (lua_State *L, const luaL_reg *l, int nup) {
|
||||
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 */
|
||||
if (lua_isnil(L, -1)) { /* no? */
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L); /* create it */
|
||||
}
|
||||
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
|
||||
}
|
||||
for (; l->name; l++) {
|
||||
int i;
|
||||
lua_pushstring(L, l->name);
|
||||
@@ -172,18 +187,12 @@ LUALIB_API void luaL_openlib (lua_State *L, const luaL_reg *l, int nup) {
|
||||
lua_pushcclosure(L, l->func, nup);
|
||||
lua_settable(L, -(nup+3));
|
||||
}
|
||||
lua_pop(L, nup);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname,
|
||||
const luaL_reg *l, int nup) {
|
||||
lua_pushstring(L, libname);
|
||||
lua_insert(L, -(nup+1));
|
||||
lua_newtable(L);
|
||||
lua_insert(L, -(nup+1));
|
||||
luaL_openlib(L, l, nup);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
lua_pop(L, nup); /* remove upvalues */
|
||||
if (libname) {
|
||||
lua_pushstring(L, libname);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -208,27 +217,27 @@ static int emptybuffer (luaL_Buffer *B) {
|
||||
else {
|
||||
lua_pushlstring(B->L, B->buffer, l);
|
||||
B->p = B->buffer;
|
||||
B->level++;
|
||||
B->lvl++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void adjuststack (luaL_Buffer *B) {
|
||||
if (B->level > 1) {
|
||||
if (B->lvl > 1) {
|
||||
lua_State *L = B->L;
|
||||
int toget = 1; /* number of levels to concat */
|
||||
size_t toplen = lua_strlen(L, -1);
|
||||
do {
|
||||
size_t l = lua_strlen(L, -(toget+1));
|
||||
if (B->level - toget + 1 >= LIMIT || toplen > l) {
|
||||
if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
|
||||
toplen += l;
|
||||
toget++;
|
||||
}
|
||||
else break;
|
||||
} while (toget < B->level);
|
||||
} while (toget < B->lvl);
|
||||
lua_concat(L, toget);
|
||||
B->level = B->level - toget + 1;
|
||||
B->lvl = B->lvl - toget + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,8 +262,8 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
|
||||
|
||||
LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
|
||||
emptybuffer(B);
|
||||
lua_concat(B->L, B->level);
|
||||
B->level = 1;
|
||||
lua_concat(B->L, B->lvl);
|
||||
B->lvl = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -269,7 +278,7 @@ LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
|
||||
else {
|
||||
if (emptybuffer(B))
|
||||
lua_insert(L, -2); /* put buffer before new value */
|
||||
B->level++; /* add new value into B stack */
|
||||
B->lvl++; /* add new value into B stack */
|
||||
adjuststack(B);
|
||||
}
|
||||
}
|
||||
@@ -278,7 +287,7 @@ LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
|
||||
LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
|
||||
B->L = L;
|
||||
B->p = B->buffer;
|
||||
B->level = 0;
|
||||
B->lvl = 0;
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
@@ -286,6 +295,10 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
|
||||
|
||||
LUALIB_API int luaL_ref (lua_State *L, int t) {
|
||||
int ref;
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1); /* remove from stack */
|
||||
return LUA_REFNIL; /* `nil' has a unique fixed reference */
|
||||
}
|
||||
lua_rawgeti(L, t, 0); /* get first free element */
|
||||
ref = (int)lua_tonumber(L, -1); /* ref = t[0] */
|
||||
lua_pop(L, 1); /* remove it from stack */
|
||||
@@ -339,38 +352,42 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
|
||||
}
|
||||
|
||||
|
||||
static int errfile (lua_State *L, const char *filename) {
|
||||
if (filename == NULL) filename = "stdin";
|
||||
lua_pushfstring(L, "cannot read %s: %s", filename, lua_fileerror);
|
||||
static int errfile (lua_State *L, int fnameindex) {
|
||||
const char *filename = lua_tostring(L, fnameindex) + 1;
|
||||
lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno));
|
||||
lua_remove(L, fnameindex);
|
||||
return LUA_ERRFILE;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
|
||||
LoadF lf;
|
||||
int status;
|
||||
int status, readstatus;
|
||||
int c;
|
||||
int old_top = lua_gettop(L);
|
||||
lf.f = (filename == NULL) ? stdin : fopen(filename, "r");
|
||||
if (lf.f == NULL) return errfile(L, filename); /* unable to open file */
|
||||
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
|
||||
if (filename == NULL) {
|
||||
lua_pushliteral(L, "=stdin");
|
||||
lf.f = stdin;
|
||||
}
|
||||
else {
|
||||
lua_pushfstring(L, "@%s", filename);
|
||||
lf.f = fopen(filename, "r");
|
||||
}
|
||||
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? */
|
||||
fclose(lf.f);
|
||||
lf.f = fopen(filename, "rb"); /* reopen in binary mode */
|
||||
if (lf.f == NULL) return errfile(L, filename); /* unable to reopen file */
|
||||
if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */
|
||||
}
|
||||
if (filename == NULL)
|
||||
lua_pushliteral(L, "=stdin");
|
||||
else
|
||||
lua_pushfstring(L, "@%s", filename);
|
||||
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
|
||||
lua_remove(L, old_top+1); /* remove filename from stack */
|
||||
if (ferror(lf.f)) {
|
||||
lua_settop(L, old_top); /* ignore results from `lua_load' */
|
||||
return errfile(L, filename);
|
||||
readstatus = ferror(lf.f);
|
||||
if (lf.f != stdin) fclose(lf.f); /* close file (even in case of errors) */
|
||||
if (readstatus) {
|
||||
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
|
||||
return errfile(L, fnameindex);
|
||||
}
|
||||
if (lf.f != stdin)
|
||||
fclose(lf.f);
|
||||
lua_remove(L, fnameindex);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -412,9 +429,14 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
|
||||
static void callalert (lua_State *L, int status) {
|
||||
if (status != 0) {
|
||||
lua_getglobal(L, "_ALERT");
|
||||
lua_insert(L, -2);
|
||||
lua_call(L, 1, 0);
|
||||
lua_pop(L, 1);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
lua_insert(L, -2);
|
||||
lua_call(L, 1, 0);
|
||||
}
|
||||
else { /* no _ALERT function; print it on stderr */
|
||||
fprintf(stderr, "%s\n", lua_tostring(L, -2));
|
||||
lua_pop(L, 2); /* remove error message and _ALERT */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
70
lauxlib.h
70
lauxlib.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lauxlib.h,v 1.51 2002/07/01 19:23:58 roberto Exp roberto $
|
||||
** $Id: lauxlib.h,v 1.54 2002/09/16 19:49:45 roberto Exp roberto $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -27,34 +27,32 @@ typedef struct luaL_reg {
|
||||
} luaL_reg;
|
||||
|
||||
|
||||
LUALIB_API void luaL_openlib (lua_State *L, const luaL_reg *l, int nup);
|
||||
LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname,
|
||||
const luaL_reg *l, int nup);
|
||||
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event);
|
||||
LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
|
||||
const luaL_reg *l, int nup);
|
||||
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname);
|
||||
LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg);
|
||||
LUALIB_API const char *luaL_check_lstr (lua_State *L, int numArg,
|
||||
size_t *len);
|
||||
LUALIB_API const char *luaL_opt_lstr (lua_State *L, int numArg,
|
||||
const char *def, size_t *len);
|
||||
LUALIB_API lua_Number luaL_check_number (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Number luaL_opt_number (lua_State *L, int nArg, lua_Number def);
|
||||
LUALIB_API const char *luaL_checklstring (lua_State *L, int numArg, size_t *l);
|
||||
LUALIB_API const char *luaL_optlstring (lua_State *L, int numArg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Number luaL_optnumber (lua_State *L, int nArg, lua_Number def);
|
||||
|
||||
LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *msg);
|
||||
LUALIB_API void luaL_check_type (lua_State *L, int narg, int t);
|
||||
LUALIB_API void luaL_check_any (lua_State *L, int narg);
|
||||
LUALIB_API void luaL_checkstack (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void luaL_checktype (lua_State *L, int narg, int t);
|
||||
LUALIB_API void luaL_checkany (lua_State *L, int narg);
|
||||
|
||||
LUALIB_API void luaL_where (lua_State *L, int level);
|
||||
LUALIB_API void luaL_where (lua_State *L, int lvl);
|
||||
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...);
|
||||
|
||||
LUALIB_API int luaL_findstring (const char *name,
|
||||
const char *const list[]);
|
||||
LUALIB_API int luaL_findstring (const char *st, const char *const lst[]);
|
||||
|
||||
LUALIB_API int luaL_ref (lua_State *L, int t);
|
||||
LUALIB_API void luaL_unref (lua_State *L, int t, int ref);
|
||||
|
||||
LUALIB_API int luaL_loadfile (lua_State *L, const char *filename);
|
||||
LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
|
||||
LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name);
|
||||
|
||||
|
||||
@@ -65,14 +63,14 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
#define luaL_arg_check(L, cond,numarg,extramsg) if (!(cond)) \
|
||||
#define luaL_argcheck(L, cond,numarg,extramsg) if (!(cond)) \
|
||||
luaL_argerror(L, numarg,extramsg)
|
||||
#define luaL_check_string(L,n) (luaL_check_lstr(L, (n), NULL))
|
||||
#define luaL_opt_string(L,n,d) (luaL_opt_lstr(L, (n), (d), NULL))
|
||||
#define luaL_check_int(L,n) ((int)luaL_check_number(L, n))
|
||||
#define luaL_check_long(L,n) ((long)luaL_check_number(L, n))
|
||||
#define luaL_opt_int(L,n,d) ((int)luaL_opt_number(L, n,d))
|
||||
#define luaL_opt_long(L,n,d) ((long)luaL_opt_number(L, n,d))
|
||||
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||
#define luaL_checkint(L,n) ((int)luaL_checknumber(L, n))
|
||||
#define luaL_checklong(L,n) ((long)luaL_checknumber(L, n))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optnumber(L, n,d))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optnumber(L, n,d))
|
||||
|
||||
|
||||
/*
|
||||
@@ -89,7 +87,7 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
char *p; /* current position in buffer */
|
||||
int level;
|
||||
int lvl; /* number of strings in the stack (level) */
|
||||
lua_State *L;
|
||||
char buffer[LUAL_BUFFERSIZE];
|
||||
} luaL_Buffer;
|
||||
@@ -116,14 +114,24 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B);
|
||||
** Compatibility macros
|
||||
*/
|
||||
|
||||
#define luaL_checktype luaL_check_type
|
||||
#define luaL_checkany luaL_check_any
|
||||
|
||||
LUALIB_API int lua_dofile (lua_State *L, const char *filename);
|
||||
LUALIB_API int lua_dostring (lua_State *L, const char *str);
|
||||
LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
|
||||
const char *name);
|
||||
LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t sz,
|
||||
const char *n);
|
||||
|
||||
/*
|
||||
#define luaL_check_lstr luaL_checklstring
|
||||
#define luaL_opt_lstr luaL_optlstring
|
||||
#define luaL_check_number luaL_checknumber
|
||||
#define luaL_opt_number luaL_optnumber
|
||||
#define luaL_arg_check luaL_argcheck
|
||||
#define luaL_check_string luaL_checkstring
|
||||
#define luaL_opt_string luaL_optstring
|
||||
#define luaL_check_int luaL_checkint
|
||||
#define luaL_check_long luaL_checklong
|
||||
#define luaL_opt_int luaL_optint
|
||||
#define luaL_opt_long luaL_optlong
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
294
lbaselib.c
294
lbaselib.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lbaselib.c,v 1.96 2002/08/06 18:54:18 roberto Exp roberto $
|
||||
** $Id: lbaselib.c,v 1.114 2002/12/04 17:38:31 roberto Exp roberto $
|
||||
** Basic library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define lbaselib_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
@@ -47,19 +49,19 @@ static int luaB_print (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_tonumber (lua_State *L) {
|
||||
int base = luaL_opt_int(L, 2, 10);
|
||||
int base = luaL_optint(L, 2, 10);
|
||||
if (base == 10) { /* standard conversion */
|
||||
luaL_check_any(L, 1);
|
||||
luaL_checkany(L, 1);
|
||||
if (lua_isnumber(L, 1)) {
|
||||
lua_pushnumber(L, lua_tonumber(L, 1));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const char *s1 = luaL_check_string(L, 1);
|
||||
const char *s1 = luaL_checkstring(L, 1);
|
||||
char *s2;
|
||||
unsigned long n;
|
||||
luaL_arg_check(L, 2 <= base && base <= 36, 2, "base out of range");
|
||||
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
|
||||
n = strtoul(s1, &s2, base);
|
||||
if (s1 != s2) { /* at least one valid digit? */
|
||||
while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
|
||||
@@ -75,57 +77,37 @@ static int luaB_tonumber (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_error (lua_State *L) {
|
||||
int level = luaL_opt_int(L, 2, 1);
|
||||
luaL_check_any(L, 1);
|
||||
int level = luaL_optint(L, 2, 1);
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_isstring(L, 1) || level == 0)
|
||||
lua_pushvalue(L, 1); /* propagate error mesage without changes */
|
||||
lua_pushvalue(L, 1); /* propagate error message without changes */
|
||||
else { /* add extra information */
|
||||
luaL_where(L, level);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_pushliteral(L, "\n");
|
||||
lua_concat(L, 3);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_getmode (lua_State *L) {
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
lua_pushstring(L, lua_getmode(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_setmode (lua_State *L) {
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
lua_setmode(L, 1, luaL_check_string(L, 2));
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_getmetatable (lua_State *L) {
|
||||
luaL_check_any(L, 1);
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_getmetatable(L, 1)) {
|
||||
lua_pushnil(L);
|
||||
return 1; /* no metatable */
|
||||
}
|
||||
else {
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_rawget(L, -2);
|
||||
if (lua_isnil(L, -1))
|
||||
lua_pop(L, 1);
|
||||
/* otherwise returns metatable.__metatable */
|
||||
}
|
||||
return 1;
|
||||
luaL_getmetafield(L, 1, "__metatable");
|
||||
return 1; /* returns either __metatable field (if present) or metatable */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
luaL_arg_check(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
|
||||
"nil or table expected");
|
||||
if (luaL_getmetafield(L, 1, "__metatable"))
|
||||
luaL_error(L, "cannot change a protected metatable");
|
||||
lua_settop(L, 2);
|
||||
lua_setmetatable(L, 1);
|
||||
return 1;
|
||||
@@ -136,8 +118,8 @@ static void getfunc (lua_State *L) {
|
||||
if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
|
||||
else {
|
||||
lua_Debug ar;
|
||||
int level = luaL_opt_int(L, 1, 1);
|
||||
luaL_arg_check(L, level >= 0, 1, "level must be non-negative");
|
||||
int level = luaL_optint(L, 1, 1);
|
||||
luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
|
||||
if (lua_getstack(L, level, &ar) == 0)
|
||||
luaL_argerror(L, 1, "invalid level");
|
||||
lua_getinfo(L, "f", &ar);
|
||||
@@ -145,16 +127,29 @@ static void getfunc (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int aux_getglobals (lua_State *L) {
|
||||
lua_getglobals(L, -1);
|
||||
lua_pushliteral(L, "__globals");
|
||||
lua_rawget(L, -2);
|
||||
return !lua_isnil(L, -1);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_getglobals (lua_State *L) {
|
||||
getfunc(L);
|
||||
lua_getglobals(L, -1);
|
||||
if (!aux_getglobals(L)) /* __globals not defined? */
|
||||
lua_pop(L, 1); /* remove it, to return real globals */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_setglobals (lua_State *L) {
|
||||
luaL_check_type(L, 2, LUA_TTABLE);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
getfunc(L);
|
||||
if (aux_getglobals(L)) /* __globals defined? */
|
||||
luaL_error(L, "cannot change a protected global table");
|
||||
else
|
||||
lua_pop(L, 2); /* remove __globals and real global table */
|
||||
lua_pushvalue(L, 2);
|
||||
if (lua_setglobals(L, -2) == 0)
|
||||
luaL_error(L, "cannot change global table of given function");
|
||||
@@ -163,24 +158,24 @@ static int luaB_setglobals (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_rawequal (lua_State *L) {
|
||||
luaL_check_any(L, 1);
|
||||
luaL_check_any(L, 2);
|
||||
luaL_checkany(L, 1);
|
||||
luaL_checkany(L, 2);
|
||||
lua_pushboolean(L, lua_rawequal(L, 1, 2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawget (lua_State *L) {
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
luaL_check_any(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
lua_rawget(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int luaB_rawset (lua_State *L) {
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
luaL_check_any(L, 2);
|
||||
luaL_check_any(L, 3);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
luaL_checkany(L, 3);
|
||||
lua_rawset(L, 1);
|
||||
return 1;
|
||||
}
|
||||
@@ -194,20 +189,20 @@ static int luaB_gcinfo (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_collectgarbage (lua_State *L) {
|
||||
lua_setgcthreshold(L, luaL_opt_int(L, 1, 0));
|
||||
lua_setgcthreshold(L, luaL_optint(L, 1, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_type (lua_State *L) {
|
||||
luaL_check_any(L, 1);
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_next (lua_State *L) {
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
|
||||
if (lua_next(L, 1))
|
||||
return 2;
|
||||
@@ -219,8 +214,9 @@ static int luaB_next (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_pairs (lua_State *L) {
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
lua_getglobal(L, "next"); /* return generator, */
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_pushliteral(L, "next");
|
||||
lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
lua_pushnil(L); /* and initial value */
|
||||
return 3;
|
||||
@@ -229,9 +225,10 @@ static int luaB_pairs (lua_State *L) {
|
||||
|
||||
static int luaB_ipairs (lua_State *L) {
|
||||
lua_Number i = lua_tonumber(L, 2);
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
if (i == 0 && lua_isnull(L, 2)) { /* `for' start? */
|
||||
lua_getglobal(L, "ipairs"); /* return generator, */
|
||||
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_pushvalue(L, 1); /* state, */
|
||||
lua_pushnumber(L, 0); /* and initial value */
|
||||
return 3;
|
||||
@@ -245,8 +242,16 @@ static int luaB_ipairs (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int passresults (lua_State *L, int status) {
|
||||
if (status == 0) return 1;
|
||||
static int load_aux (lua_State *L, int status) {
|
||||
if (status == 0) { /* OK? */
|
||||
lua_Debug ar;
|
||||
lua_getstack(L, 1, &ar);
|
||||
lua_getinfo(L, "f", &ar); /* get calling function */
|
||||
lua_getglobals(L, -1); /* get its global table */
|
||||
lua_setglobals(L, -3); /* set it as the global table of the new chunk */
|
||||
lua_pop(L, 1); /* remove calling function */
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
lua_insert(L, -2);
|
||||
@@ -257,20 +262,20 @@ static int passresults (lua_State *L, int status) {
|
||||
|
||||
static int luaB_loadstring (lua_State *L) {
|
||||
size_t l;
|
||||
const char *s = luaL_check_lstr(L, 1, &l);
|
||||
const char *chunkname = luaL_opt_string(L, 2, s);
|
||||
return passresults(L, luaL_loadbuffer(L, s, l, chunkname));
|
||||
const char *s = luaL_checklstring(L, 1, &l);
|
||||
const char *chunkname = luaL_optstring(L, 2, s);
|
||||
return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
|
||||
}
|
||||
|
||||
|
||||
static int luaB_loadfile (lua_State *L) {
|
||||
const char *fname = luaL_opt_string(L, 1, NULL);
|
||||
return passresults(L, luaL_loadfile(L, fname));
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
return load_aux(L, luaL_loadfile(L, fname));
|
||||
}
|
||||
|
||||
|
||||
static int luaB_dofile (lua_State *L) {
|
||||
const char *fname = luaL_opt_string(L, 1, NULL);
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
int status = luaL_loadfile(L, fname);
|
||||
if (status != 0) lua_error(L);
|
||||
lua_call(L, 0, LUA_MULTRET);
|
||||
@@ -279,9 +284,9 @@ static int luaB_dofile (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_assert (lua_State *L) {
|
||||
luaL_check_any(L, 1);
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_toboolean(L, 1))
|
||||
return luaL_error(L, "%s", luaL_opt_string(L, 2, "assertion failed!"));
|
||||
return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
@@ -289,12 +294,12 @@ static int luaB_assert (lua_State *L) {
|
||||
|
||||
static int luaB_unpack (lua_State *L) {
|
||||
int n, i;
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_pushliteral(L, "n");
|
||||
lua_rawget(L, 1);
|
||||
n = (lua_isnumber(L, -1)) ? (int)lua_tonumber(L, -1) : -1;
|
||||
for (i=0; i<n || n==-1; i++) { /* push arg[1...n] */
|
||||
luaL_check_stack(L, LUA_MINSTACK, "table too big to unpack");
|
||||
luaL_checkstack(L, LUA_MINSTACK, "table too big to unpack");
|
||||
lua_rawgeti(L, 1, i+1);
|
||||
if (n == -1) { /* no explicit limit? */
|
||||
if (lua_isnil(L, -1)) { /* stop at first `nil' element */
|
||||
@@ -309,7 +314,7 @@ static int luaB_unpack (lua_State *L) {
|
||||
|
||||
static int luaB_pcall (lua_State *L) {
|
||||
int status;
|
||||
luaL_check_any(L, 1);
|
||||
luaL_checkany(L, 1);
|
||||
status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
|
||||
lua_pushboolean(L, (status == 0));
|
||||
lua_insert(L, 1);
|
||||
@@ -319,7 +324,7 @@ static int luaB_pcall (lua_State *L) {
|
||||
|
||||
static int luaB_xpcall (lua_State *L) {
|
||||
int status;
|
||||
luaL_check_any(L, 2);
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_insert(L, 1); /* put error function under function to be called */
|
||||
status = lua_pcall(L, 0, LUA_MULTRET, 1);
|
||||
@@ -354,6 +359,9 @@ static int luaB_tostring (lua_State *L) {
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
|
||||
break;
|
||||
case LUA_TTHREAD:
|
||||
sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1));
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
lua_pushliteral(L, "nil");
|
||||
return 1;
|
||||
@@ -381,7 +389,7 @@ static int luaB_newproxy (lua_State *L) {
|
||||
validproxy = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1); /* remove value */
|
||||
}
|
||||
luaL_arg_check(L, validproxy, 1, "boolean/proxy expected");
|
||||
luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
|
||||
lua_getmetatable(L, 1); /* metatable is valid; get it */
|
||||
}
|
||||
lua_setmetatable(L, 2);
|
||||
@@ -425,7 +433,7 @@ static const char *getpath (lua_State *L) {
|
||||
|
||||
static const char *pushnextpath (lua_State *L, const char *path) {
|
||||
const char *l;
|
||||
if (*path == '\0') return NULL; /* no more pathes */
|
||||
if (*path == '\0') return NULL; /* no more paths */
|
||||
if (*path == LUA_PATH_SEP) path++; /* skip separator */
|
||||
l = strchr(path, LUA_PATH_SEP); /* find next separator */
|
||||
if (l == NULL) l = path+strlen(path);
|
||||
@@ -448,7 +456,7 @@ static void pushcomposename (lua_State *L) {
|
||||
static int luaB_require (lua_State *L) {
|
||||
const char *path;
|
||||
int status = LUA_ERRFILE; /* not found (yet) */
|
||||
luaL_check_string(L, 1);
|
||||
luaL_checkstring(L, 1);
|
||||
lua_settop(L, 1);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_setglobal(L, "_REQUIREDNAME");
|
||||
@@ -494,8 +502,6 @@ static const luaL_reg base_funcs[] = {
|
||||
{"setmetatable", luaB_setmetatable},
|
||||
{"getglobals", luaB_getglobals},
|
||||
{"setglobals", luaB_setglobals},
|
||||
{"getmode", luaB_getmode},
|
||||
{"setmode", luaB_setmode},
|
||||
{"next", luaB_next},
|
||||
{"ipairs", luaB_ipairs},
|
||||
{"pairs", luaB_pairs},
|
||||
@@ -526,48 +532,65 @@ static const luaL_reg base_funcs[] = {
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
static int luaB_resume (lua_State *L) {
|
||||
lua_State *co = (lua_State *)lua_unboxpointer(L, lua_upvalueindex(1));
|
||||
static int auxresume (lua_State *L, lua_State *co, int narg) {
|
||||
int status;
|
||||
lua_settop(L, 0);
|
||||
status = lua_resume(L, co);
|
||||
if (status != 0)
|
||||
return lua_error(L);
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int gc_coroutine (lua_State *L) {
|
||||
lua_State *co = (lua_State *)lua_unboxpointer(L, 1);
|
||||
lua_closethread(L, co);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_coroutine (lua_State *L) {
|
||||
lua_State *NL;
|
||||
int ref;
|
||||
int i;
|
||||
int n = lua_gettop(L);
|
||||
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
|
||||
"Lua function expected");
|
||||
NL = lua_newthread(L);
|
||||
if (NL == NULL) return luaL_error(L, "unable to create new thread");
|
||||
/* move function and arguments from L to NL */
|
||||
for (i=0; i<n; i++) {
|
||||
ref = lua_ref(L, 1);
|
||||
lua_getref(NL, ref);
|
||||
lua_insert(NL, 1);
|
||||
lua_unref(L, ref);
|
||||
if (!lua_checkstack(co, narg))
|
||||
luaL_error(L, "too many arguments to resume");
|
||||
lua_xmove(L, co, narg);
|
||||
status = lua_resume(co, narg);
|
||||
if (status == 0) {
|
||||
int nres = lua_gettop(co);
|
||||
if (!lua_checkstack(L, narg))
|
||||
luaL_error(L, "too many results to resume");
|
||||
lua_xmove(co, L, nres); /* move yielded values */
|
||||
return nres;
|
||||
}
|
||||
lua_cobegin(NL, n-1);
|
||||
lua_boxpointer(L, NL);
|
||||
lua_pushliteral(L, "Coroutine");
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushcclosure(L, luaB_resume, 1);
|
||||
else {
|
||||
lua_xmove(co, L, 1); /* move error message */
|
||||
return -1; /* error flag */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_coresume (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
int r;
|
||||
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||
r = auxresume(L, co, lua_gettop(L) - 1);
|
||||
if (r < 0) {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_insert(L, -2);
|
||||
return 2; /* return false + error message */
|
||||
}
|
||||
else {
|
||||
lua_pushboolean(L, 1);
|
||||
lua_insert(L, -(r + 1));
|
||||
return r + 1; /* return true + `resume' returns */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_auxwrap (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
|
||||
int r = auxresume(L, co, lua_gettop(L));
|
||||
if (r < 0) lua_error(L); /* propagate error */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_cocreate (lua_State *L) {
|
||||
lua_State *NL = lua_newthread(L);
|
||||
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
|
||||
"Lua function expected");
|
||||
lua_pushvalue(L, 1); /* move function to top */
|
||||
lua_xmove(L, NL, 1); /* move function from L to NL */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_cowrap (lua_State *L) {
|
||||
luaB_cocreate(L);
|
||||
lua_pushcclosure(L, luaB_auxwrap, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -576,24 +599,31 @@ static int luaB_yield (lua_State *L) {
|
||||
return lua_yield(L, lua_gettop(L));
|
||||
}
|
||||
|
||||
|
||||
static int luaB_costatus (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||
if (L == co) lua_pushliteral(L, "running");
|
||||
else {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0)
|
||||
lua_pushliteral(L, "dead");
|
||||
else
|
||||
lua_pushliteral(L, "suspended");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_reg co_funcs[] = {
|
||||
{"create", luaB_coroutine},
|
||||
{"create", luaB_cocreate},
|
||||
{"wrap", luaB_cowrap},
|
||||
{"resume", luaB_coresume},
|
||||
{"yield", luaB_yield},
|
||||
{"status", luaB_costatus},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
static void co_open (lua_State *L) {
|
||||
luaL_opennamedlib(L, LUA_COLIBNAME, co_funcs, 0);
|
||||
/* create metatable for coroutines */
|
||||
lua_pushliteral(L, "Coroutine");
|
||||
lua_newtable(L);
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_coroutine);
|
||||
lua_rawset(L, -3);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
@@ -601,14 +631,18 @@ static void co_open (lua_State *L) {
|
||||
static void base_open (lua_State *L) {
|
||||
lua_pushliteral(L, "_G");
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
luaL_openlib(L, base_funcs, 0); /* open lib into global table */
|
||||
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 */
|
||||
/* `newproxy' needs a weaktable as upvalue */
|
||||
lua_pushliteral(L, "newproxy");
|
||||
lua_newtable(L); /* new table `w' */
|
||||
lua_setmode(L, -1, "k");
|
||||
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_pushcclosure(L, luaB_newproxy, 1);
|
||||
lua_rawset(L, -3); /* set global `newproxy' */
|
||||
lua_rawset(L, -1); /* set global _G */
|
||||
@@ -617,7 +651,7 @@ static void base_open (lua_State *L) {
|
||||
|
||||
LUALIB_API int lua_baselibopen (lua_State *L) {
|
||||
base_open(L);
|
||||
co_open(L);
|
||||
luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0);
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, REQTAB);
|
||||
return 0;
|
||||
|
||||
104
lcode.c
104
lcode.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.c,v 1.108 2002/06/13 13:39:55 roberto Exp $
|
||||
** $Id: lcode.c,v 1.114 2002/12/04 17:38:31 roberto Exp roberto $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define lcode_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lcode.h"
|
||||
@@ -100,14 +102,14 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) {
|
||||
static int need_value (FuncState *fs, int list, int cond) {
|
||||
for (; list != NO_JUMP; list = luaK_getjump(fs, list)) {
|
||||
Instruction i = *getjumpcontrol(fs, list);
|
||||
if (GET_OPCODE(i) != OP_TEST || GETARG_B(i) != cond) return 1;
|
||||
if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1;
|
||||
}
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
|
||||
static void patchtestreg (Instruction *i, int reg) {
|
||||
if (reg == NO_REG) reg = GETARG_C(*i);
|
||||
if (reg == NO_REG) reg = GETARG_B(*i);
|
||||
SETARG_A(*i, reg);
|
||||
}
|
||||
|
||||
@@ -122,7 +124,7 @@ static void luaK_patchlistaux (FuncState *fs, int list,
|
||||
luaK_fixjump(fs, list, dtarget); /* jump to default target */
|
||||
}
|
||||
else {
|
||||
if (GETARG_B(*i)) {
|
||||
if (GETARG_C(*i)) {
|
||||
lua_assert(ttarget != NO_JUMP);
|
||||
patchtestreg(i, treg);
|
||||
luaK_fixjump(fs, list, ttarget);
|
||||
@@ -174,7 +176,7 @@ void luaK_concat (FuncState *fs, int *l1, int l2) {
|
||||
}
|
||||
|
||||
|
||||
static void luaK_checkstack (FuncState *fs, int n) {
|
||||
void luaK_checkstack (FuncState *fs, int n) {
|
||||
int newstack = fs->freereg + n;
|
||||
if (newstack > fs->f->maxstacksize) {
|
||||
if (newstack >= MAXSTACK)
|
||||
@@ -214,7 +216,7 @@ static int addk (FuncState *fs, TObject *k, TObject *v) {
|
||||
Proto *f = fs->f;
|
||||
luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject,
|
||||
MAXARG_Bx, "constant table overflow");
|
||||
setobj(&f->k[fs->nk], v);
|
||||
setobj2n(&f->k[fs->nk], v);
|
||||
setnvalue(luaH_set(fs->L, fs->h, k), fs->nk);
|
||||
return fs->nk++;
|
||||
}
|
||||
@@ -409,7 +411,7 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
/* not a constant in the right range: put in a register */
|
||||
/* not a constant in the right range: put it in a register */
|
||||
return luaK_exp2anyreg(fs, e);
|
||||
}
|
||||
|
||||
@@ -432,8 +434,8 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
|
||||
break;
|
||||
}
|
||||
case VINDEXED: {
|
||||
int e = luaK_exp2anyreg(fs, exp);
|
||||
luaK_codeABC(fs, OP_SETTABLE, e, var->info, var->aux);
|
||||
int e = luaK_exp2RK(fs, exp);
|
||||
luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -460,8 +462,9 @@ 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));
|
||||
SETARG_B(*pc, !(GETARG_B(*pc)));
|
||||
lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) &&
|
||||
GET_OPCODE(*pc) != OP_TEST);
|
||||
SETARG_A(*pc, !(GETARG_A(*pc)));
|
||||
}
|
||||
|
||||
|
||||
@@ -470,13 +473,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
|
||||
Instruction ie = getcode(fs, e);
|
||||
if (GET_OPCODE(ie) == OP_NOT) {
|
||||
fs->pc--; /* remove previous OP_NOT */
|
||||
return luaK_condjump(fs, OP_TEST, NO_REG, !cond ,GETARG_B(ie));
|
||||
return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond);
|
||||
}
|
||||
/* else go through */
|
||||
}
|
||||
discharge2anyreg(fs, e);
|
||||
freeexp(fs, e);
|
||||
return luaK_condjump(fs, OP_TEST, NO_REG, cond, e->info);
|
||||
return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond);
|
||||
}
|
||||
|
||||
|
||||
@@ -605,11 +608,6 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
|
||||
luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
|
||||
break;
|
||||
}
|
||||
case OPR_SUB: case OPR_DIV: case OPR_POW: {
|
||||
/* non-comutative operators */
|
||||
luaK_exp2anyreg(fs, v); /* first operand must be a register */
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
luaK_exp2RK(fs, v);
|
||||
break;
|
||||
@@ -619,40 +617,22 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
|
||||
|
||||
|
||||
static void codebinop (FuncState *fs, expdesc *res, BinOpr op,
|
||||
int o1, int o2, int ic) {
|
||||
switch (op) {
|
||||
case OPR_SUB:
|
||||
case OPR_DIV:
|
||||
case OPR_POW:
|
||||
lua_assert(!ic);
|
||||
/* go through */
|
||||
case OPR_ADD:
|
||||
case OPR_MULT: { /* ORDER OPR */
|
||||
OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD);
|
||||
res->info = luaK_codeABC(fs, opc, 0, o1, o2);
|
||||
res->k = VRELOCABLE;
|
||||
break;
|
||||
int o1, int o2) {
|
||||
if (op <= OPR_POW) { /* arithmetic operator? */
|
||||
OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */
|
||||
res->info = luaK_codeABC(fs, opc, 0, o1, o2);
|
||||
res->k = VRELOCABLE;
|
||||
}
|
||||
else { /* test operator */
|
||||
static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE};
|
||||
int cond = 1;
|
||||
if (op >= OPR_GT) { /* `>' or `>='? */
|
||||
int temp; /* exchange args and replace by `<' or `<=' */
|
||||
temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
|
||||
}
|
||||
case OPR_NE:
|
||||
case OPR_EQ: {
|
||||
res->info = luaK_condjump(fs, OP_EQ, o1, (op == OPR_EQ), o2);
|
||||
res->k = VJMP;
|
||||
break;
|
||||
}
|
||||
case OPR_LT:
|
||||
case OPR_LE:
|
||||
case OPR_GT:
|
||||
case OPR_GE: { /* ORDER OPR */
|
||||
OpCode opc;
|
||||
int i = op - OPR_LT;
|
||||
if (ic) /* operands were interchanged? */
|
||||
i = (i+2)&3; /* correct operator */
|
||||
opc = cast(OpCode, i + OP_LT);
|
||||
res->info = luaK_condjump(fs, opc, o1, 1, o2);
|
||||
res->k = VJMP;
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0);
|
||||
else if (op == OPR_NE) cond = 0;
|
||||
res->info = luaK_condjump(fs, ops[op - OPR_NE], cond, o1, o2);
|
||||
res->k = VJMP;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,21 +671,11 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
int o1, o2;
|
||||
int ic; /* interchange flag */
|
||||
if (e1->k != VK) { /* not a constant operator? */
|
||||
o1 = e1->info;
|
||||
o2 = luaK_exp2RK(fs, e2); /* maybe other operator is constant... */
|
||||
ic = 0;
|
||||
}
|
||||
else { /* interchange operands */
|
||||
o2 = luaK_exp2RK(fs, e1); /* constant must be 2nd operand */
|
||||
o1 = luaK_exp2anyreg(fs, e2); /* other operator must be in register */
|
||||
ic = 1;
|
||||
}
|
||||
int o1 = luaK_exp2RK(fs, e1);
|
||||
int o2 = luaK_exp2RK(fs, e2);
|
||||
freeexp(fs, e2);
|
||||
freeexp(fs, e1);
|
||||
codebinop(fs, e1, op, o1, o2, ic);
|
||||
codebinop(fs, e1, op, o1, o2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -718,14 +688,14 @@ void luaK_fixline (FuncState *fs, int line) {
|
||||
|
||||
int luaK_code (FuncState *fs, Instruction i, int line) {
|
||||
Proto *f = fs->f;
|
||||
int oldsize = f->sizecode;
|
||||
luaK_dischargejpc(fs); /* `pc' will change */
|
||||
/* put new instruction in code array */
|
||||
luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
|
||||
MAX_INT, "code size overflow");
|
||||
f->code[fs->pc] = i;
|
||||
if (f->sizecode != oldsize)
|
||||
luaM_reallocvector(fs->L, f->lineinfo, oldsize, f->sizecode, int);
|
||||
/* save corresponding line information */
|
||||
luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
|
||||
MAX_INT, "code size overflow");
|
||||
f->lineinfo[fs->pc] = line;
|
||||
return fs->pc++;
|
||||
}
|
||||
|
||||
3
lcode.h
3
lcode.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.h,v 1.36 2002/05/13 13:07:48 roberto Exp roberto $
|
||||
** $Id: lcode.h,v 1.37 2002/06/12 19:16:00 roberto Exp roberto $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -47,6 +47,7 @@ int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
|
||||
void luaK_fixline (FuncState *fs, int line);
|
||||
void luaK_nil (FuncState *fs, int from, int n);
|
||||
void luaK_reserveregs (FuncState *fs, int n);
|
||||
void luaK_checkstack (FuncState *fs, int n);
|
||||
int luaK_stringK (FuncState *fs, TString *s);
|
||||
int luaK_numberK (FuncState *fs, lua_Number r);
|
||||
void luaK_dischargevars (FuncState *fs, expdesc *e);
|
||||
|
||||
59
ldblib.c
59
ldblib.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldblib.c,v 1.66 2002/08/06 18:01:50 roberto Exp roberto $
|
||||
** $Id: ldblib.c,v 1.74 2002/12/04 17:38:31 roberto Exp roberto $
|
||||
** Interface from Lua to its debug API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ldblib_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
@@ -32,7 +34,7 @@ static void settabsi (lua_State *L, const char *i, int v) {
|
||||
|
||||
static int getinfo (lua_State *L) {
|
||||
lua_Debug ar;
|
||||
const char *options = luaL_opt_string(L, 2, "flnSu");
|
||||
const char *options = luaL_optstring(L, 2, "flnSu");
|
||||
if (lua_isnumber(L, 1)) {
|
||||
if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) {
|
||||
lua_pushnil(L); /* level out of range */
|
||||
@@ -81,9 +83,9 @@ static int getinfo (lua_State *L) {
|
||||
static int getlocal (lua_State *L) {
|
||||
lua_Debug ar;
|
||||
const char *name;
|
||||
if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */
|
||||
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_check_int(L, 2));
|
||||
name = lua_getlocal(L, &ar, luaL_checkint(L, 2));
|
||||
if (name) {
|
||||
lua_pushstring(L, name);
|
||||
lua_pushvalue(L, -2);
|
||||
@@ -98,10 +100,10 @@ static int getlocal (lua_State *L) {
|
||||
|
||||
static int setlocal (lua_State *L) {
|
||||
lua_Debug ar;
|
||||
if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */
|
||||
if (!lua_getstack(L, luaL_checkint(L, 1), &ar)) /* level out of range? */
|
||||
return luaL_argerror(L, 1, "level out of range");
|
||||
luaL_check_any(L, 3);
|
||||
lua_pushstring(L, lua_setlocal(L, &ar, luaL_check_int(L, 2)));
|
||||
luaL_checkany(L, 3);
|
||||
lua_pushstring(L, lua_setlocal(L, &ar, luaL_checkint(L, 2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -126,16 +128,17 @@ static void hookf (lua_State *L, lua_Debug *ar) {
|
||||
}
|
||||
|
||||
|
||||
static unsigned long makemask (const char *smask, int count) {
|
||||
unsigned long mask = 0;
|
||||
static int makemask (const char *smask, int count) {
|
||||
int mask = 0;
|
||||
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
|
||||
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
|
||||
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
|
||||
return mask | LUA_MASKCOUNT(count);
|
||||
if (count > 0) mask |= LUA_MASKCOUNT;
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
static char *unmakemask (unsigned long mask, char *smask) {
|
||||
static char *unmakemask (int mask, char *smask) {
|
||||
int i = 0;
|
||||
if (mask & LUA_MASKCALL) smask[i++] = 'c';
|
||||
if (mask & LUA_MASKRET) smask[i++] = 'r';
|
||||
@@ -148,14 +151,13 @@ static char *unmakemask (unsigned long mask, char *smask) {
|
||||
static int sethook (lua_State *L) {
|
||||
if (lua_isnoneornil(L, 1)) {
|
||||
lua_settop(L, 1);
|
||||
lua_sethook(L, NULL, 0); /* turn off hooks */
|
||||
lua_sethook(L, NULL, 0, 0); /* turn off hooks */
|
||||
}
|
||||
else {
|
||||
const char *smask = luaL_check_string(L, 2);
|
||||
lua_Number count = luaL_opt_number(L, 3, 0);
|
||||
luaL_check_type(L, 1, LUA_TFUNCTION);
|
||||
luaL_arg_check(L, count <= LUA_MAXCOUNT, 2, "count too large (>= 2^24)");
|
||||
lua_sethook(L, hookf, makemask(smask, count));
|
||||
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);
|
||||
}
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
lua_pushvalue(L, 1);
|
||||
@@ -166,11 +168,16 @@ static int sethook (lua_State *L) {
|
||||
|
||||
static int gethook (lua_State *L) {
|
||||
char buff[5];
|
||||
unsigned long mask = lua_gethookmask(L);
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
|
||||
int mask = lua_gethookmask(L);
|
||||
lua_Hook hook = lua_gethook(L);
|
||||
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 */
|
||||
}
|
||||
lua_pushstring(L, unmakemask(mask, buff));
|
||||
lua_pushnumber(L, lua_getmaskcount(mask));
|
||||
lua_pushnumber(L, lua_gethookcount(L));
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -198,21 +205,22 @@ static int errorfb (lua_State *L) {
|
||||
if (lua_gettop(L) == 0)
|
||||
lua_pushliteral(L, "");
|
||||
else if (!lua_isstring(L, 1)) return 1; /* no string message */
|
||||
lua_pushliteral(L, "stack traceback:\n");
|
||||
else lua_pushliteral(L, "\n");
|
||||
lua_pushliteral(L, "stack traceback:");
|
||||
while (lua_getstack(L, level++, &ar)) {
|
||||
if (level > LEVELS1 && firstpart) {
|
||||
/* no more than `LEVELS2' more levels? */
|
||||
if (!lua_getstack(L, level+LEVELS2, &ar))
|
||||
level--; /* keep going */
|
||||
else {
|
||||
lua_pushliteral(L, "\t...\n"); /* too many levels */
|
||||
lua_pushliteral(L, "\n\t..."); /* too many levels */
|
||||
while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */
|
||||
level++;
|
||||
}
|
||||
firstpart = 0;
|
||||
continue;
|
||||
}
|
||||
lua_pushliteral(L, "\t");
|
||||
lua_pushliteral(L, "\n\t");
|
||||
lua_getinfo(L, "Snl", &ar);
|
||||
lua_pushfstring(L, "%s:", ar.short_src);
|
||||
if (ar.currentline > 0)
|
||||
@@ -234,7 +242,6 @@ static int errorfb (lua_State *L) {
|
||||
ar.short_src, ar.linedefined);
|
||||
}
|
||||
}
|
||||
lua_pushliteral(L, "\n");
|
||||
lua_concat(L, lua_gettop(L));
|
||||
}
|
||||
lua_concat(L, lua_gettop(L));
|
||||
@@ -255,7 +262,7 @@ static const luaL_reg dblib[] = {
|
||||
|
||||
|
||||
LUALIB_API int lua_dblibopen (lua_State *L) {
|
||||
luaL_opennamedlib(L, LUA_DBLIBNAME, dblib, 0);
|
||||
luaL_openlib(L, LUA_DBLIBNAME, dblib, 0);
|
||||
lua_pushliteral(L, "_TRACEBACK");
|
||||
lua_pushcfunction(L, errorfb);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
|
||||
86
ldebug.c
86
ldebug.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldebug.c,v 1.131 2002/08/08 20:08:41 roberto Exp roberto $
|
||||
** $Id: ldebug.c,v 1.142 2002/12/06 17:15:35 roberto Exp roberto $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ldebug_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lapi.h"
|
||||
@@ -49,20 +51,27 @@ static int currentline (CallInfo *ci) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_sethook (lua_State *L, lua_Hook func, unsigned long mask) {
|
||||
int allow;
|
||||
void luaG_inithooks (lua_State *L) {
|
||||
CallInfo *ci;
|
||||
lua_lock(L);
|
||||
allow = allowhook(L);
|
||||
if (func == NULL) mask = 0;
|
||||
else if (mask == 0) func = NULL;
|
||||
L->hook = func;
|
||||
L->hookmask = mask;
|
||||
setallowhook(L, allow);
|
||||
resethookcount(L);
|
||||
for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */
|
||||
currentpc(ci);
|
||||
lua_unlock(L);
|
||||
L->hookinit = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** this function can be called asynchronous (e.g. during a signal)
|
||||
*/
|
||||
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
|
||||
if (func == NULL || mask == 0) { /* turn off hooks? */
|
||||
mask = 0;
|
||||
func = NULL;
|
||||
}
|
||||
L->hook = func;
|
||||
L->basehookcount = count;
|
||||
resethookcount(L);
|
||||
L->hookmask = cast(lu_byte, mask);
|
||||
L->hookinit = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -72,17 +81,24 @@ LUA_API lua_Hook lua_gethook (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API unsigned long lua_gethookmask (lua_State *L) {
|
||||
LUA_API int lua_gethookmask (lua_State *L) {
|
||||
return L->hookmask;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_gethookcount (lua_State *L) {
|
||||
return L->basehookcount;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
|
||||
int status;
|
||||
int ci;
|
||||
lua_lock(L);
|
||||
if (L->ci - L->base_ci <= level) status = 0; /* there is no such level */
|
||||
ci = (L->ci - L->base_ci) - level;
|
||||
if (ci <= 0) status = 0; /* there is no such level */
|
||||
else {
|
||||
ar->i_ci = (L->ci - L->base_ci) - level;
|
||||
ar->i_ci = ci;
|
||||
status = 1;
|
||||
}
|
||||
lua_unlock(L);
|
||||
@@ -127,7 +143,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
|
||||
setobj(ci->base+(n-1), L->top);
|
||||
setobjs2s(ci->base+(n-1), L->top);
|
||||
}
|
||||
lua_unlock(L);
|
||||
return name;
|
||||
@@ -218,7 +234,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
||||
break;
|
||||
}
|
||||
case 'f': {
|
||||
setobj(L->top, f);
|
||||
setobj2s(L->top, f);
|
||||
status = 2;
|
||||
break;
|
||||
}
|
||||
@@ -248,6 +264,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
||||
|
||||
static int precheck (const Proto *pt) {
|
||||
check(pt->maxstacksize <= MAXSTACK);
|
||||
check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
|
||||
lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize);
|
||||
check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
|
||||
return 1;
|
||||
@@ -269,6 +286,11 @@ 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 Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
int pc;
|
||||
int last; /* stores position of last instruction that changed `reg' */
|
||||
@@ -285,11 +307,13 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
case iABC: {
|
||||
b = GETARG_B(i);
|
||||
c = GETARG_C(i);
|
||||
if (testOpMode(op, OpModeBreg))
|
||||
if (testOpMode(op, OpModeBreg)) {
|
||||
checkreg(pt, b);
|
||||
if (testOpMode(op, OpModeCreg))
|
||||
check(c < pt->maxstacksize ||
|
||||
(c >= MAXSTACK && c-MAXSTACK < pt->sizek));
|
||||
}
|
||||
else if (testOpMode(op, OpModeBrk))
|
||||
check(checkRK(pt, b));
|
||||
if (testOpMode(op, OpModeCrk))
|
||||
check(checkRK(pt, c));
|
||||
break;
|
||||
}
|
||||
case iABx: {
|
||||
@@ -340,7 +364,8 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
break;
|
||||
}
|
||||
case OP_TFORLOOP:
|
||||
checkreg(pt, a+2+c);
|
||||
checkreg(pt, a+c+5);
|
||||
if (reg >= a) last = pc; /* affect all registers above base */
|
||||
/* go through */
|
||||
case OP_FORLOOP:
|
||||
checkreg(pt, a+2);
|
||||
@@ -480,7 +505,7 @@ void luaG_typeerror (lua_State *L, const TObject *o, const char *op) {
|
||||
const char *name = NULL;
|
||||
const char *t = luaT_typenames[ttype(o)];
|
||||
const char *kind = (isinstack(L->ci, o)) ?
|
||||
getobjname(L->ci, o - L->ci->base, &name) : NULL;
|
||||
getobjname(L->ci, o - L->base, &name) : NULL;
|
||||
if (kind)
|
||||
luaG_runerror(L, "attempt to %s %s `%s' (a %s value)",
|
||||
op, kind, name, t);
|
||||
@@ -496,7 +521,7 @@ void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
|
||||
}
|
||||
|
||||
|
||||
void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2) {
|
||||
void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2) {
|
||||
TObject temp;
|
||||
if (luaV_tonumber(p1, &temp) == NULL)
|
||||
p2 = p1; /* first operand is wrong */
|
||||
@@ -517,14 +542,11 @@ int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) {
|
||||
|
||||
static void addinfo (lua_State *L, const char *msg) {
|
||||
CallInfo *ci = L->ci;
|
||||
if (!isLua(ci)) { /* no Lua code? */
|
||||
luaO_pushfstring(L, "%s\n", msg); /* no extra info; just add '\n' */
|
||||
}
|
||||
else { /* add file:line information */
|
||||
char buff[LUA_IDSIZE];
|
||||
if (isLua(ci)) { /* is Lua code? */
|
||||
char buff[LUA_IDSIZE]; /* add file:line information */
|
||||
int line = currentline(ci);
|
||||
luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
|
||||
luaO_pushfstring(L, "%s:%d: %s\n", buff, line, msg);
|
||||
luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,8 +555,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);
|
||||
setobj(L->top, L->top - 1); /* move argument */
|
||||
setobj(L->top - 1, errfunc); /* push function */
|
||||
setobjs2s(L->top, L->top - 1); /* move argument */
|
||||
setobjs2s(L->top - 1, errfunc); /* push function */
|
||||
incr_top(L);
|
||||
luaD_call(L, L->top - 2, 1); /* call it */
|
||||
}
|
||||
|
||||
10
ldebug.h
10
ldebug.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldebug.h,v 1.29 2002/08/08 20:08:41 roberto Exp roberto $
|
||||
** $Id: ldebug.h,v 1.31 2002/08/20 20:03:05 roberto Exp roberto $
|
||||
** Auxiliary functions from Debug Interface module
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -15,15 +15,13 @@
|
||||
|
||||
#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
|
||||
|
||||
#define resethookcount(L) (L->hookcount = lua_getmaskcount(L->hookmask))
|
||||
|
||||
#define setallowhook(L,cond) ((L->hookmask) = ((L->hookmask) & ~1) | (cond))
|
||||
#define allowhook(L) ((L->hookmask) & 1)
|
||||
#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_concaterror (lua_State *L, StkId p1, StkId p2);
|
||||
void luaG_aritherror (lua_State *L, StkId p1, const TObject *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_runerror (lua_State *L, const char *fmt, ...);
|
||||
void luaG_errormsg (lua_State *L);
|
||||
|
||||
228
ldo.c
228
ldo.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldo.c,v 1.191 2002/08/07 19:22:39 roberto Exp roberto $
|
||||
** $Id: ldo.c,v 1.210 2002/12/04 17:28:27 roberto Exp roberto $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ldo_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
@@ -44,22 +46,23 @@ struct lua_longjmp {
|
||||
};
|
||||
|
||||
|
||||
static void seterrorobj (lua_State *L, int errcode) {
|
||||
static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
|
||||
switch (errcode) {
|
||||
case LUA_ERRMEM: {
|
||||
setsvalue(L->top, luaS_new(L, MEMERRMSG));
|
||||
setsvalue2s(oldtop, luaS_new(L, MEMERRMSG));
|
||||
break;
|
||||
}
|
||||
case LUA_ERRERR: {
|
||||
setsvalue(L->top, luaS_new(L, "error in error handling"));
|
||||
setsvalue2s(oldtop, luaS_new(L, "error in error handling"));
|
||||
break;
|
||||
}
|
||||
case LUA_ERRSYNTAX:
|
||||
case LUA_ERRRUN: {
|
||||
return; /* error message already on top */
|
||||
setobjs2s(oldtop, L->top - 1); /* error message on current top */
|
||||
break;
|
||||
}
|
||||
}
|
||||
L->top++;
|
||||
L->top = oldtop + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,16 +104,15 @@ static void restore_stack_limit (lua_State *L) {
|
||||
|
||||
static void correctstack (lua_State *L, TObject *oldstack) {
|
||||
CallInfo *ci;
|
||||
UpVal *up;
|
||||
GCObject *up;
|
||||
L->top = (L->top - oldstack) + L->stack;
|
||||
for (up = L->openupval; up != NULL; up = up->next)
|
||||
up->v = (up->v - oldstack) + L->stack;
|
||||
for (up = L->openupval; up != NULL; up = up->gch.next)
|
||||
gcotouv(up)->v = (gcotouv(up)->v - oldstack) + L->stack;
|
||||
for (ci = L->base_ci; ci <= L->ci; ci++) {
|
||||
ci->base = (ci->base - oldstack) + L->stack;
|
||||
ci->top = (ci->top - oldstack) + L->stack;
|
||||
if (ci->state & CI_HASFRAME) /* Lua function with active frame? */
|
||||
*ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */
|
||||
ci->base = (ci->base - oldstack) + L->stack;
|
||||
}
|
||||
L->base = L->ci->base;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +128,7 @@ void luaD_reallocstack (lua_State *L, int newsize) {
|
||||
void luaD_reallocCI (lua_State *L, int newsize) {
|
||||
CallInfo *oldci = L->base_ci;
|
||||
luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
|
||||
L->size_ci = newsize;
|
||||
L->size_ci = cast(unsigned short, newsize);
|
||||
L->ci = (L->ci - oldci) + L->base_ci;
|
||||
L->end_ci = L->base_ci + L->size_ci;
|
||||
}
|
||||
@@ -151,9 +153,9 @@ static void luaD_growCI (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
void luaD_callhook (lua_State *L, lua_Hookevent event, int line) {
|
||||
void luaD_callhook (lua_State *L, int event, int line) {
|
||||
lua_Hook hook = L->hook;
|
||||
if (hook && allowhook(L)) {
|
||||
if (hook && L->allowhook) {
|
||||
ptrdiff_t top = savestack(L, L->top);
|
||||
ptrdiff_t ci_top = savestack(L, L->ci->top);
|
||||
lua_Debug ar;
|
||||
@@ -162,12 +164,12 @@ void luaD_callhook (lua_State *L, lua_Hookevent event, int line) {
|
||||
ar.i_ci = L->ci - L->base_ci;
|
||||
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
||||
L->ci->top = L->top + LUA_MINSTACK;
|
||||
setallowhook(L, 0); /* cannot call hooks inside a hook */
|
||||
L->allowhook = 0; /* cannot call hooks inside a hook */
|
||||
lua_unlock(L);
|
||||
(*hook)(L, &ar);
|
||||
lua_lock(L);
|
||||
lua_assert(!allowhook(L));
|
||||
setallowhook(L, 1);
|
||||
lua_assert(!L->allowhook);
|
||||
L->allowhook = 1;
|
||||
L->ci->top = restorestack(L, ci_top);
|
||||
L->top = restorestack(L, top);
|
||||
}
|
||||
@@ -187,7 +189,7 @@ static void adjust_varargs (lua_State *L, int nfixargs, StkId base) {
|
||||
actual -= nfixargs; /* number of extra arguments */
|
||||
htab = luaH_new(L, 0, 0); /* create `arg' table */
|
||||
for (i=0; i<actual; i++) /* put extra arguments into `arg' table */
|
||||
setobj(luaH_setnum(L, htab, i+1), L->top - actual + i);
|
||||
setobj2n(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), actual);
|
||||
@@ -204,10 +206,10 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
|
||||
if (!ttisfunction(tm))
|
||||
luaG_typeerror(L, func, "call");
|
||||
/* Open a hole inside the stack at `func' */
|
||||
for (p = L->top; p > func; p--) setobj(p, p-1);
|
||||
for (p = L->top; p > func; p--) setobjs2s(p, p-1);
|
||||
incr_top(L);
|
||||
func = restorestack(L, funcr); /* previous call may change stack */
|
||||
setobj(func, tm); /* tag method is the new function to be called */
|
||||
setobj2s(func, tm); /* tag method is the new function to be called */
|
||||
return func;
|
||||
}
|
||||
|
||||
@@ -218,6 +220,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
|
||||
if (!ttisfunction(func)) /* `func' is not a function? */
|
||||
func = tryfuncTM(L, func); /* check the `function' tag method */
|
||||
if (L->ci + 1 == L->end_ci) luaD_growCI(L);
|
||||
else condhardstacktests(luaD_reallocCI(L, L->size_ci));
|
||||
cl = &clvalue(func)->l;
|
||||
if (!cl->isC) { /* Lua function? prepare its call */
|
||||
CallInfo *ci;
|
||||
@@ -226,8 +229,8 @@ StkId luaD_precall (lua_State *L, StkId func) {
|
||||
adjust_varargs(L, p->numparams, func+1);
|
||||
luaD_checkstack(L, p->maxstacksize);
|
||||
ci = ++L->ci; /* now `enter' new function */
|
||||
ci->base = restorestack(L, funcr) + 1;
|
||||
ci->top = ci->base + p->maxstacksize;
|
||||
L->base = L->ci->base = restorestack(L, funcr) + 1;
|
||||
ci->top = L->base + p->maxstacksize;
|
||||
ci->u.l.savedpc = p->code; /* starting point */
|
||||
ci->state = CI_SAVEDPC;
|
||||
while (L->top < ci->top)
|
||||
@@ -240,18 +243,18 @@ StkId luaD_precall (lua_State *L, StkId func) {
|
||||
int n;
|
||||
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
||||
ci = ++L->ci; /* now `enter' new function */
|
||||
ci->base = restorestack(L, funcr) + 1;
|
||||
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);
|
||||
ci = L->ci; /* previous call may realocate `ci' */
|
||||
ci = L->ci; /* previous call may reallocate `ci' */
|
||||
}
|
||||
lua_unlock(L);
|
||||
#ifdef LUA_COMPATUPVALUES
|
||||
lua_pushupvalues(L);
|
||||
#endif
|
||||
n = (*clvalue(ci->base-1)->c.f)(L); /* do the actual call */
|
||||
n = (*clvalue(L->base - 1)->c.f)(L); /* do the actual call */
|
||||
lua_lock(L);
|
||||
return L->top - n;
|
||||
}
|
||||
@@ -265,11 +268,12 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
|
||||
luaD_callhook(L, LUA_HOOKRET, -1);
|
||||
firstResult = restorestack(L, fr);
|
||||
}
|
||||
res = L->ci->base - 1; /* res == final position of 1st result */
|
||||
res = L->base - 1; /* res == final position of 1st result */
|
||||
L->ci--;
|
||||
L->base = L->ci->base; /* restore base */
|
||||
/* move results to correct place */
|
||||
while (wanted != 0 && firstResult < L->top) {
|
||||
setobj(res++, firstResult++);
|
||||
setobjs2s(res++, firstResult++);
|
||||
wanted--;
|
||||
}
|
||||
while (wanted-- > 0)
|
||||
@@ -286,73 +290,68 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
|
||||
** function position.
|
||||
*/
|
||||
void luaD_call (lua_State *L, StkId func, int nResults) {
|
||||
StkId firstResult = luaD_precall(L, func);
|
||||
if (firstResult == NULL) { /* is a Lua function? */
|
||||
StkId firstResult;
|
||||
if (++L->nCcalls >= LUA_MAXCCALLS) {
|
||||
if (L->nCcalls == LUA_MAXCCALLS)
|
||||
luaG_runerror(L, "stack overflow");
|
||||
else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3)))
|
||||
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
|
||||
}
|
||||
firstResult = luaD_precall(L, func);
|
||||
if (firstResult == NULL) /* is a Lua function? */
|
||||
firstResult = luaV_execute(L); /* call it */
|
||||
if (firstResult == NULL) {
|
||||
luaD_poscall(L, 0, L->top);
|
||||
luaG_runerror(L, "attempt to yield across tag-method/C-call boundary");
|
||||
}
|
||||
}
|
||||
luaD_poscall(L, nResults, firstResult);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_cobegin (lua_State *L, int nargs) {
|
||||
lua_lock(L);
|
||||
luaD_precall(L, L->top - (nargs+1));
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
||||
static void move_results (lua_State *L, TObject *from, TObject *to) {
|
||||
while (from < to) {
|
||||
setobj(L->top, from);
|
||||
from++;
|
||||
incr_top(L);
|
||||
}
|
||||
L->nCcalls--;
|
||||
}
|
||||
|
||||
|
||||
static void resume (lua_State *L, void *ud) {
|
||||
StkId firstResult;
|
||||
int nargs = *cast(int *, ud);
|
||||
CallInfo *ci = L->ci;
|
||||
if (ci->state & CI_C) { /* not first time (i.e. inside a 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); /* complete it */
|
||||
if (nresults >= 0) L->top = L->ci->top;
|
||||
if (ci == L->base_ci) { /* no activation record? */
|
||||
if (nargs >= L->top - L->base)
|
||||
luaG_runerror(L, "cannot resume dead coroutine");
|
||||
luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */
|
||||
}
|
||||
else if (ci->state & CI_YIELD) { /* inside a yield? */
|
||||
if (ci->state & CI_C) { /* `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
|
||||
luaG_runerror(L, "cannot resume non-suspended coroutine");
|
||||
firstResult = luaV_execute(L);
|
||||
if (firstResult == NULL) /* yield? */
|
||||
*cast(int *, ud) = L->ci->u.c.yield_results;
|
||||
else { /* return */
|
||||
*cast(int *, ud) = L->top - firstResult;
|
||||
if (firstResult != NULL) /* return? */
|
||||
luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_resume (lua_State *L, lua_State *co) {
|
||||
CallInfo *ci;
|
||||
int numres;
|
||||
LUA_API int lua_resume (lua_State *L, int nargs) {
|
||||
int status;
|
||||
lu_byte old_allowhooks;
|
||||
lua_lock(L);
|
||||
ci = co->ci;
|
||||
if (ci == co->base_ci) /* no activation record? ?? */
|
||||
luaG_runerror(L, "cannot resume dead thread");
|
||||
if (co->errorJmp != NULL) /* ?? */
|
||||
luaG_runerror(L, "cannot resume active thread");
|
||||
status = luaD_rawrunprotected(co, resume, &numres);
|
||||
if (status == 0)
|
||||
move_results(L, co->top - numres, co->top);
|
||||
else {
|
||||
setobj(L->top++, co->top - 1); /* move error message to other stack */
|
||||
co->ci = co->base_ci; /* `kill' thread */
|
||||
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 */
|
||||
L->base = L->ci->base;
|
||||
L->nCcalls = 0;
|
||||
luaF_close(L, L->base); /* close eventual pending closures */
|
||||
seterrorobj(L, status, L->base);
|
||||
L->allowhook = old_allowhooks;
|
||||
restore_stack_limit(L);
|
||||
}
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
@@ -363,51 +362,41 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
|
||||
CallInfo *ci;
|
||||
lua_lock(L);
|
||||
ci = L->ci;
|
||||
if ((ci-1)->state & CI_C)
|
||||
luaG_runerror(L, "cannot yield a C function");
|
||||
lua_assert(ci->state & CI_C); /* current function is not Lua */
|
||||
ci->u.c.yield_results = nresults;
|
||||
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 (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);
|
||||
L->top = L->base + nresults;
|
||||
}
|
||||
} /* else it's an yield inside a hook: nothing to do */
|
||||
ci->state |= CI_YIELD;
|
||||
lua_unlock(L);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Execute a protected call.
|
||||
*/
|
||||
struct CallS { /* data to `f_call' */
|
||||
StkId func;
|
||||
int nresults;
|
||||
};
|
||||
|
||||
|
||||
static void f_call (lua_State *L, void *ud) {
|
||||
struct CallS *c = cast(struct CallS *, ud);
|
||||
luaD_call(L, c->func, c->nresults);
|
||||
}
|
||||
|
||||
|
||||
int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
|
||||
struct CallS c;
|
||||
int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||
ptrdiff_t old_top, ptrdiff_t ef) {
|
||||
int status;
|
||||
ptrdiff_t old_top = savestack(L, L->top);
|
||||
unsigned short oldnCcalls = L->nCcalls;
|
||||
ptrdiff_t old_ci = saveci(L, L->ci);
|
||||
int old_allowhooks = allowhook(L);
|
||||
lu_byte old_allowhooks = L->allowhook;
|
||||
ptrdiff_t old_errfunc = L->errfunc;
|
||||
L->errfunc = errfunc;
|
||||
c.func = L->top - (nargs+1); /* function to be called */
|
||||
c.nresults = nresults;
|
||||
status = luaD_rawrunprotected(L, &f_call, &c);
|
||||
L->errfunc = ef;
|
||||
status = luaD_rawrunprotected(L, func, u);
|
||||
if (status != 0) { /* an error occurred? */
|
||||
StkId err; /* error msg. position */
|
||||
seterrorobj(L, status);
|
||||
err = L->top - 1;
|
||||
/* remove parameters and func from the stack */
|
||||
L->top = restorestack(L, old_top) - (nargs+1);
|
||||
setobj(L->top++, err); /* copy error message to corrected top */
|
||||
luaF_close(L, L->top); /* close eventual pending closures */
|
||||
StkId oldtop = restorestack(L, old_top);
|
||||
luaF_close(L, oldtop); /* close eventual pending closures */
|
||||
seterrorobj(L, status, oldtop);
|
||||
L->nCcalls = oldnCcalls;
|
||||
L->ci = restoreci(L, old_ci);
|
||||
setallowhook(L, old_allowhooks);
|
||||
L->base = L->ci->base;
|
||||
L->allowhook = old_allowhooks;
|
||||
restore_stack_limit(L);
|
||||
}
|
||||
L->errfunc = old_errfunc;
|
||||
@@ -415,17 +404,20 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Execute a protected parser.
|
||||
*/
|
||||
struct SParser { /* data to `f_parser' */
|
||||
ZIO *z;
|
||||
Mbuffer buff; /* buffer to be used by the scanner */
|
||||
int bin;
|
||||
};
|
||||
|
||||
static void f_parser (lua_State *L, void *ud) {
|
||||
struct SParser *p = cast(struct SParser *, ud);
|
||||
Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
|
||||
Proto *tf = p->bin ? luaU_undump(L, p->z, &p->buff) :
|
||||
luaY_parser(L, p->z, &p->buff);
|
||||
Closure *cl = luaF_newLclosure(L, 0, gt(L));
|
||||
cl->l.p = tf;
|
||||
setclvalue(L->top, cl);
|
||||
@@ -439,11 +431,13 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
|
||||
int status;
|
||||
ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */
|
||||
p.z = z; p.bin = bin;
|
||||
luaZ_initbuffer(L, &p.buff);
|
||||
/* before parsing, give a (good) chance to GC */
|
||||
if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
|
||||
luaC_collectgarbage(L);
|
||||
old_blocks = G(L)->nblocks;
|
||||
status = luaD_rawrunprotected(L, f_parser, &p);
|
||||
luaZ_freebuffer(L, &p.buff);
|
||||
if (status == 0) {
|
||||
/* add new memory to threshold (as it probably will stay) */
|
||||
lua_assert(G(L)->nblocks >= old_blocks);
|
||||
@@ -451,9 +445,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
|
||||
}
|
||||
else { /* error */
|
||||
StkId oldtop = restorestack(L, oldtopr);
|
||||
seterrorobj(L, status);
|
||||
setobj(oldtop, L->top - 1); /* copy error message to old top */
|
||||
L->top = oldtop+1;
|
||||
seterrorobj(L, status, oldtop);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
26
ldo.h
26
ldo.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldo.h,v 1.50 2002/08/06 15:32:22 roberto Exp roberto $
|
||||
** $Id: ldo.h,v 1.55 2002/11/21 17:41:25 roberto Exp roberto $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -14,15 +14,22 @@
|
||||
|
||||
|
||||
/*
|
||||
** macro to increment stack top.
|
||||
** There must be always an empty slot at the L->stack.top
|
||||
*/
|
||||
#define incr_top(L) \
|
||||
{if (L->top >= L->stack_last) luaD_growstack(L, 1); L->top++;}
|
||||
** macro to control inclusion of some hard tests on stack reallocation
|
||||
*/
|
||||
#ifndef HARDSTACKTESTS
|
||||
#define condhardstacktests(x) { /* empty */ }
|
||||
#else
|
||||
#define condhardstacktests(x) x
|
||||
#endif
|
||||
|
||||
|
||||
#define luaD_checkstack(L,n) \
|
||||
if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TObject)) \
|
||||
luaD_growstack(L, n)
|
||||
luaD_growstack(L, n); \
|
||||
else condhardstacktests(luaD_reallocstack(L, L->stacksize));
|
||||
|
||||
|
||||
#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)))
|
||||
@@ -36,10 +43,11 @@ typedef void (*Pfunc) (lua_State *L, void *ud);
|
||||
|
||||
void luaD_resetprotection (lua_State *L);
|
||||
int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
|
||||
void luaD_callhook (lua_State *L, lua_Hookevent event, int line);
|
||||
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);
|
||||
int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc);
|
||||
int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||
ptrdiff_t oldtop, ptrdiff_t ef);
|
||||
void luaD_poscall (lua_State *L, int wanted, StkId firstResult);
|
||||
void luaD_reallocCI (lua_State *L, int newsize);
|
||||
void luaD_reallocstack (lua_State *L, int newsize);
|
||||
|
||||
160
ldump.c
Normal file
160
ldump.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
** $Id: ldump.c,v 1.1 2002/10/25 21:31:28 roberto Exp roberto $
|
||||
** save bytecodes
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define ldump_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lstate.h"
|
||||
#include "lundump.h"
|
||||
|
||||
#define DumpVector(b,n,size,D) DumpBlock(b,(n)*(size),D)
|
||||
#define DumpLiteral(s,D) DumpBlock("" s,(sizeof(s))-1,D)
|
||||
|
||||
typedef struct {
|
||||
lua_State *L;
|
||||
lua_Chunkwriter write;
|
||||
void *data;
|
||||
} DumpState;
|
||||
|
||||
|
||||
static void DumpBlock(const void *b, size_t size, DumpState* D)
|
||||
{
|
||||
lua_unlock(D->L);
|
||||
(*D->write)(D->L,b,size,D->data);
|
||||
lua_lock(D->L);
|
||||
}
|
||||
|
||||
static void DumpByte(int y, DumpState* D)
|
||||
{
|
||||
char x=(char)y;
|
||||
DumpBlock(&x,sizeof(x),D);
|
||||
}
|
||||
|
||||
static void DumpInt(int x, DumpState* D)
|
||||
{
|
||||
DumpBlock(&x,sizeof(x),D);
|
||||
}
|
||||
|
||||
static void DumpSize(size_t x, DumpState* D)
|
||||
{
|
||||
DumpBlock(&x,sizeof(x),D);
|
||||
}
|
||||
|
||||
static void DumpNumber(lua_Number x, DumpState* D)
|
||||
{
|
||||
DumpBlock(&x,sizeof(x),D);
|
||||
}
|
||||
|
||||
static void DumpString(TString* s, DumpState* D)
|
||||
{
|
||||
if (s==NULL || getstr(s)==NULL)
|
||||
DumpSize(0,D);
|
||||
else
|
||||
{
|
||||
size_t size=s->tsv.len+1; /* include trailing '\0' */
|
||||
DumpSize(size,D);
|
||||
DumpBlock(getstr(s),size,D);
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpCode(const Proto* f, DumpState* D)
|
||||
{
|
||||
DumpInt(f->sizecode,D);
|
||||
DumpVector(f->code,f->sizecode,sizeof(*f->code),D);
|
||||
}
|
||||
|
||||
static void DumpLocals(const Proto* f, DumpState* D)
|
||||
{
|
||||
int i,n=f->sizelocvars;
|
||||
DumpInt(n,D);
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
DumpString(f->locvars[i].varname,D);
|
||||
DumpInt(f->locvars[i].startpc,D);
|
||||
DumpInt(f->locvars[i].endpc,D);
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpLines(const Proto* f, DumpState* D)
|
||||
{
|
||||
DumpInt(f->sizelineinfo,D);
|
||||
DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D);
|
||||
}
|
||||
|
||||
static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
|
||||
|
||||
static void DumpConstants(const Proto* f, DumpState* D)
|
||||
{
|
||||
int i,n;
|
||||
DumpInt(n=f->sizek,D);
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
const TObject* o=&f->k[i];
|
||||
DumpByte(ttype(o),D);
|
||||
switch (ttype(o))
|
||||
{
|
||||
case LUA_TNUMBER:
|
||||
DumpNumber(nvalue(o),D);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
DumpString(tsvalue(o),D);
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
break;
|
||||
default:
|
||||
lua_assert(0); /* cannot happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
DumpInt(n=f->sizep,D);
|
||||
for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
|
||||
}
|
||||
|
||||
static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
|
||||
{
|
||||
DumpString((f->source==p) ? NULL : f->source,D);
|
||||
DumpInt(f->lineDefined,D);
|
||||
DumpByte(f->nupvalues,D);
|
||||
DumpByte(f->numparams,D);
|
||||
DumpByte(f->is_vararg,D);
|
||||
DumpByte(f->maxstacksize,D);
|
||||
DumpLocals(f,D);
|
||||
DumpLines(f,D);
|
||||
DumpConstants(f,D);
|
||||
DumpCode(f,D);
|
||||
}
|
||||
|
||||
static void DumpHeader(DumpState* D)
|
||||
{
|
||||
DumpLiteral(LUA_SIGNATURE,D);
|
||||
DumpByte(VERSION,D);
|
||||
DumpByte(luaU_endianness(),D);
|
||||
DumpByte(sizeof(int),D);
|
||||
DumpByte(sizeof(size_t),D);
|
||||
DumpByte(sizeof(Instruction),D);
|
||||
DumpByte(SIZE_OP,D);
|
||||
DumpByte(SIZE_A,D);
|
||||
DumpByte(SIZE_B,D);
|
||||
DumpByte(SIZE_C,D);
|
||||
DumpByte(sizeof(lua_Number),D);
|
||||
DumpNumber(TEST_NUMBER,D);
|
||||
}
|
||||
|
||||
void luaU_dump(lua_State *L, const Proto* Main, lua_Chunkwriter w, void* data)
|
||||
{
|
||||
DumpState D;
|
||||
D.L=L;
|
||||
D.write=w;
|
||||
D.data=data;
|
||||
DumpHeader(&D);
|
||||
DumpFunction(Main,NULL,&D);
|
||||
}
|
||||
|
||||
49
lfunc.c
49
lfunc.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lfunc.c,v 1.56 2002/05/02 13:06:20 roberto Exp roberto $
|
||||
** $Id: lfunc.c,v 1.63 2002/11/14 16:15:53 roberto Exp roberto $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,9 +7,12 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define lfunc_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lfunc.h"
|
||||
#include "lgc.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
@@ -25,10 +28,8 @@
|
||||
|
||||
Closure *luaF_newCclosure (lua_State *L, int nelems) {
|
||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
|
||||
luaC_link(L, valtogco(c), LUA_TFUNCTION);
|
||||
c->c.isC = 1;
|
||||
c->c.next = G(L)->rootcl;
|
||||
G(L)->rootcl = c;
|
||||
c->c.marked = 0;
|
||||
c->c.nupvalues = cast(lu_byte, nelems);
|
||||
return c;
|
||||
}
|
||||
@@ -36,10 +37,8 @@ Closure *luaF_newCclosure (lua_State *L, int nelems) {
|
||||
|
||||
Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *gt) {
|
||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
|
||||
luaC_link(L, valtogco(c), LUA_TFUNCTION);
|
||||
c->l.isC = 0;
|
||||
c->c.next = G(L)->rootcl;
|
||||
G(L)->rootcl = c;
|
||||
c->l.marked = 0;
|
||||
c->l.g = *gt;
|
||||
c->l.nupvalues = cast(lu_byte, nelems);
|
||||
return c;
|
||||
@@ -47,63 +46,63 @@ Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *gt) {
|
||||
|
||||
|
||||
UpVal *luaF_findupval (lua_State *L, StkId level) {
|
||||
UpVal **pp = &L->openupval;
|
||||
GCObject **pp = &L->openupval;
|
||||
UpVal *p;
|
||||
while ((p = *pp) != NULL && p->v >= level) {
|
||||
UpVal *v;
|
||||
while ((p = ngcotouv(*pp)) != NULL && p->v >= level) {
|
||||
if (p->v == level) return p;
|
||||
pp = &p->next;
|
||||
}
|
||||
p = luaM_new(L, UpVal); /* not found: create a new one */
|
||||
p->v = level; /* current value lives in the stack */
|
||||
p->next = *pp; /* chain it in the proper position */
|
||||
*pp = p;
|
||||
return p;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void luaF_close (lua_State *L, StkId level) {
|
||||
UpVal *p;
|
||||
while ((p = L->openupval) != NULL && p->v >= level) {
|
||||
setobj(&p->value, p->v); /* save current value */
|
||||
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 */
|
||||
p->next = G(L)->rootupval; /* chain in `closed' list */
|
||||
G(L)->rootupval = p;
|
||||
luaC_link(L, valtogco(p), LUA_TUPVAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Proto *luaF_newproto (lua_State *L) {
|
||||
Proto *f = luaM_new(L, Proto);
|
||||
luaC_link(L, valtogco(f), LUA_TPROTO);
|
||||
f->k = NULL;
|
||||
f->sizek = 0;
|
||||
f->p = NULL;
|
||||
f->sizep = 0;
|
||||
f->code = NULL;
|
||||
f->sizecode = 0;
|
||||
f->sizelineinfo = 0;
|
||||
f->nupvalues = 0;
|
||||
f->numparams = 0;
|
||||
f->is_vararg = 0;
|
||||
f->maxstacksize = 0;
|
||||
f->marked = 0;
|
||||
f->lineinfo = NULL;
|
||||
f->sizelocvars = 0;
|
||||
f->locvars = NULL;
|
||||
f->lineDefined = 0;
|
||||
f->source = NULL;
|
||||
f->next = G(L)->rootproto; /* chain in list of protos */
|
||||
G(L)->rootproto = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
void luaF_freeproto (lua_State *L, Proto *f) {
|
||||
luaM_freearray(L, f->code, f->sizecode, Instruction);
|
||||
if (f->lineinfo)
|
||||
luaM_freearray(L, f->lineinfo, f->sizecode, int);
|
||||
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
|
||||
luaM_freearray(L, f->k, f->sizek, TObject);
|
||||
luaM_freearray(L, f->p, f->sizep, Proto *);
|
||||
luaM_freearray(L, f->k, f->sizek, TObject);
|
||||
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
|
||||
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
|
||||
luaM_freelem(L, f);
|
||||
}
|
||||
|
||||
|
||||
660
lgc.c
660
lgc.c
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
** $Id: lgc.c,v 1.144 2002/08/05 14:50:39 roberto Exp roberto $
|
||||
** $Id: lgc.c,v 1.165 2002/12/02 12:06:10 roberto Exp roberto $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define lgc_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
@@ -21,183 +23,112 @@
|
||||
|
||||
|
||||
typedef struct GCState {
|
||||
Table *tmark; /* list of marked tables to be visited */
|
||||
Table *toclear; /* list of visited weak tables (to be cleared after GC) */
|
||||
lua_State *L;
|
||||
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;
|
||||
|
||||
|
||||
/* mark a string; marks larger than 1 cannot be changed */
|
||||
#define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;}
|
||||
/*
|
||||
** 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 unmark(x) resetbit((x)->gch.marked, 0)
|
||||
#define ismarked(x) ((x)->gch.marked & ((1<<4)|1))
|
||||
|
||||
#define stringmark(s) setbit((s)->tsv.marked, 0)
|
||||
|
||||
|
||||
/* unmarked tables are represented by pointing `mark' to themselves */
|
||||
#define ismarked(x) ((x)->mark != (x))
|
||||
#define isfinalized(u) (!testbit((u)->uv.marked, 1))
|
||||
#define markfinalized(u) resetbit((u)->uv.marked, 1)
|
||||
|
||||
|
||||
#define KEYWEAKBIT 1
|
||||
#define VALUEWEAKBIT 2
|
||||
#define KEYWEAK (1<<KEYWEAKBIT)
|
||||
#define VALUEWEAK (1<<VALUEWEAKBIT)
|
||||
|
||||
|
||||
|
||||
/* mark tricks for userdata */
|
||||
#define isudmarked(u) (u->uv.len & 1)
|
||||
#define markud(u) (u->uv.len |= 1)
|
||||
#define unmarkud(u) (u->uv.len &= (~(size_t)1))
|
||||
#define markobject(st,o) { checkconsistency(o); \
|
||||
if (iscollectable(o) && !ismarked(gcvalue(o))) reallymarkobject(st,gcvalue(o)); }
|
||||
|
||||
#define isfinalized(u) (u->uv.len & 2)
|
||||
#define markfinalized(u) (u->uv.len |= 2)
|
||||
#define condmarkobject(st,o,c) { checkconsistency(o); \
|
||||
if (iscollectable(o) && !ismarked(gcvalue(o)) && (c)) \
|
||||
reallymarkobject(st,gcvalue(o)); }
|
||||
|
||||
|
||||
/* mark tricks for upvalues (assume that open upvalues are always marked) */
|
||||
#define isupvalmarked(uv) ((uv)->v != &(uv)->value)
|
||||
#define markvalue(st,t) { if (!ismarked(valtogco(t))) \
|
||||
reallymarkobject(st, valtogco(t)); }
|
||||
|
||||
|
||||
|
||||
#define ismarkable(o) (!((1 << ttype(o)) & \
|
||||
((1 << LUA_TNIL) | (1 << LUA_TNUMBER) | \
|
||||
(1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA))))
|
||||
|
||||
static void reallymarkobject (GCState *st, TObject *o);
|
||||
|
||||
#define markobject(st,o) if (ismarkable(o)) reallymarkobject(st,o)
|
||||
|
||||
|
||||
static void protomark (Proto *f) {
|
||||
if (!f->marked) {
|
||||
int i;
|
||||
f->marked = 1;
|
||||
strmark(f->source);
|
||||
for (i=0; i<f->sizek; i++) {
|
||||
if (ttisstring(f->k+i))
|
||||
strmark(tsvalue(f->k+i));
|
||||
}
|
||||
for (i=0; i<f->sizep; i++)
|
||||
protomark(f->p[i]);
|
||||
for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */
|
||||
strmark(f->locvars[i].varname);
|
||||
}
|
||||
lua_assert(luaG_checkcode(f));
|
||||
}
|
||||
|
||||
|
||||
static void marktable (GCState *st, Table *h) {
|
||||
if (!ismarked(h)) {
|
||||
h->mark = st->tmark; /* chain it for later traversal */
|
||||
st->tmark = h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void markclosure (GCState *st, Closure *cl) {
|
||||
if (!cl->c.marked) {
|
||||
cl->c.marked = 1;
|
||||
if (cl->c.isC) {
|
||||
int i;
|
||||
for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
|
||||
markobject(st, &cl->c.upvalue[i]);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
lua_assert(cl->l.nupvalues == cl->l.p->nupvalues);
|
||||
marktable(st, hvalue(&cl->l.g));
|
||||
protomark(cl->l.p);
|
||||
for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
|
||||
UpVal *u = cl->l.upvals[i];
|
||||
if (!isupvalmarked(u)) {
|
||||
markobject(st, &u->value);
|
||||
u->v = NULL; /* mark it! */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void markudata (GCState *st, Udata *u) {
|
||||
markud(u);
|
||||
marktable(st, u->uv.metatable);
|
||||
}
|
||||
|
||||
|
||||
static void reallymarkobject (GCState *st, TObject *o) {
|
||||
switch (ttype(o)) {
|
||||
case LUA_TSTRING:
|
||||
strmark(tsvalue(o));
|
||||
static void reallymarkobject (GCState *st, GCObject *o) {
|
||||
lua_assert(!ismarked(o));
|
||||
setbit(o->gch.marked, 0); /* mark object */
|
||||
switch (o->gch.tt) {
|
||||
case LUA_TUSERDATA: {
|
||||
markvalue(st, gcotou(o)->uv.metatable);
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
if (!isudmarked(uvalue(o)))
|
||||
markudata(st, uvalue(o));
|
||||
break;
|
||||
case LUA_TFUNCTION:
|
||||
markclosure(st, clvalue(o));
|
||||
}
|
||||
case LUA_TFUNCTION: {
|
||||
gcotocl(o)->c.gclist = st->tmark;
|
||||
st->tmark = o;
|
||||
break;
|
||||
}
|
||||
case LUA_TTABLE: {
|
||||
marktable(st, hvalue(o));
|
||||
gcotoh(o)->gclist = st->tmark;
|
||||
st->tmark = o;
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0); /* should not be called with other types */
|
||||
case LUA_TTHREAD: {
|
||||
gcototh(o)->gclist = st->tmark;
|
||||
st->tmark = o;
|
||||
break;
|
||||
}
|
||||
case LUA_TPROTO: {
|
||||
gcotop(o)->gclist = st->tmark;
|
||||
st->tmark = o;
|
||||
break;
|
||||
}
|
||||
default: lua_assert(o->gch.tt == LUA_TSTRING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void checkstacksizes (lua_State *L, StkId max) {
|
||||
int used = L->ci - L->base_ci; /* number of `ci' in use */
|
||||
if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
|
||||
luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
|
||||
used = max - L->stack; /* part of stack in use */
|
||||
if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
|
||||
luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
|
||||
}
|
||||
|
||||
|
||||
static void markstacks (GCState *st) {
|
||||
lua_State *L1 = st->L;
|
||||
do { /* for each thread */
|
||||
StkId o, lim;
|
||||
CallInfo *ci;
|
||||
if (ttisnil(defaultmeta(L1))) { /* incomplete state? */
|
||||
lua_assert(L1 != st->L);
|
||||
L1 = L1->next;
|
||||
luaE_closethread(st->L, L1->previous); /* collect it */
|
||||
continue;
|
||||
}
|
||||
markobject(st, defaultmeta(L1));
|
||||
markobject(st, gt(L1));
|
||||
markobject(st, registry(L1));
|
||||
for (o=L1->stack; o<L1->top; o++)
|
||||
markobject(st, o);
|
||||
lim = o;
|
||||
for (ci = L1->base_ci; ci <= L1->ci; ci++) {
|
||||
lua_assert(ci->top <= L1->stack_last);
|
||||
if (lim < ci->top) lim = ci->top;
|
||||
}
|
||||
for (; o<=lim; o++) setnilvalue(o);
|
||||
checkstacksizes(L1, lim);
|
||||
lua_assert(L1->previous->next == L1 && L1->next->previous == L1);
|
||||
L1 = L1->next;
|
||||
} while (L1 != st->L);
|
||||
}
|
||||
|
||||
|
||||
static void marktmu (GCState *st) {
|
||||
Udata *u;
|
||||
for (u = G(st->L)->tmudata; u; u = u->uv.next)
|
||||
markudata(st, u);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* move `dead' udata that need finalization to list `tmudata' */
|
||||
static void separateudata (lua_State *L) {
|
||||
Udata **p = &G(L)->rootudata;
|
||||
Udata *curr;
|
||||
Udata *collected = NULL; /* to collect udata with gc event */
|
||||
Udata **lastcollected = &collected;
|
||||
GCObject **p = &G(L)->rootudata;
|
||||
GCObject *curr;
|
||||
GCObject *collected = NULL; /* to collect udata with gc event */
|
||||
GCObject **lastcollected = &collected;
|
||||
while ((curr = *p) != NULL) {
|
||||
if (isudmarked(curr) || isfinalized(curr) ||
|
||||
(fasttm(L, curr->uv.metatable, TM_GC) == NULL))
|
||||
p = &curr->uv.next;
|
||||
lua_assert(curr->gch.tt == LUA_TUSERDATA);
|
||||
if (ismarked(curr) || isfinalized(gcotou(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 */
|
||||
p = &curr->gch.next;
|
||||
}
|
||||
else { /* must call its gc method */
|
||||
*p = curr->uv.next;
|
||||
curr->uv.next = NULL; /* link `curr' at the end of `collected' list */
|
||||
*p = curr->gch.next;
|
||||
curr->gch.next = NULL; /* link `curr' at the end of `collected' list */
|
||||
*lastcollected = curr;
|
||||
lastcollected = &curr->uv.next;
|
||||
lastcollected = &curr->gch.next;
|
||||
}
|
||||
}
|
||||
/* insert collected udata with gc event into `tmudata' list */
|
||||
@@ -208,7 +139,7 @@ static void separateudata (lua_State *L) {
|
||||
|
||||
static void removekey (Node *n) {
|
||||
setnilvalue(val(n)); /* remove corresponding value ... */
|
||||
if (ismarkable(key(n)))
|
||||
if (iscollectable(key(n)))
|
||||
setttype(key(n), LUA_TNONE); /* dead key; remove it */
|
||||
}
|
||||
|
||||
@@ -217,13 +148,23 @@ static void traversetable (GCState *st, Table *h) {
|
||||
int i;
|
||||
int weakkey = 0;
|
||||
int weakvalue = 0;
|
||||
marktable(st, h->metatable);
|
||||
lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
|
||||
if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */
|
||||
weakkey = h->mode & WEAKKEY;
|
||||
weakvalue = h->mode & WEAKVALUE;
|
||||
h->mark = st->toclear; /* must be cleared after GC, ... */
|
||||
st->toclear = h; /* ... so put in the appropriate list */
|
||||
const TObject *mode;
|
||||
markvalue(st, h->metatable);
|
||||
lua_assert(h->lsizenode || h->node == st->G->dummynode);
|
||||
mode = gfasttm(st->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 |= (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 */
|
||||
}
|
||||
}
|
||||
if (!weakvalue) {
|
||||
i = sizearray(h);
|
||||
@@ -235,54 +176,136 @@ static void traversetable (GCState *st, Table *h) {
|
||||
Node *n = node(h, i);
|
||||
if (!ttisnil(val(n))) {
|
||||
lua_assert(!ttisnil(key(n)));
|
||||
if (!weakkey) markobject(st, key(n));
|
||||
if (!weakvalue) markobject(st, val(n));
|
||||
condmarkobject(st, key(n), !weakkey);
|
||||
condmarkobject(st, val(n), !weakvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void propagatemarks (GCState *st) {
|
||||
while (st->tmark) { /* traverse marked tables */
|
||||
Table *h = st->tmark; /* get first table from list */
|
||||
st->tmark = h->mark; /* remove it from list */
|
||||
traversetable(st, h);
|
||||
static void traverseproto (GCState *st, Proto *f) {
|
||||
int i;
|
||||
stringmark(f->source);
|
||||
for (i=0; i<f->sizek; i++) {
|
||||
if (ttisstring(f->k+i))
|
||||
stringmark(tsvalue(f->k+i));
|
||||
}
|
||||
for (i=0; i<f->sizep; i++)
|
||||
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) {
|
||||
if (cl->c.isC) {
|
||||
int i;
|
||||
for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
|
||||
markobject(st, &cl->c.upvalue[i]);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
lua_assert(cl->l.nupvalues == cl->l.p->nupvalues);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int hasmark (const TObject *o) {
|
||||
switch (ttype(o)) {
|
||||
case LUA_TUSERDATA:
|
||||
return isudmarked(uvalue(o));
|
||||
case LUA_TTABLE:
|
||||
return ismarked(hvalue(o));
|
||||
case LUA_TFUNCTION:
|
||||
return clvalue(o)->c.marked;
|
||||
case LUA_TSTRING:
|
||||
strmark(tsvalue(o)); /* strings are `values', so are never weak */
|
||||
/* go through */
|
||||
default: /* number, nil, boolean, udataval */
|
||||
return 1;
|
||||
static void checkstacksizes (lua_State *L, StkId max) {
|
||||
int used = L->ci - L->base_ci; /* number of `ci' in use */
|
||||
if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
|
||||
luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
|
||||
else condhardstacktests(luaD_reallocCI(L, L->size_ci));
|
||||
used = max - L->stack; /* part of stack in use */
|
||||
if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
|
||||
luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
|
||||
else condhardstacktests(luaD_reallocstack(L, L->stacksize));
|
||||
}
|
||||
|
||||
|
||||
static void traversestack (GCState *st, lua_State *L1) {
|
||||
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 (!(ci->state & CI_C) && lim < ci->top)
|
||||
lim = ci->top;
|
||||
}
|
||||
for (o = L1->stack; o < L1->top; o++)
|
||||
markobject(st, o);
|
||||
for (; o <= lim; o++)
|
||||
setnilvalue(o);
|
||||
checkstacksizes(L1, lim);
|
||||
}
|
||||
|
||||
|
||||
static void propagatemarks (GCState *st) {
|
||||
while (st->tmark) { /* traverse marked objects */
|
||||
switch (st->tmark->gch.tt) {
|
||||
case LUA_TTABLE: {
|
||||
Table *h = gcotoh(st->tmark);
|
||||
st->tmark = h->gclist;
|
||||
traversetable(st, h);
|
||||
break;
|
||||
}
|
||||
case LUA_TFUNCTION: {
|
||||
Closure *cl = gcotocl(st->tmark);
|
||||
st->tmark = cl->c.gclist;
|
||||
traverseclosure(st, cl);
|
||||
break;
|
||||
}
|
||||
case LUA_TTHREAD: {
|
||||
lua_State *th = gcototh(st->tmark);
|
||||
st->tmark = th->gclist;
|
||||
traversestack(st, th);
|
||||
break;
|
||||
}
|
||||
case LUA_TPROTO: {
|
||||
Proto *p = gcotop(st->tmark);
|
||||
st->tmark = p->gclist;
|
||||
traverseproto(st, p);
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** clear collected keys from weaktables
|
||||
*/
|
||||
static void cleartablekeys (GCState *st) {
|
||||
Table *h;
|
||||
for (h = st->toclear; h; h = h->mark) {
|
||||
lua_assert(h->mode & (WEAKKEY | WEAKVALUE));
|
||||
if ((h->mode & WEAKKEY)) { /* table may have collected keys? */
|
||||
int i = sizenode(h);
|
||||
while (i--) {
|
||||
Node *n = node(h, i);
|
||||
if (!hasmark(key(n))) /* key was collected? */
|
||||
removekey(n); /* remove entry from table */
|
||||
}
|
||||
static void cleartablekeys (GCObject *l) {
|
||||
while (l) {
|
||||
Table *h = gcotoh(l);
|
||||
int i = sizenode(h);
|
||||
lua_assert(h->marked & KEYWEAK);
|
||||
while (i--) {
|
||||
Node *n = node(h, i);
|
||||
if (!valismarked(key(n))) /* key was collected? */
|
||||
removekey(n); /* remove entry from table */
|
||||
}
|
||||
l = h->gclist;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,148 +313,95 @@ static void cleartablekeys (GCState *st) {
|
||||
/*
|
||||
** clear collected values from weaktables
|
||||
*/
|
||||
static void cleartablevalues (GCState *st) {
|
||||
Table *h;
|
||||
for (h = st->toclear; h; h = h->mark) {
|
||||
if ((h->mode & WEAKVALUE)) { /* table may have collected values? */
|
||||
int i = sizearray(h);
|
||||
while (i--) {
|
||||
TObject *o = &h->array[i];
|
||||
if (!hasmark(o)) /* value was collected? */
|
||||
setnilvalue(o); /* remove value */
|
||||
}
|
||||
i = sizenode(h);
|
||||
while (i--) {
|
||||
Node *n = node(h, i);
|
||||
if (!hasmark(val(n))) /* value was collected? */
|
||||
removekey(n); /* remove entry from table */
|
||||
}
|
||||
static void cleartablevalues (GCObject *l) {
|
||||
while (l) {
|
||||
Table *h = gcotoh(l);
|
||||
int i = sizearray(h);
|
||||
lua_assert(h->marked & VALUEWEAK);
|
||||
while (i--) {
|
||||
TObject *o = &h->array[i];
|
||||
if (!valismarked(o)) /* value was collected? */
|
||||
setnilvalue(o); /* remove value */
|
||||
}
|
||||
i = sizenode(h);
|
||||
while (i--) {
|
||||
Node *n = node(h, i);
|
||||
if (!valismarked(val(n))) /* value was collected? */
|
||||
removekey(n); /* remove entry from table */
|
||||
}
|
||||
l = h->gclist;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void collectproto (lua_State *L) {
|
||||
Proto **p = &G(L)->rootproto;
|
||||
Proto *curr;
|
||||
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_TTHREAD: {
|
||||
lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread);
|
||||
luaE_freethread(L, gcototh(o));
|
||||
break;
|
||||
}
|
||||
case LUA_TSTRING: {
|
||||
luaM_free(L, o, sizestring(gcotots(o)->tsv.len));
|
||||
break;
|
||||
}
|
||||
case LUA_TUSERDATA: {
|
||||
luaM_free(L, o, sizeudata(gcotou(o)->uv.len));
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int sweeplist (lua_State *L, GCObject **p, int limit) {
|
||||
GCObject *curr;
|
||||
int count = 0; /* number of collected items */
|
||||
while ((curr = *p) != NULL) {
|
||||
if (curr->marked) {
|
||||
curr->marked = 0;
|
||||
p = &curr->next;
|
||||
if (curr->gch.marked > limit) {
|
||||
unmark(curr);
|
||||
p = &curr->gch.next;
|
||||
}
|
||||
else {
|
||||
*p = curr->next;
|
||||
luaF_freeproto(L, curr);
|
||||
count++;
|
||||
*p = curr->gch.next;
|
||||
freeobj(L, curr);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static void collectclosures (lua_State *L) {
|
||||
Closure **p = &G(L)->rootcl;
|
||||
Closure *curr;
|
||||
while ((curr = *p) != NULL) {
|
||||
if (curr->c.marked) {
|
||||
curr->c.marked = 0;
|
||||
p = &curr->c.next;
|
||||
}
|
||||
else {
|
||||
*p = curr->c.next;
|
||||
luaF_freeclosure(L, curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void collectupval (lua_State *L) {
|
||||
UpVal **v = &G(L)->rootupval;
|
||||
UpVal *curr;
|
||||
while ((curr = *v) != NULL) {
|
||||
if (isupvalmarked(curr)) {
|
||||
lua_assert(curr->v == NULL);
|
||||
curr->v = &curr->value; /* unmark */
|
||||
v = &curr->next; /* next */
|
||||
}
|
||||
else {
|
||||
*v = curr->next; /* next */
|
||||
luaM_freelem(L, curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void collecttable (lua_State *L) {
|
||||
Table **p = &G(L)->roottable;
|
||||
Table *curr;
|
||||
while ((curr = *p) != NULL) {
|
||||
if (ismarked(curr)) {
|
||||
curr->mark = curr; /* unmark */
|
||||
p = &curr->next;
|
||||
}
|
||||
else {
|
||||
*p = curr->next;
|
||||
luaH_free(L, curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void collectudata (lua_State *L) {
|
||||
Udata **p = &G(L)->rootudata;
|
||||
Udata *curr;
|
||||
while ((curr = *p) != NULL) {
|
||||
if (isudmarked(curr)) {
|
||||
unmarkud(curr);
|
||||
p = &curr->uv.next;
|
||||
}
|
||||
else {
|
||||
*p = curr->uv.next;
|
||||
luaM_free(L, curr, sizeudata(curr->uv.len & (~(size_t)3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void collectstrings (lua_State *L, int all) {
|
||||
static void sweepstrings (lua_State *L, int all) {
|
||||
int i;
|
||||
for (i=0; i<G(L)->strt.size; i++) { /* for each list */
|
||||
TString **p = &G(L)->strt.hash[i];
|
||||
TString *curr;
|
||||
while ((curr = *p) != NULL) {
|
||||
if (curr->tsv.marked && !all) { /* preserve? */
|
||||
if (curr->tsv.marked < FIXMARK) /* does not change FIXMARKs */
|
||||
curr->tsv.marked = 0;
|
||||
p = &curr->tsv.nexthash;
|
||||
}
|
||||
else { /* collect */
|
||||
*p = curr->tsv.nexthash;
|
||||
G(L)->strt.nuse--;
|
||||
luaM_free(L, curr, sizestring(curr->tsv.len));
|
||||
}
|
||||
}
|
||||
G(L)->strt.nuse -= sweeplist(L, &G(L)->strt.hash[i], all);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void checkSizes (lua_State *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 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define MINBUFFER 256
|
||||
static void checkMbuffer (lua_State *L) {
|
||||
if (G(L)->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */
|
||||
size_t newsize = G(L)->Mbuffsize/2; /* still larger than MINBUFFER */
|
||||
luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, newsize, char);
|
||||
G(L)->Mbuffsize = newsize;
|
||||
/* 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);
|
||||
}
|
||||
G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
|
||||
}
|
||||
|
||||
|
||||
static void do1gcTM (lua_State *L, Udata *udata) {
|
||||
const TObject *tm = fasttm(L, udata->uv.metatable, TM_GC);
|
||||
if (tm != NULL) {
|
||||
setobj(L->top, tm);
|
||||
setobj2s(L->top, tm);
|
||||
setuvalue(L->top+1, udata);
|
||||
L->top += 2;
|
||||
luaD_call(L, L->top - 2, 0);
|
||||
@@ -440,21 +410,22 @@ static void do1gcTM (lua_State *L, Udata *udata) {
|
||||
|
||||
|
||||
static void callGCTM (lua_State *L) {
|
||||
int oldah = allowhook(L);
|
||||
setallowhook(L, 0); /* stop debug hooks during GC tag methods */
|
||||
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) {
|
||||
Udata *udata = G(L)->tmudata;
|
||||
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 = udata;
|
||||
G(L)->rootudata = o;
|
||||
setuvalue(L->top - 1, udata); /* keep a reference to it */
|
||||
unmarkud(udata);
|
||||
unmark(o);
|
||||
markfinalized(udata);
|
||||
do1gcTM(L, udata);
|
||||
}
|
||||
L->top--;
|
||||
setallowhook(L, oldah); /* restore hooks */
|
||||
L->allowhook = oldah; /* restore hooks */
|
||||
}
|
||||
|
||||
|
||||
@@ -464,31 +435,62 @@ void luaC_callallgcTM (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
void luaC_collect (lua_State *L, int all) {
|
||||
collectudata(L);
|
||||
collectstrings(L, all);
|
||||
collecttable(L);
|
||||
collectproto(L);
|
||||
collectupval(L);
|
||||
collectclosures(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);
|
||||
}
|
||||
|
||||
|
||||
/* 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 mark (lua_State *L) {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void luaC_collectgarbage (lua_State *L) {
|
||||
GCState st;
|
||||
st.L = L;
|
||||
st.tmark = NULL;
|
||||
st.toclear = NULL;
|
||||
markstacks(&st); /* mark all stacks */
|
||||
propagatemarks(&st); /* mark all reachable objects */
|
||||
cleartablevalues(&st);
|
||||
separateudata(L); /* separate userdata to be preserved */
|
||||
marktmu(&st); /* mark `preserved' userdata */
|
||||
propagatemarks(&st); /* remark */
|
||||
cleartablekeys(&st);
|
||||
luaC_collect(L, 0);
|
||||
checkMbuffer(L);
|
||||
G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
|
||||
mark(L);
|
||||
luaC_sweep(L, 0);
|
||||
checkSizes(L);
|
||||
callGCTM(L);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
o->gch.tt = tt;
|
||||
}
|
||||
|
||||
|
||||
5
lgc.h
5
lgc.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lgc.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
|
||||
** $Id: lgc.h,v 1.16 2002/08/30 19:09:21 roberto Exp roberto $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -16,8 +16,9 @@
|
||||
|
||||
|
||||
void luaC_callallgcTM (lua_State *L);
|
||||
void luaC_collect (lua_State *L, int all);
|
||||
void luaC_sweep (lua_State *L, int all);
|
||||
void luaC_collectgarbage (lua_State *L);
|
||||
void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
301
liolib.c
301
liolib.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: liolib.c,v 2.14 2002/07/17 16:25:13 roberto Exp roberto $
|
||||
** $Id: liolib.c,v 2.27 2002/12/04 15:27:17 roberto Exp roberto $
|
||||
** Standard I/O (and system) library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define liolib_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
@@ -26,125 +28,175 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef POPEN
|
||||
#ifndef USE_POPEN
|
||||
#define pclose(f) (-1)
|
||||
#endif
|
||||
|
||||
|
||||
#define FILEHANDLE "FileHandle"
|
||||
#define CLOSEDFILEHANDLE "ClosedFileHandle"
|
||||
|
||||
#define IO_INPUT "_input"
|
||||
#define IO_OUTPUT "_output"
|
||||
|
||||
|
||||
static int pushresult (lua_State *L, int i) {
|
||||
static int pushresult (lua_State *L, int i, const char *filename) {
|
||||
if (i) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, strerror(errno));
|
||||
if (filename)
|
||||
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
|
||||
else
|
||||
lua_pushfstring(L, "%s", strerror(errno));
|
||||
lua_pushnumber(L, errno);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static FILE *tofile (lua_State *L, int findex) {
|
||||
static FILE **topfile (lua_State *L, int findex) {
|
||||
FILE **f = (FILE **)lua_touserdata(L, findex);
|
||||
if (f && lua_getmetatable(L, findex) &&
|
||||
lua_rawequal(L, -1, lua_upvalueindex(1))) {
|
||||
lua_pop(L, 1);
|
||||
return *f;
|
||||
}
|
||||
if (findex > 0)
|
||||
if (f == NULL || !lua_getmetatable(L, findex) ||
|
||||
!lua_rawequal(L, -1, lua_upvalueindex(1))) {
|
||||
luaL_argerror(L, findex, "bad file");
|
||||
return NULL;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
static void newfile (lua_State *L, FILE *f) {
|
||||
lua_boxpointer(L, f);
|
||||
static int io_type (lua_State *L) {
|
||||
FILE **f = (FILE **)lua_touserdata(L, 1);
|
||||
if (f == NULL || !lua_getmetatable(L, 1) ||
|
||||
!lua_rawequal(L, -1, lua_upvalueindex(1)))
|
||||
lua_pushnil(L);
|
||||
else if (*f == NULL)
|
||||
lua_pushliteral(L, "closed file");
|
||||
else
|
||||
lua_pushliteral(L, "file");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static FILE *tofile (lua_State *L, int findex) {
|
||||
FILE **f = topfile(L, findex);
|
||||
if (*f == NULL)
|
||||
luaL_error(L, "attempt to use a closed file");
|
||||
return *f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** When creating file handles, always creates a `closed' file handle
|
||||
** before opening the actual file; so, if there is a memory error, the
|
||||
** file is not left opened.
|
||||
*/
|
||||
static FILE **newfile (lua_State *L) {
|
||||
FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
|
||||
*pf = NULL; /* file handle is currently `closed' */
|
||||
lua_pushliteral(L, FILEHANDLE);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
return pf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 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);
|
||||
*newfile(L) = f;
|
||||
if (impname) {
|
||||
lua_pushstring(L, impname);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, -6);
|
||||
lua_settable(L, -6); /* metatable[impname] = file */
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
lua_settable(L, -3); /* io[name] = file */
|
||||
}
|
||||
|
||||
|
||||
static int setnewfile (lua_State *L, FILE *f) {
|
||||
if (f == NULL)
|
||||
return pushresult(L, 0);
|
||||
static int aux_close (lua_State *L) {
|
||||
FILE *f = tofile(L, 1);
|
||||
if (f == stdin || f == stdout || f == stderr)
|
||||
return 0; /* file cannot be closed */
|
||||
else {
|
||||
newfile(L, f);
|
||||
return 1;
|
||||
int ok = (pclose(f) != -1) || (fclose(f) == 0);
|
||||
if (ok)
|
||||
*(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int io_close (lua_State *L) {
|
||||
FILE *f;
|
||||
int status = 1;
|
||||
if (lua_isnone(L, 1)) {
|
||||
lua_pushstring(L, IO_OUTPUT);
|
||||
lua_rawget(L, lua_upvalueindex(1));
|
||||
}
|
||||
f = tofile(L, 1);
|
||||
if (f != stdin && f != stdout && f != stderr) {
|
||||
lua_settop(L, 1); /* make sure file is on top */
|
||||
lua_pushliteral(L, CLOSEDFILEHANDLE);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, 1);
|
||||
status = (pclose(f) != -1) || (fclose(f) == 0);
|
||||
}
|
||||
return pushresult(L, status);
|
||||
return pushresult(L, aux_close(L), NULL);
|
||||
}
|
||||
|
||||
|
||||
static int io_gc (lua_State *L) {
|
||||
FILE **f = topfile(L, 1);
|
||||
if (*f != NULL) /* ignore closed files */
|
||||
aux_close(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int io_tostring (lua_State *L) {
|
||||
char buff[32];
|
||||
FILE **f = topfile(L, 1);
|
||||
if (*f == NULL)
|
||||
strcpy(buff, "closed");
|
||||
else
|
||||
sprintf(buff, "%p", lua_touserdata(L, 1));
|
||||
lua_pushfstring(L, "file (%s)", buff);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_open (lua_State *L) {
|
||||
FILE *f = fopen(luaL_check_string(L, 1), luaL_opt_string(L, 2, "r"));
|
||||
return setnewfile(L, f);
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
FILE **pf = newfile(L);
|
||||
*pf = fopen(filename, mode);
|
||||
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_popen (lua_State *L) {
|
||||
#ifndef POPEN
|
||||
#ifndef USE_POPEN
|
||||
luaL_error(L, "`popen' not supported");
|
||||
return 0;
|
||||
#else
|
||||
FILE *f = popen(luaL_check_string(L, 1), luaL_opt_string(L, 2, "r"));
|
||||
return setnewfile(L, f);
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
FILE **pf = newfile(L);
|
||||
*pf = popen(filename, mode);
|
||||
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int io_tmpfile (lua_State *L) {
|
||||
return setnewfile(L, tmpfile());
|
||||
FILE **pf = newfile(L);
|
||||
*pf = tmpfile();
|
||||
return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
|
||||
}
|
||||
|
||||
|
||||
static FILE *getiofile (lua_State *L, const char *name) {
|
||||
FILE *f;
|
||||
lua_pushstring(L, name);
|
||||
lua_rawget(L, lua_upvalueindex(1));
|
||||
f = tofile(L, -1);
|
||||
if (f == NULL)
|
||||
luaL_error(L, "%s is closed", name);
|
||||
return f;
|
||||
return tofile(L, -1);
|
||||
}
|
||||
|
||||
|
||||
@@ -158,9 +210,12 @@ static int g_iofile (lua_State *L, const char *name, const char *mode) {
|
||||
const char *filename = lua_tostring(L, 1);
|
||||
lua_pushstring(L, name);
|
||||
if (filename) {
|
||||
FILE *f = fopen(filename, mode);
|
||||
luaL_arg_check(L, f, 1, strerror(errno));
|
||||
newfile(L, f);
|
||||
FILE **pf = newfile(L);
|
||||
*pf = fopen(filename, mode);
|
||||
if (*pf == NULL) {
|
||||
lua_pushfstring(L, "%s: %s", filename, strerror(errno));
|
||||
luaL_argerror(L, 1, lua_tostring(L, -1));
|
||||
}
|
||||
}
|
||||
else {
|
||||
tofile(L, 1); /* check that it's a valid file handle */
|
||||
@@ -182,6 +237,42 @@ static int io_output (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int io_readline (lua_State *L);
|
||||
|
||||
|
||||
static void aux_lines (lua_State *L, int index, int close) {
|
||||
lua_pushliteral(L, FILEHANDLE);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(L, index);
|
||||
lua_pushboolean(L, close); /* close/not close file when finished */
|
||||
lua_pushcclosure(L, io_readline, 3);
|
||||
}
|
||||
|
||||
|
||||
static int f_lines (lua_State *L) {
|
||||
tofile(L, 1); /* check that it's a valid file handle */
|
||||
aux_lines(L, 1, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
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 */
|
||||
return f_lines(L);
|
||||
}
|
||||
else {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
FILE **pf = newfile(L);
|
||||
*pf = fopen(filename, "r");
|
||||
luaL_argcheck(L, *pf, 1, strerror(errno));
|
||||
aux_lines(L, lua_gettop(L), 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** READ
|
||||
@@ -256,7 +347,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
|
||||
n = first+1; /* to return 1 result */
|
||||
}
|
||||
else { /* ensure stack space for all results and for auxlib's buffer */
|
||||
luaL_check_stack(L, nargs+LUA_MINSTACK, "too many arguments");
|
||||
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
|
||||
success = 1;
|
||||
for (n = first; nargs-- && success; n++) {
|
||||
if (lua_type(L, n) == LUA_TNUMBER) {
|
||||
@@ -303,6 +394,22 @@ static int f_read (lua_State *L) {
|
||||
return g_read(L, tofile(L, 1), 2);
|
||||
}
|
||||
|
||||
|
||||
static int io_readline (lua_State *L) {
|
||||
FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2));
|
||||
if (f == NULL) /* file is already closed? */
|
||||
luaL_error(L, "file is already closed");
|
||||
if (read_line(L, f)) return 1;
|
||||
else { /* EOF */
|
||||
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
|
||||
lua_settop(L, 0);
|
||||
lua_pushvalue(L, lua_upvalueindex(2));
|
||||
aux_close(L); /* close it */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
@@ -317,12 +424,11 @@ static int g_write (lua_State *L, FILE *f, int arg) {
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = luaL_check_lstr(L, arg, &l);
|
||||
const char *s = luaL_checklstring(L, arg, &l);
|
||||
status = status && (fwrite(s, sizeof(char), l, f) == l);
|
||||
}
|
||||
}
|
||||
pushresult(L, status);
|
||||
return 1;
|
||||
return pushresult(L, status, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -340,12 +446,12 @@ static int f_seek (lua_State *L) {
|
||||
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
|
||||
static const char *const modenames[] = {"set", "cur", "end", NULL};
|
||||
FILE *f = tofile(L, 1);
|
||||
int op = luaL_findstring(luaL_opt_string(L, 2, "cur"), modenames);
|
||||
long offset = luaL_opt_long(L, 3, 0);
|
||||
luaL_arg_check(L, op != -1, 2, "invalid mode");
|
||||
int op = luaL_findstring(luaL_optstring(L, 2, "cur"), modenames);
|
||||
long offset = luaL_optlong(L, 3, 0);
|
||||
luaL_argcheck(L, op != -1, 2, "invalid mode");
|
||||
op = fseek(f, offset, mode[op]);
|
||||
if (op)
|
||||
return pushresult(L, 0); /* error */
|
||||
return pushresult(L, 0, NULL); /* error */
|
||||
else {
|
||||
lua_pushnumber(L, ftell(f));
|
||||
return 1;
|
||||
@@ -354,24 +460,26 @@ static int f_seek (lua_State *L) {
|
||||
|
||||
|
||||
static int io_flush (lua_State *L) {
|
||||
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0);
|
||||
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int f_flush (lua_State *L) {
|
||||
return pushresult(L, fflush(tofile(L, 1)) == 0);
|
||||
return pushresult(L, fflush(tofile(L, 1)) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static const luaL_reg iolib[] = {
|
||||
{"input", io_input},
|
||||
{"output", io_output},
|
||||
{"lines", io_lines},
|
||||
{"close", io_close},
|
||||
{"flush", io_flush},
|
||||
{"open", io_open},
|
||||
{"popen", io_popen},
|
||||
{"read", io_read},
|
||||
{"tmpfile", io_tmpfile},
|
||||
{"type", io_type},
|
||||
{"write", io_write},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -380,6 +488,7 @@ static const luaL_reg iolib[] = {
|
||||
static const luaL_reg flib[] = {
|
||||
{"flush", f_flush},
|
||||
{"read", f_read},
|
||||
{"lines", f_lines},
|
||||
{"seek", f_seek},
|
||||
{"write", f_write},
|
||||
{"close", io_close},
|
||||
@@ -388,25 +497,24 @@ static const luaL_reg flib[] = {
|
||||
|
||||
|
||||
static void createmeta (lua_State *L) {
|
||||
lua_pushliteral(L, FILEHANDLE); /* S: FH */
|
||||
lua_newtable(L); /* S: mt FH */
|
||||
lua_pushliteral(L, FILEHANDLE);
|
||||
lua_newtable(L); /* push new metatable for file handles */
|
||||
/* close files when collected */
|
||||
lua_pushliteral(L, "__gc"); /* S: `gc' mt FH */
|
||||
lua_pushvalue(L, -2); /* S: mt `gc' mt FH */
|
||||
lua_pushcclosure(L, io_close, 1); /* S: close `gc' mt FH */
|
||||
lua_rawset(L, -3); /* S: mt FH */
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushvalue(L, -2); /* push metatable (will be upvalue for `gc' method) */
|
||||
lua_pushcclosure(L, io_gc, 1);
|
||||
lua_rawset(L, -3); /* metatable.__gc = io_gc */
|
||||
lua_pushliteral(L, "__tostring");
|
||||
lua_pushvalue(L, -2); /* push metatable */
|
||||
lua_pushcclosure(L, io_tostring, 1);
|
||||
lua_rawset(L, -3);
|
||||
/* file methods */
|
||||
lua_pushliteral(L, "__gettable"); /* S: `gettable' mt FH */
|
||||
lua_pushvalue(L, -2); /* S: mt `gettable' mt FH */
|
||||
lua_rawset(L, -3); /* S: mt FH */
|
||||
lua_pushvalue(L, -1); /* S: mt mt FH */
|
||||
luaL_openlib(L, flib, 1); /* S: mt FH */
|
||||
/* put new metatable into registry */
|
||||
lua_rawset(L, LUA_REGISTRYINDEX); /* S: empty */
|
||||
/* meta table for CLOSEDFILEHANDLE */
|
||||
lua_pushliteral(L, CLOSEDFILEHANDLE);
|
||||
lua_newtable(L);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, -2); /* push metatable */
|
||||
lua_rawset(L, -3); /* metatable.__index = metatable */
|
||||
lua_pushvalue(L, -1); /* push metatable (will be upvalue for library) */
|
||||
luaL_openlib(L, NULL, flib, 1);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX); /* registry.FILEHANDLE = metatable */
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
@@ -419,19 +527,21 @@ static void createmeta (lua_State *L) {
|
||||
*/
|
||||
|
||||
static int io_execute (lua_State *L) {
|
||||
lua_pushnumber(L, system(luaL_check_string(L, 1)));
|
||||
lua_pushnumber(L, system(luaL_checkstring(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_remove (lua_State *L) {
|
||||
return pushresult(L, remove(luaL_check_string(L, 1)) == 0);
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
return pushresult(L, remove(filename) == 0, filename);
|
||||
}
|
||||
|
||||
|
||||
static int io_rename (lua_State *L) {
|
||||
return pushresult(L, rename(luaL_check_string(L, 1),
|
||||
luaL_check_string(L, 2)) == 0);
|
||||
const char *fromname = luaL_checkstring(L, 1);
|
||||
const char *toname = luaL_checkstring(L, 2);
|
||||
return pushresult(L, rename(fromname, toname) == 0, fromname);
|
||||
}
|
||||
|
||||
|
||||
@@ -445,7 +555,7 @@ static int io_tmpname (lua_State *L) {
|
||||
|
||||
|
||||
static int io_getenv (lua_State *L) {
|
||||
lua_pushstring(L, getenv(luaL_check_string(L, 1))); /* if NULL push nil */
|
||||
lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -503,8 +613,8 @@ static int getfield (lua_State *L, const char *key, int d) {
|
||||
|
||||
|
||||
static int io_date (lua_State *L) {
|
||||
const char *s = luaL_opt_string(L, 1, "%c");
|
||||
time_t t = (time_t)(luaL_opt_number(L, 2, -1));
|
||||
const char *s = luaL_optstring(L, 1, "%c");
|
||||
time_t t = (time_t)(luaL_optnumber(L, 2, -1));
|
||||
struct tm *stm;
|
||||
if (t == (time_t)(-1)) /* no time given? */
|
||||
t = time(NULL); /* use current time */
|
||||
@@ -545,7 +655,7 @@ static int io_time (lua_State *L) {
|
||||
else {
|
||||
time_t t;
|
||||
struct tm ts;
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_settop(L, 1); /* make sure table is at the top */
|
||||
ts.tm_sec = getfield(L, "sec", 0);
|
||||
ts.tm_min = getfield(L, "min", 0);
|
||||
@@ -565,8 +675,8 @@ static int io_time (lua_State *L) {
|
||||
|
||||
|
||||
static int io_difftime (lua_State *L) {
|
||||
lua_pushnumber(L, difftime((time_t)(luaL_check_number(L, 1)),
|
||||
(time_t)(luaL_opt_number(L, 2, 0))));
|
||||
lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
|
||||
(time_t)(luaL_optnumber(L, 2, 0))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -579,16 +689,16 @@ static int io_setloc (lua_State *L) {
|
||||
static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
|
||||
"numeric", "time", NULL};
|
||||
const char *l = lua_tostring(L, 1);
|
||||
int op = luaL_findstring(luaL_opt_string(L, 2, "all"), catnames);
|
||||
luaL_arg_check(L, l || lua_isnoneornil(L, 1), 1, "string expected");
|
||||
luaL_arg_check(L, op != -1, 2, "invalid option");
|
||||
int op = luaL_findstring(luaL_optstring(L, 2, "all"), catnames);
|
||||
luaL_argcheck(L, l || lua_isnoneornil(L, 1), 1, "string expected");
|
||||
luaL_argcheck(L, op != -1, 2, "invalid option");
|
||||
lua_pushstring(L, setlocale(cat[op], l));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_exit (lua_State *L) {
|
||||
exit(luaL_opt_int(L, 1, EXIT_SUCCESS));
|
||||
exit(luaL_optint(L, 1, EXIT_SUCCESS));
|
||||
return 0; /* to avoid warnings */
|
||||
}
|
||||
|
||||
@@ -613,18 +723,15 @@ static const luaL_reg syslib[] = {
|
||||
|
||||
LUALIB_API int lua_iolibopen (lua_State *L) {
|
||||
createmeta(L);
|
||||
luaL_opennamedlib(L, LUA_OSLIBNAME, syslib, 0);
|
||||
lua_pushliteral(L, FILEHANDLE); /* S: FH */
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); /* S: mt */
|
||||
lua_pushvalue(L, -1); /* S: mt mt */
|
||||
luaL_opennamedlib(L, LUA_IOLIBNAME, iolib, 1); /* S: mt */
|
||||
lua_pushliteral(L, LUA_IOLIBNAME); /* S: `io' mt */
|
||||
lua_gettable(L, LUA_GLOBALSINDEX); /* S: io mt */
|
||||
luaL_openlib(L, LUA_OSLIBNAME, syslib, 0);
|
||||
lua_pushliteral(L, FILEHANDLE);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
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_pop(L, 2); /* S: empty */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
155
llex.c
155
llex.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: llex.c,v 1.107 2002/07/08 18:14:36 roberto Exp roberto $
|
||||
** $Id: llex.c,v 1.116 2002/10/23 19:08:13 roberto Exp roberto $
|
||||
** Lexical Analyzer
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#define llex_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldo.h"
|
||||
@@ -27,7 +29,7 @@
|
||||
/* ORDER RESERVED */
|
||||
static const char *const token2string [] = {
|
||||
"and", "break", "do", "else", "elseif",
|
||||
"end", "false", "for", "function", "global", "if",
|
||||
"end", "false", "for", "function", "if",
|
||||
"in", "local", "nil", "not", "or", "repeat",
|
||||
"return", "then", "true", "until", "while", "*name",
|
||||
"..", "...", "==", ">=", "<=", "~=",
|
||||
@@ -39,8 +41,9 @@ void luaX_init (lua_State *L) {
|
||||
int i;
|
||||
for (i=0; i<NUM_RESERVED; i++) {
|
||||
TString *ts = luaS_new(L, token2string[i]);
|
||||
luaS_fix(ts); /* reserved words are never collected */
|
||||
lua_assert(strlen(token2string[i])+1 <= TOKEN_LEN);
|
||||
ts->tsv.marked = cast(unsigned short, RESERVEDMARK+i); /* reserved word */
|
||||
ts->tsv.reserved = cast(lu_byte, i+1); /* reserved word */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +63,7 @@ static void luaX_error (LexState *ls, const char *s, const char *token) {
|
||||
lua_State *L = ls->L;
|
||||
char buff[MAXSRC];
|
||||
luaO_chunkid(buff, getstr(ls->source), MAXSRC);
|
||||
luaO_pushfstring(L, "%s:%d: %s near `%s'\n", buff, ls->linenumber, s, token);
|
||||
luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, ls->linenumber, s, token);
|
||||
luaD_throw(L, LUA_ERRSYNTAX);
|
||||
}
|
||||
|
||||
@@ -69,13 +72,11 @@ void luaX_syntaxerror (LexState *ls, const char *msg) {
|
||||
const char *lasttoken;
|
||||
switch (ls->t.token) {
|
||||
case TK_NAME:
|
||||
lasttoken = luaO_pushfstring(ls->L, "%s", getstr(ls->t.seminfo.ts));
|
||||
lasttoken = getstr(ls->t.seminfo.ts);
|
||||
break;
|
||||
case TK_STRING:
|
||||
lasttoken = luaO_pushfstring(ls->L, "\"%s\"", getstr(ls->t.seminfo.ts));
|
||||
break;
|
||||
case TK_NUMBER:
|
||||
lasttoken = luaO_pushfstring(ls->L, "%f", ls->t.seminfo.r);
|
||||
lasttoken = luaZ_buffer(ls->buff);
|
||||
break;
|
||||
default:
|
||||
lasttoken = luaX_token2str(ls, ls->t.token);
|
||||
@@ -99,7 +100,7 @@ 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, cast(char *, G(ls->L)->Mbuffer));
|
||||
luaX_error(ls, s, luaZ_buffer(ls->buff));
|
||||
}
|
||||
|
||||
|
||||
@@ -135,148 +136,150 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
|
||||
*/
|
||||
|
||||
|
||||
/* use Mbuffer to store names, literal strings and numbers */
|
||||
/* use buffer to store names, literal strings and numbers */
|
||||
|
||||
#define EXTRABUFF 128
|
||||
#define checkbuffer(L, len) \
|
||||
if (((len)+10)*sizeof(char) > G(L)->Mbuffsize) \
|
||||
luaO_openspace(L, (len)+EXTRABUFF, char)
|
||||
/* extra space to allocate when growing buffer */
|
||||
#define EXTRABUFF 32
|
||||
|
||||
#define save(L, c, l) (cast(char *, G(L)->Mbuffer)[l++] = cast(char, c))
|
||||
#define save_and_next(L, LS, l) (save(L, LS->current, l), next(LS))
|
||||
/* 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) {
|
||||
lua_State *L = LS->L;
|
||||
size_t l = 0;
|
||||
checkbuffer(L, l);
|
||||
checkbuffer(LS, l);
|
||||
do {
|
||||
checkbuffer(L, l);
|
||||
save_and_next(L, LS, l);
|
||||
checkbuffer(LS, l);
|
||||
save_and_next(LS, l);
|
||||
} while (isalnum(LS->current) || LS->current == '_');
|
||||
save(L, '\0', l);
|
||||
save(LS, '\0', l);
|
||||
return l-1;
|
||||
}
|
||||
|
||||
|
||||
/* LUA_NUMBER */
|
||||
static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
|
||||
lua_State *L = LS->L;
|
||||
size_t l = 0;
|
||||
checkbuffer(L, l);
|
||||
if (comma) save(L, '.', l);
|
||||
checkbuffer(LS, l);
|
||||
if (comma) save(LS, '.', l);
|
||||
while (isdigit(LS->current)) {
|
||||
checkbuffer(L, l);
|
||||
save_and_next(L, LS, l);
|
||||
checkbuffer(LS, l);
|
||||
save_and_next(LS, l);
|
||||
}
|
||||
if (LS->current == '.') {
|
||||
save_and_next(L, LS, l);
|
||||
save_and_next(LS, l);
|
||||
if (LS->current == '.') {
|
||||
save_and_next(L, LS, l);
|
||||
save(L, '\0', l);
|
||||
save_and_next(LS, l);
|
||||
save(LS, '\0', l);
|
||||
luaX_lexerror(LS,
|
||||
"ambiguous syntax (decimal point x string concatenation)",
|
||||
TK_NUMBER);
|
||||
}
|
||||
}
|
||||
while (isdigit(LS->current)) {
|
||||
checkbuffer(L, l);
|
||||
save_and_next(L, LS, l);
|
||||
checkbuffer(LS, l);
|
||||
save_and_next(LS, l);
|
||||
}
|
||||
if (LS->current == 'e' || LS->current == 'E') {
|
||||
save_and_next(L, LS, l); /* read `E' */
|
||||
save_and_next(LS, l); /* read `E' */
|
||||
if (LS->current == '+' || LS->current == '-')
|
||||
save_and_next(L, LS, l); /* optional exponent sign */
|
||||
save_and_next(LS, l); /* optional exponent sign */
|
||||
while (isdigit(LS->current)) {
|
||||
checkbuffer(L, l);
|
||||
save_and_next(L, LS, l);
|
||||
checkbuffer(LS, l);
|
||||
save_and_next(LS, l);
|
||||
}
|
||||
}
|
||||
save(L, '\0', l);
|
||||
if (!luaO_str2d(cast(char *, G(L)->Mbuffer), &seminfo->r))
|
||||
save(LS, '\0', l);
|
||||
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) {
|
||||
lua_State *L = LS->L;
|
||||
int cont = 0;
|
||||
size_t l = 0;
|
||||
checkbuffer(L, l);
|
||||
save(L, '[', l); /* save first `[' */
|
||||
save_and_next(L, LS, l); /* pass the second `[' */
|
||||
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 */
|
||||
for (;;) {
|
||||
checkbuffer(L, l);
|
||||
checkbuffer(LS, l);
|
||||
switch (LS->current) {
|
||||
case EOZ:
|
||||
save(L, '\0', l);
|
||||
save(LS, '\0', l);
|
||||
luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
|
||||
"unfinished long comment", TK_EOS);
|
||||
break; /* to avoid warnings */
|
||||
case '[':
|
||||
save_and_next(L, LS, l);
|
||||
save_and_next(LS, l);
|
||||
if (LS->current == '[') {
|
||||
cont++;
|
||||
save_and_next(L, LS, l);
|
||||
save_and_next(LS, l);
|
||||
}
|
||||
continue;
|
||||
case ']':
|
||||
save_and_next(L, LS, l);
|
||||
save_and_next(LS, l);
|
||||
if (LS->current == ']') {
|
||||
if (cont == 0) goto endloop;
|
||||
cont--;
|
||||
save_and_next(L, LS, l);
|
||||
save_and_next(LS, l);
|
||||
}
|
||||
continue;
|
||||
case '\n':
|
||||
save(L, '\n', l);
|
||||
save(LS, '\n', l);
|
||||
inclinenumber(LS);
|
||||
if (!seminfo) l = 0; /* reset buffer to avoid wasting space */
|
||||
continue;
|
||||
default:
|
||||
save_and_next(L, LS, l);
|
||||
save_and_next(LS, l);
|
||||
}
|
||||
} endloop:
|
||||
save_and_next(L, LS, l); /* skip the second `]' */
|
||||
save(L, '\0', l);
|
||||
save_and_next(LS, l); /* skip the second `]' */
|
||||
save(LS, '\0', l);
|
||||
if (seminfo)
|
||||
seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+2, l-5);
|
||||
seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5);
|
||||
}
|
||||
|
||||
|
||||
static void read_string (LexState *LS, int del, SemInfo *seminfo) {
|
||||
lua_State *L = LS->L;
|
||||
size_t l = 0;
|
||||
checkbuffer(L, l);
|
||||
save_and_next(L, LS, l);
|
||||
checkbuffer(LS, l);
|
||||
save_and_next(LS, l);
|
||||
while (LS->current != del) {
|
||||
checkbuffer(L, l);
|
||||
checkbuffer(LS, l);
|
||||
switch (LS->current) {
|
||||
case EOZ:
|
||||
save(L, '\0', l);
|
||||
save(LS, '\0', l);
|
||||
luaX_lexerror(LS, "unfinished string", TK_EOS);
|
||||
break; /* to avoid warnings */
|
||||
case '\n':
|
||||
save(L, '\0', l);
|
||||
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(L, '\a', l); next(LS); break;
|
||||
case 'b': save(L, '\b', l); next(LS); break;
|
||||
case 'f': save(L, '\f', l); next(LS); break;
|
||||
case 'n': save(L, '\n', l); next(LS); break;
|
||||
case 'r': save(L, '\r', l); next(LS); break;
|
||||
case 't': save(L, '\t', l); next(LS); break;
|
||||
case 'v': save(L, '\v', l); next(LS); break;
|
||||
case '\n': save(L, '\n', l); inclinenumber(LS); break;
|
||||
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 */
|
||||
default: {
|
||||
if (!isdigit(LS->current))
|
||||
save_and_next(L, LS, l); /* handles \\, \", \', and \? */
|
||||
save_and_next(LS, l); /* handles \\, \", \', and \? */
|
||||
else { /* \xxx */
|
||||
int c = 0;
|
||||
int i = 0;
|
||||
@@ -285,21 +288,21 @@ static void read_string (LexState *LS, int del, SemInfo *seminfo) {
|
||||
next(LS);
|
||||
} while (++i<3 && isdigit(LS->current));
|
||||
if (c > UCHAR_MAX) {
|
||||
save(L, '\0', l);
|
||||
save(LS, '\0', l);
|
||||
luaX_lexerror(LS, "escape sequence too large", TK_STRING);
|
||||
}
|
||||
save(L, c, l);
|
||||
save(LS, c, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
save_and_next(L, LS, l);
|
||||
save_and_next(LS, l);
|
||||
}
|
||||
}
|
||||
save_and_next(L, LS, l); /* skip delimiter */
|
||||
save(L, '\0', l);
|
||||
seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+1, l-3);
|
||||
save_and_next(LS, l); /* skip delimiter */
|
||||
save(LS, '\0', l);
|
||||
seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3);
|
||||
}
|
||||
|
||||
|
||||
@@ -387,9 +390,9 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) {
|
||||
else if (isalpha(LS->current) || LS->current == '_') {
|
||||
/* identifier or reserved word */
|
||||
size_t l = readname(LS);
|
||||
TString *ts = luaS_newlstr(LS->L, cast(char *, G(LS->L)->Mbuffer), l);
|
||||
if (ts->tsv.marked >= RESERVEDMARK) /* reserved word? */
|
||||
return ts->tsv.marked-RESERVEDMARK+FIRST_RESERVED;
|
||||
TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l);
|
||||
if (ts->tsv.reserved > 0) /* reserved word? */
|
||||
return ts->tsv.reserved - 1 + FIRST_RESERVED;
|
||||
seminfo->ts = ts;
|
||||
return TK_NAME;
|
||||
}
|
||||
|
||||
8
llex.h
8
llex.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: llex.h,v 1.42 2002/02/08 22:42:41 roberto Exp roberto $
|
||||
** $Id: llex.h,v 1.45 2002/10/08 18:46:08 roberto Exp roberto $
|
||||
** Lexical Analyzer
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -25,7 +25,7 @@ enum RESERVED {
|
||||
/* terminal symbols denoted by reserved words */
|
||||
TK_AND = FIRST_RESERVED, TK_BREAK,
|
||||
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
|
||||
TK_GLOBAL, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
||||
TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
||||
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
|
||||
/* other terminal symbols */
|
||||
TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
|
||||
@@ -56,8 +56,10 @@ typedef struct LexState {
|
||||
Token lookahead; /* look ahead token */
|
||||
struct FuncState *fs; /* `FuncState' is private to the parser */
|
||||
struct lua_State *L;
|
||||
struct zio *z; /* input stream */
|
||||
ZIO *z; /* input stream */
|
||||
Mbuffer *buff; /* buffer for tokens */
|
||||
TString *source; /* current source name */
|
||||
int nestlevel; /* level of nested non-terminals */
|
||||
} LexState;
|
||||
|
||||
|
||||
|
||||
49
llimits.h
49
llimits.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: llimits.h,v 1.44 2002/06/13 13:45:31 roberto Exp roberto $
|
||||
** $Id: llimits.h,v 1.50 2002/11/22 18:01:46 roberto Exp roberto $
|
||||
** Limits, basic types, and some other `installation-dependent' definitions
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -52,12 +52,7 @@ typedef unsigned long lu_mem;
|
||||
/* an integer big enough to count the number of strings in use */
|
||||
typedef long ls_nstr;
|
||||
|
||||
/* an integer big enough to count the number of steps when calling a
|
||||
** `count' hook */
|
||||
typedef long ls_count;
|
||||
|
||||
|
||||
/* chars used as small naturals (so that `char' is reserved for characteres) */
|
||||
/* chars used as small naturals (so that `char' is reserved for characters) */
|
||||
typedef unsigned char lu_byte;
|
||||
|
||||
|
||||
@@ -77,9 +72,18 @@ typedef unsigned char lu_byte;
|
||||
|
||||
/* type to ensure maximum alignment */
|
||||
#ifndef LUSER_ALIGNMENT_T
|
||||
#define LUSER_ALIGNMENT_T double
|
||||
typedef union { double u; void *s; long l; } L_Umaxalign;
|
||||
#else
|
||||
typedef LUSER_ALIGNMENT_T L_Umaxalign;
|
||||
#endif
|
||||
|
||||
|
||||
/* result of `usual argument conversion' over lua_Number */
|
||||
#ifndef LUA_UACNUMBER
|
||||
typedef double l_uacNumber;
|
||||
#else
|
||||
typedef LUA_UACNUMBER l_uacNumber;
|
||||
#endif
|
||||
union L_Umaxalign { LUSER_ALIGNMENT_T u; void *s; long l; };
|
||||
|
||||
|
||||
#ifndef lua_assert
|
||||
@@ -110,12 +114,22 @@ union L_Umaxalign { LUSER_ALIGNMENT_T u; void *s; long l; };
|
||||
typedef unsigned long Instruction;
|
||||
|
||||
|
||||
/* maximum depth for calls */
|
||||
/* maximum depth for calls (unsigned short) */
|
||||
#ifndef LUA_MAXCALLS
|
||||
#define LUA_MAXCALLS 4096
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** maximum depth for C calls (unsigned short): Not too big, or may
|
||||
** overflow the C stack...
|
||||
*/
|
||||
|
||||
#ifndef LUA_MAXCCALLS
|
||||
#define LUA_MAXCCALLS 200
|
||||
#endif
|
||||
|
||||
|
||||
/* maximum size for the C stack */
|
||||
#ifndef LUA_MAXCSTACK
|
||||
#define LUA_MAXCSTACK 2048
|
||||
@@ -150,4 +164,19 @@ typedef unsigned long Instruction;
|
||||
#endif
|
||||
|
||||
|
||||
/* minimum size for string buffer */
|
||||
#ifndef LUA_MINBUFFER
|
||||
#define LUA_MINBUFFER 32
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** maximum number of syntactical nested non-terminals: Not too big,
|
||||
** or may overflow the C stack...
|
||||
*/
|
||||
#ifndef LUA_MAXPARSERLEVEL
|
||||
#define LUA_MAXPARSERLEVEL 200
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
69
lmathlib.c
69
lmathlib.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lmathlib.c,v 1.50 2002/08/14 20:07:43 roberto Exp roberto $
|
||||
** $Id: lmathlib.c,v 1.52 2002/11/14 15:41:38 roberto Exp roberto $
|
||||
** Standard mathematical library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#define lmathlib_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
@@ -34,104 +36,104 @@
|
||||
|
||||
|
||||
static int math_abs (lua_State *L) {
|
||||
lua_pushnumber(L, fabs(luaL_check_number(L, 1)));
|
||||
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_sin (lua_State *L) {
|
||||
lua_pushnumber(L, sin(TORAD(luaL_check_number(L, 1))));
|
||||
lua_pushnumber(L, sin(TORAD(luaL_checknumber(L, 1))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_cos (lua_State *L) {
|
||||
lua_pushnumber(L, cos(TORAD(luaL_check_number(L, 1))));
|
||||
lua_pushnumber(L, cos(TORAD(luaL_checknumber(L, 1))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_tan (lua_State *L) {
|
||||
lua_pushnumber(L, tan(TORAD(luaL_check_number(L, 1))));
|
||||
lua_pushnumber(L, tan(TORAD(luaL_checknumber(L, 1))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_asin (lua_State *L) {
|
||||
lua_pushnumber(L, FROMRAD(asin(luaL_check_number(L, 1))));
|
||||
lua_pushnumber(L, FROMRAD(asin(luaL_checknumber(L, 1))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_acos (lua_State *L) {
|
||||
lua_pushnumber(L, FROMRAD(acos(luaL_check_number(L, 1))));
|
||||
lua_pushnumber(L, FROMRAD(acos(luaL_checknumber(L, 1))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_atan (lua_State *L) {
|
||||
lua_pushnumber(L, FROMRAD(atan(luaL_check_number(L, 1))));
|
||||
lua_pushnumber(L, FROMRAD(atan(luaL_checknumber(L, 1))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_atan2 (lua_State *L) {
|
||||
lua_pushnumber(L, FROMRAD(atan2(luaL_check_number(L, 1), luaL_check_number(L, 2))));
|
||||
lua_pushnumber(L, FROMRAD(atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_ceil (lua_State *L) {
|
||||
lua_pushnumber(L, ceil(luaL_check_number(L, 1)));
|
||||
lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_floor (lua_State *L) {
|
||||
lua_pushnumber(L, floor(luaL_check_number(L, 1)));
|
||||
lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_mod (lua_State *L) {
|
||||
lua_pushnumber(L, fmod(luaL_check_number(L, 1), luaL_check_number(L, 2)));
|
||||
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_sqrt (lua_State *L) {
|
||||
lua_pushnumber(L, sqrt(luaL_check_number(L, 1)));
|
||||
lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_pow (lua_State *L) {
|
||||
lua_pushnumber(L, pow(luaL_check_number(L, 1), luaL_check_number(L, 2)));
|
||||
lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_log (lua_State *L) {
|
||||
lua_pushnumber(L, log(luaL_check_number(L, 1)));
|
||||
lua_pushnumber(L, log(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_log10 (lua_State *L) {
|
||||
lua_pushnumber(L, log10(luaL_check_number(L, 1)));
|
||||
lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_exp (lua_State *L) {
|
||||
lua_pushnumber(L, exp(luaL_check_number(L, 1)));
|
||||
lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_deg (lua_State *L) {
|
||||
lua_pushnumber(L, luaL_check_number(L, 1)/RADIANS_PER_DEGREE);
|
||||
lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_rad (lua_State *L) {
|
||||
lua_pushnumber(L, luaL_check_number(L, 1)*RADIANS_PER_DEGREE);
|
||||
lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_frexp (lua_State *L) {
|
||||
int e;
|
||||
lua_pushnumber(L, frexp(luaL_check_number(L, 1), &e));
|
||||
lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
|
||||
lua_pushnumber(L, e);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int math_ldexp (lua_State *L) {
|
||||
lua_pushnumber(L, ldexp(luaL_check_number(L, 1), luaL_check_int(L, 2)));
|
||||
lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -139,10 +141,10 @@ static int math_ldexp (lua_State *L) {
|
||||
|
||||
static int math_min (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
lua_Number dmin = luaL_check_number(L, 1);
|
||||
lua_Number dmin = luaL_checknumber(L, 1);
|
||||
int i;
|
||||
for (i=2; i<=n; i++) {
|
||||
lua_Number d = luaL_check_number(L, i);
|
||||
lua_Number d = luaL_checknumber(L, i);
|
||||
if (d < dmin)
|
||||
dmin = d;
|
||||
}
|
||||
@@ -153,10 +155,10 @@ static int math_min (lua_State *L) {
|
||||
|
||||
static int math_max (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
lua_Number dmax = luaL_check_number(L, 1);
|
||||
lua_Number dmax = luaL_checknumber(L, 1);
|
||||
int i;
|
||||
for (i=2; i<=n; i++) {
|
||||
lua_Number d = luaL_check_number(L, i);
|
||||
lua_Number d = luaL_checknumber(L, i);
|
||||
if (d > dmax)
|
||||
dmax = d;
|
||||
}
|
||||
@@ -175,15 +177,15 @@ static int math_random (lua_State *L) {
|
||||
break;
|
||||
}
|
||||
case 1: { /* only upper limit */
|
||||
int u = luaL_check_int(L, 1);
|
||||
luaL_arg_check(L, 1<=u, 1, "interval is empty");
|
||||
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' */
|
||||
break;
|
||||
}
|
||||
case 2: { /* lower and upper limits */
|
||||
int l = luaL_check_int(L, 1);
|
||||
int u = luaL_check_int(L, 2);
|
||||
luaL_arg_check(L, l<=u, 2, "interval is empty");
|
||||
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' */
|
||||
break;
|
||||
}
|
||||
@@ -194,7 +196,7 @@ static int math_random (lua_State *L) {
|
||||
|
||||
|
||||
static int math_randomseed (lua_State *L) {
|
||||
srand(luaL_check_int(L, 1));
|
||||
srand(luaL_checkint(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -232,13 +234,10 @@ static const luaL_reg mathlib[] = {
|
||||
** Open math library
|
||||
*/
|
||||
LUALIB_API int lua_mathlibopen (lua_State *L) {
|
||||
lua_pushliteral(L, LUA_MATHLIBNAME);
|
||||
lua_newtable(L);
|
||||
luaL_openlib(L, mathlib, 0);
|
||||
luaL_openlib(L, LUA_MATHLIBNAME, mathlib, 0);
|
||||
lua_pushliteral(L, "pi");
|
||||
lua_pushnumber(L, PI);
|
||||
lua_settable(L, -3);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
lua_pushliteral(L, "__pow");
|
||||
lua_pushcfunction(L, math_pow);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
26
lmem.c
26
lmem.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lmem.c,v 1.56 2002/06/11 16:23:47 roberto Exp roberto $
|
||||
** $Id: lmem.c,v 1.60 2002/11/21 14:14:42 roberto Exp roberto $
|
||||
** Interface to Memory Manager
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define lmem_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
@@ -18,15 +20,22 @@
|
||||
|
||||
|
||||
/*
|
||||
** definition for realloc function. It must assure that
|
||||
** l_realloc(block, x, 0) frees the block, and l_realloc(NULL, 0, x)
|
||||
** allocates a new block (ANSI C assures that).
|
||||
** (`os' is the old block size; some allocators may use that.)
|
||||
** 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.)
|
||||
*/
|
||||
#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
|
||||
|
||||
@@ -54,11 +63,13 @@ 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_realloc(block, oldsize, size);
|
||||
l_free(block, oldsize);
|
||||
block = NULL;
|
||||
}
|
||||
else return NULL; /* avoid `nblocks' computations when oldsize==size==0 */
|
||||
}
|
||||
else if (size >= MAX_SIZET)
|
||||
luaG_runerror(L, "memory allocation error: block too big");
|
||||
@@ -70,7 +81,8 @@ void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
|
||||
else return NULL; /* error before creating state! */
|
||||
}
|
||||
}
|
||||
if (L && G(L)) {
|
||||
if (L) {
|
||||
lua_assert(G(L) != NULL && G(L)->nblocks > 0);
|
||||
G(L)->nblocks -= oldsize;
|
||||
G(L)->nblocks += size;
|
||||
}
|
||||
|
||||
36
lobject.c
36
lobject.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lobject.c,v 1.85 2002/07/17 16:25:13 roberto Exp roberto $
|
||||
** $Id: lobject.c,v 1.93 2002/11/21 15:16:04 roberto Exp roberto $
|
||||
** Some generic functions over Lua objects
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define lobject_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldo.h"
|
||||
@@ -57,38 +59,22 @@ int luaO_log2 (unsigned int x) {
|
||||
|
||||
int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
|
||||
if (ttype(t1) != ttype(t2)) return 0;
|
||||
switch (ttype(t1)) {
|
||||
case LUA_TNUMBER:
|
||||
return nvalue(t1) == nvalue(t2);
|
||||
if (iscollectable(t1)) return gcvalue(t1) == gcvalue(t2);
|
||||
else switch (ttype(t1)) {
|
||||
case LUA_TNIL:
|
||||
return 1;
|
||||
case LUA_TSTRING:
|
||||
return tsvalue(t1) == tsvalue(t2);
|
||||
case LUA_TBOOLEAN:
|
||||
return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
return pvalue(t1) == pvalue(t2);
|
||||
case LUA_TUSERDATA:
|
||||
return uvalue(t1) == uvalue(t2);
|
||||
case LUA_TTABLE:
|
||||
return hvalue(t1) == hvalue(t2);
|
||||
case LUA_TFUNCTION:
|
||||
return clvalue(t1) == clvalue(t2);
|
||||
case LUA_TNUMBER:
|
||||
return nvalue(t1) == nvalue(t2);
|
||||
}
|
||||
lua_assert(0);
|
||||
return 0; /* to avoid warnings */
|
||||
}
|
||||
|
||||
|
||||
void *luaO_openspaceaux (lua_State *L, size_t n) {
|
||||
if (n > G(L)->Mbuffsize) {
|
||||
G(L)->Mbuffer = luaM_realloc(L, G(L)->Mbuffer, G(L)->Mbuffsize, n);
|
||||
G(L)->Mbuffsize = n;
|
||||
}
|
||||
return G(L)->Mbuffer;
|
||||
}
|
||||
|
||||
|
||||
int luaO_str2d (const char *s, lua_Number *result) {
|
||||
char *endptr;
|
||||
lua_Number res = lua_str2number(s, &endptr);
|
||||
@@ -102,7 +88,7 @@ int luaO_str2d (const char *s, lua_Number *result) {
|
||||
|
||||
|
||||
static void pushstr (lua_State *L, const char *str) {
|
||||
setsvalue(L->top, luaS_new(L, str));
|
||||
setsvalue2s(L->top, luaS_new(L, str));
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
@@ -114,7 +100,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
||||
for (;;) {
|
||||
const char *e = strchr(fmt, '%');
|
||||
if (e == NULL) break;
|
||||
setsvalue(L->top, luaS_newlstr(L, fmt, e-fmt));
|
||||
setsvalue2s(L->top, luaS_newlstr(L, fmt, e-fmt));
|
||||
incr_top(L);
|
||||
switch (*(e+1)) {
|
||||
case 's':
|
||||
@@ -132,7 +118,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
||||
incr_top(L);
|
||||
break;
|
||||
case 'f':
|
||||
setnvalue(L->top, va_arg(argp, lua_Number));
|
||||
setnvalue(L->top, va_arg(argp, l_uacNumber));
|
||||
incr_top(L);
|
||||
break;
|
||||
case '%':
|
||||
@@ -144,7 +130,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
||||
fmt = e+2;
|
||||
}
|
||||
pushstr(L, fmt);
|
||||
luaV_concat(L, n+1, L->top - L->ci->base - 1);
|
||||
luaV_concat(L, n+1, L->top - L->base - 1);
|
||||
L->top -= n;
|
||||
return svalue(L->top - 1);
|
||||
}
|
||||
|
||||
155
lobject.h
155
lobject.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lobject.h,v 1.141 2002/08/05 14:08:02 roberto Exp roberto $
|
||||
** $Id: lobject.h,v 1.154 2002/11/14 11:51:50 roberto Exp roberto $
|
||||
** Type definitions for Lua objects
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -13,20 +13,53 @@
|
||||
|
||||
|
||||
/* tags for values visible from Lua */
|
||||
#define NUM_TAGS LUA_TFUNCTION
|
||||
#define NUM_TAGS LUA_TTHREAD
|
||||
|
||||
|
||||
/*
|
||||
** Extra tags for non-values
|
||||
*/
|
||||
#define LUA_TPROTO (NUM_TAGS+1)
|
||||
#define LUA_TUPVAL (NUM_TAGS+2)
|
||||
|
||||
|
||||
/*
|
||||
** Union of all collectable objects
|
||||
*/
|
||||
typedef union GCObject GCObject;
|
||||
|
||||
|
||||
/*
|
||||
** Common Header for all collectable objects (in macro form, to be
|
||||
** included in other objects)
|
||||
*/
|
||||
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
|
||||
|
||||
|
||||
/*
|
||||
** Common header in struct form
|
||||
*/
|
||||
typedef struct GCheader {
|
||||
CommonHeader;
|
||||
} GCheader;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Union of all Lua values
|
||||
*/
|
||||
typedef union {
|
||||
GCObject *gc;
|
||||
void *p;
|
||||
union TString *ts;
|
||||
union Udata *u;
|
||||
union Closure *cl;
|
||||
struct Table *h;
|
||||
lua_Number n;
|
||||
int b;
|
||||
} Value;
|
||||
|
||||
|
||||
/*
|
||||
** Lua values (or `tagged objects')
|
||||
*/
|
||||
typedef struct lua_TObject {
|
||||
int tt;
|
||||
Value value;
|
||||
@@ -41,17 +74,20 @@ typedef struct lua_TObject {
|
||||
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
|
||||
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
|
||||
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
|
||||
#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
|
||||
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
|
||||
|
||||
/* Macros to access values */
|
||||
#define ttype(o) ((o)->tt)
|
||||
#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.ts)
|
||||
#define uvalue(o) check_exp(ttisuserdata(o), (o)->value.u)
|
||||
#define clvalue(o) check_exp(ttisfunction(o), (o)->value.cl)
|
||||
#define hvalue(o) check_exp(ttistable(o), (o)->value.h)
|
||||
#define tsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
|
||||
#define uvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
|
||||
#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)
|
||||
#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
|
||||
|
||||
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
|
||||
|
||||
@@ -69,26 +105,70 @@ typedef struct lua_TObject {
|
||||
{ TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); }
|
||||
|
||||
#define setsvalue(obj,x) \
|
||||
{ TObject *i_o=(obj); i_o->tt=LUA_TSTRING; i_o->value.ts=(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 setuvalue(obj,x) \
|
||||
{ TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; i_o->value.u=(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 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 setclvalue(obj,x) \
|
||||
{ TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; i_o->value.cl=(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 sethvalue(obj,x) \
|
||||
{ TObject *i_o=(obj); i_o->tt=LUA_TTABLE; i_o->value.h=(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)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** 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; }
|
||||
|
||||
|
||||
/*
|
||||
** different types of sets, according to destination
|
||||
*/
|
||||
|
||||
/* from stack to (same) stack */
|
||||
#define setobjs2s setobj
|
||||
/* to stack (not from same stack) */
|
||||
#define setobj2s setobj
|
||||
#define setsvalue2s setsvalue
|
||||
/* from table to same table */
|
||||
#define setobjt2t setobj
|
||||
/* to table */
|
||||
#define setobj2t setobj
|
||||
/* to new object */
|
||||
#define setobj2n setobj
|
||||
#define setsvalue2n setsvalue
|
||||
|
||||
#define setttype(obj, tt) (ttype(obj) = (tt))
|
||||
|
||||
|
||||
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
|
||||
|
||||
|
||||
|
||||
typedef TObject *StkId; /* index to stack elements */
|
||||
|
||||
@@ -97,12 +177,12 @@ typedef TObject *StkId; /* index to stack elements */
|
||||
** String headers for string table
|
||||
*/
|
||||
typedef union TString {
|
||||
union L_Umaxalign dummy; /* ensures maximum alignment for strings */
|
||||
L_Umaxalign dummy; /* ensures maximum alignment for strings */
|
||||
struct {
|
||||
CommonHeader;
|
||||
lu_byte reserved;
|
||||
lu_hash hash;
|
||||
size_t len;
|
||||
int marked;
|
||||
union TString *nexthash; /* chain for hash table */
|
||||
} tsv;
|
||||
} TString;
|
||||
|
||||
@@ -113,11 +193,11 @@ typedef union TString {
|
||||
|
||||
|
||||
typedef union Udata {
|
||||
union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
|
||||
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
|
||||
struct {
|
||||
CommonHeader;
|
||||
struct Table *metatable;
|
||||
union Udata *next; /* chain for list of all udata */
|
||||
size_t len; /* least 2 bits reserved for gc mark */
|
||||
size_t len;
|
||||
} uv;
|
||||
} Udata;
|
||||
|
||||
@@ -128,23 +208,24 @@ typedef union Udata {
|
||||
** Function Prototypes
|
||||
*/
|
||||
typedef struct Proto {
|
||||
CommonHeader;
|
||||
TObject *k; /* constants used by the function */
|
||||
Instruction *code;
|
||||
struct Proto **p; /* functions defined inside the function */
|
||||
struct Proto *next;
|
||||
int *lineinfo; /* map from opcodes to source lines */
|
||||
struct LocVar *locvars; /* information about local variables */
|
||||
TString *source;
|
||||
int sizek; /* size of `k' */
|
||||
int sizecode;
|
||||
int sizelineinfo;
|
||||
int sizep; /* size of `p' */
|
||||
int sizelocvars;
|
||||
int lineDefined;
|
||||
GCObject *gclist;
|
||||
lu_byte nupvalues;
|
||||
lu_byte numparams;
|
||||
lu_byte is_vararg;
|
||||
lu_byte maxstacksize;
|
||||
lu_byte marked;
|
||||
} Proto;
|
||||
|
||||
|
||||
@@ -161,8 +242,8 @@ typedef struct LocVar {
|
||||
*/
|
||||
|
||||
typedef struct UpVal {
|
||||
CommonHeader;
|
||||
TObject *v; /* points to stack or to its own value */
|
||||
struct UpVal *next;
|
||||
TObject value; /* the value (when closed) */
|
||||
} UpVal;
|
||||
|
||||
@@ -171,21 +252,18 @@ typedef struct UpVal {
|
||||
** Closures
|
||||
*/
|
||||
|
||||
#define ClosureHeader \
|
||||
CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist
|
||||
|
||||
typedef struct CClosure {
|
||||
lu_byte isC; /* 0 for Lua functions, 1 for C functions */
|
||||
lu_byte nupvalues;
|
||||
lu_byte marked;
|
||||
union Closure *next;
|
||||
ClosureHeader;
|
||||
lua_CFunction f;
|
||||
TObject upvalue[1];
|
||||
} CClosure;
|
||||
|
||||
|
||||
typedef struct LClosure {
|
||||
lu_byte isC;
|
||||
lu_byte nupvalues;
|
||||
lu_byte marked;
|
||||
union Closure *next; /* first four fields must be equal to CClosure!! */
|
||||
ClosureHeader;
|
||||
struct Proto *p;
|
||||
TObject g; /* global table for this closure */
|
||||
UpVal *upvals[1];
|
||||
@@ -214,21 +292,17 @@ typedef struct Node {
|
||||
|
||||
|
||||
typedef struct Table {
|
||||
CommonHeader;
|
||||
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 */
|
||||
Node *node;
|
||||
Node *firstfree; /* this position is free; all positions after it are full */
|
||||
struct Table *next;
|
||||
struct Table *mark; /* marked tables (point to itself when not marked) */
|
||||
GCObject *gclist;
|
||||
int sizearray; /* size of `array' array */
|
||||
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
||||
lu_byte lsizenode; /* log2 of size of `node' array */
|
||||
lu_byte mode;
|
||||
} Table;
|
||||
|
||||
/* bit masks for `mode' */
|
||||
#define WEAKKEY 1
|
||||
#define WEAKVALUE 2
|
||||
|
||||
|
||||
/*
|
||||
@@ -249,9 +323,6 @@ extern const TObject luaO_nilobject;
|
||||
int luaO_log2 (unsigned int x);
|
||||
|
||||
|
||||
#define luaO_openspace(L,n,t) cast(t *, luaO_openspaceaux(L,(n)*sizeof(t)))
|
||||
void *luaO_openspaceaux (lua_State *L, size_t n);
|
||||
|
||||
int luaO_rawequalObj (const TObject *t1, const TObject *t2);
|
||||
int luaO_str2d (const char *s, lua_Number *result);
|
||||
|
||||
|
||||
84
lopcodes.c
84
lopcodes.c
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
** $Id: lopcodes.c,v 1.19 2002/05/13 13:09:00 roberto Exp roberto $
|
||||
** $Id: lopcodes.c,v 1.21 2002/08/20 20:03:05 roberto Exp roberto $
|
||||
** extracted automatically from lopcodes.h by mkprint.lua
|
||||
** DO NOT EDIT
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#define lopcodes_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lobject.h"
|
||||
@@ -39,8 +41,6 @@ const char *const luaP_opnames[] = {
|
||||
"EQ",
|
||||
"LT",
|
||||
"LE",
|
||||
"GT",
|
||||
"GE",
|
||||
"TEST",
|
||||
"CALL",
|
||||
"TAILCALL",
|
||||
@@ -56,49 +56,47 @@ const char *const luaP_opnames[] = {
|
||||
|
||||
#endif
|
||||
|
||||
#define opmode(t,x,b,c,sa,k,m) (((t)<<OpModeT) | \
|
||||
((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \
|
||||
#define opmode(t,b,bk,ck,sa,k,m) (((t)<<OpModeT) | \
|
||||
((b)<<OpModeBreg) | ((bk)<<OpModeBrk) | ((ck)<<OpModeCrk) | \
|
||||
((sa)<<OpModesetA) | ((k)<<OpModeK) | (m))
|
||||
|
||||
|
||||
const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||
/* T _ B C sA K mode opcode */
|
||||
opmode(0,0,1,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,0,1,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,0,1,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,0,1,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,0,1,0, 1,0,iABC) /* OP_UNM */
|
||||
,opmode(0,0,1,0, 1,0,iABC) /* OP_NOT */
|
||||
,opmode(0,0,1,1, 1,0,iABC) /* OP_CONCAT */
|
||||
,opmode(0,0,0,0, 0,0,iAsBx) /* OP_JMP */
|
||||
,opmode(1,0,0,1, 0,0,iABC) /* OP_EQ */
|
||||
,opmode(1,0,0,1, 0,0,iABC) /* OP_LT */
|
||||
,opmode(1,0,0,1, 0,0,iABC) /* OP_LE */
|
||||
,opmode(1,0,0,1, 0,0,iABC) /* OP_GT */
|
||||
,opmode(1,0,0,1, 0,0,iABC) /* OP_GE */
|
||||
,opmode(1,0,0,1, 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 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 */
|
||||
};
|
||||
|
||||
|
||||
53
lopcodes.h
53
lopcodes.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lopcodes.h,v 1.99 2002/06/12 14:51:31 roberto Exp $
|
||||
** $Id: lopcodes.h,v 1.101 2002/08/20 20:03:05 roberto Exp roberto $
|
||||
** Opcodes for Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -14,9 +14,9 @@
|
||||
We assume that instructions are unsigned numbers.
|
||||
All instructions have an opcode in the first 6 bits.
|
||||
Instructions can have the following fields:
|
||||
`A' : 8 bits (25-32)
|
||||
`B' : 8 bits (17-24)
|
||||
`C' : 10 bits (7-16)
|
||||
`A' : 8 bits
|
||||
`B' : 9 bits
|
||||
`C' : 9 bits
|
||||
`Bx' : 18 bits (`B' and `C' together)
|
||||
`sBx' : signed Bx
|
||||
|
||||
@@ -34,8 +34,8 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
|
||||
/*
|
||||
** size and position of opcode arguments.
|
||||
*/
|
||||
#define SIZE_C 10
|
||||
#define SIZE_B 8
|
||||
#define SIZE_C 9
|
||||
#define SIZE_B 9
|
||||
#define SIZE_Bx (SIZE_C + SIZE_B)
|
||||
#define SIZE_A 8
|
||||
|
||||
@@ -112,16 +112,20 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
|
||||
|
||||
|
||||
/*
|
||||
** invalid registers that fits in 8 bits
|
||||
** invalid register that fits in 8 bits
|
||||
*/
|
||||
#define NO_REG MAXARG_A
|
||||
#define NO_REG1 (NO_REG+1)
|
||||
|
||||
|
||||
/*
|
||||
** R(x) - register
|
||||
** Kst(x) - constant (in constant table)
|
||||
** R/K(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK)
|
||||
** RK(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** grep "ORDER OP" if you change these enums
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
@@ -135,21 +139,21 @@ OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
|
||||
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
|
||||
|
||||
OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
|
||||
OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */
|
||||
OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
|
||||
|
||||
OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
|
||||
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
|
||||
OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */
|
||||
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
|
||||
|
||||
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
|
||||
|
||||
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[R/K(C)] */
|
||||
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
|
||||
|
||||
OP_ADD,/* A B C R(A) := R(B) + R/K(C) */
|
||||
OP_SUB,/* A B C R(A) := R(B) - R/K(C) */
|
||||
OP_MUL,/* A B C R(A) := R(B) * R/K(C) */
|
||||
OP_DIV,/* A B C R(A) := R(B) / R/K(C) */
|
||||
OP_POW,/* A B C R(A) := R(B) ^ R/K(C) */
|
||||
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
|
||||
OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
|
||||
OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
|
||||
OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
|
||||
OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
|
||||
OP_UNM,/* A B R(A) := -R(B) */
|
||||
OP_NOT,/* A B R(A) := not R(B) */
|
||||
|
||||
@@ -157,13 +161,11 @@ OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
|
||||
|
||||
OP_JMP,/* sBx PC += sBx */
|
||||
|
||||
OP_EQ,/* A B C if ((R(A) == R/K(C)) ~= B) then pc++ */
|
||||
OP_LT,/* A B C if ((R(A) < R/K(C)) ~= B) then pc++ */
|
||||
OP_LE,/* A B C if ((R(A) <= R/K(C)) ~= B) then pc++ */
|
||||
OP_GT,/* A B C if ((R(A) > R/K(C)) ~= B) then pc++ */
|
||||
OP_GE,/* A B C if ((R(A) >= R/K(C)) ~= B) then pc++ */
|
||||
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
|
||||
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
||||
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
||||
|
||||
OP_TEST,/* A B C if (R(C) <=> B) then R(A) := R(C) else pc++ */
|
||||
OP_TEST,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
||||
|
||||
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||
@@ -207,12 +209,15 @@ OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
|
||||
*/
|
||||
enum OpModeMask {
|
||||
OpModeBreg = 2, /* B is a register */
|
||||
OpModeCreg, /* C is a register/constant */
|
||||
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 */
|
||||
|
||||
};
|
||||
|
||||
|
||||
extern const lu_byte luaP_opmodes[NUM_OPCODES];
|
||||
|
||||
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
|
||||
|
||||
290
lparser.c
290
lparser.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lparser.c,v 1.190 2002/07/04 18:23:42 roberto Exp $
|
||||
** $Id: lparser.c,v 1.201 2002/12/06 17:09:00 roberto Exp roberto $
|
||||
** Lua Parser
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define lparser_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lcode.h"
|
||||
@@ -26,6 +28,10 @@
|
||||
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
|
||||
|
||||
|
||||
#define enterlevel(ls) if (++(ls)->nestlevel > LUA_MAXPARSERLEVEL) \
|
||||
luaX_syntaxerror(ls, "too many syntax levels");
|
||||
#define leavelevel(ls) ((ls)->nestlevel--)
|
||||
|
||||
|
||||
/*
|
||||
** nodes for block list (list of active blocks)
|
||||
@@ -43,9 +49,7 @@ typedef struct BlockCnt {
|
||||
/*
|
||||
** prototypes for recursive non-terminal functions
|
||||
*/
|
||||
static void body (LexState *ls, expdesc *v, int needself, int line);
|
||||
static void chunk (LexState *ls);
|
||||
static void constructor (LexState *ls, expdesc *v);
|
||||
static void expr (LexState *ls, expdesc *v);
|
||||
|
||||
|
||||
@@ -299,8 +303,8 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
|
||||
f->p[fs->np++] = func->f;
|
||||
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
|
||||
for (i=0; i<func->f->nupvalues; i++) {
|
||||
luaK_exp2nextreg(fs, &func->upvalues[i]);
|
||||
fs->freereg--; /* CLOSURE will use these values */
|
||||
OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
|
||||
luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +328,7 @@ static void open_func (LexState *ls, FuncState *fs) {
|
||||
fs->bl = NULL;
|
||||
f->code = NULL;
|
||||
f->source = ls->source;
|
||||
f->maxstacksize = 1; /* register 0 is always valid */
|
||||
f->maxstacksize = 2; /* registers 0/1 are always valid */
|
||||
f->numparams = 0; /* default for main chunk */
|
||||
f->is_vararg = 0; /* default for main chunk */
|
||||
}
|
||||
@@ -336,12 +340,10 @@ static void close_func (LexState *ls) {
|
||||
Proto *f = fs->f;
|
||||
removevars(ls, 0);
|
||||
luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */
|
||||
lua_assert(G(L)->roottable == fs->h);
|
||||
G(L)->roottable = fs->h->next;
|
||||
luaH_free(L, fs->h);
|
||||
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
|
||||
luaM_reallocvector(L, f->lineinfo, f->sizecode, fs->pc, int);
|
||||
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);
|
||||
f->sizek = fs->nk;
|
||||
luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
|
||||
@@ -354,9 +356,11 @@ static void close_func (LexState *ls) {
|
||||
}
|
||||
|
||||
|
||||
Proto *luaY_parser (lua_State *L, ZIO *z) {
|
||||
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff) {
|
||||
struct LexState lexstate;
|
||||
struct FuncState funcstate;
|
||||
lexstate.buff = buff;
|
||||
lexstate.nestlevel = 0;
|
||||
luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z)));
|
||||
open_func(&lexstate, &funcstate);
|
||||
next(&lexstate); /* read first token */
|
||||
@@ -365,6 +369,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z) {
|
||||
close_func(&lexstate);
|
||||
lua_assert(funcstate.prev == NULL);
|
||||
lua_assert(funcstate.f->nupvalues == 0);
|
||||
lua_assert(lexstate.nestlevel == 0);
|
||||
return funcstate.f;
|
||||
}
|
||||
|
||||
@@ -395,69 +400,6 @@ static void luaY_index (LexState *ls, expdesc *v) {
|
||||
}
|
||||
|
||||
|
||||
static int explist1 (LexState *ls, expdesc *v) {
|
||||
/* explist1 -> expr { `,' expr } */
|
||||
int n = 1; /* at least one expression */
|
||||
expr(ls, v);
|
||||
while (testnext(ls, ',')) {
|
||||
luaK_exp2nextreg(ls->fs, v);
|
||||
expr(ls, v);
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static void funcargs (LexState *ls, expdesc *f) {
|
||||
FuncState *fs = ls->fs;
|
||||
expdesc args;
|
||||
int base, nparams;
|
||||
int line = ls->linenumber;
|
||||
switch (ls->t.token) {
|
||||
case '(': { /* funcargs -> `(' [ explist1 ] `)' */
|
||||
if (line != ls->lastline)
|
||||
luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
|
||||
next(ls);
|
||||
if (ls->t.token == ')') /* arg list is empty? */
|
||||
args.k = VVOID;
|
||||
else {
|
||||
explist1(ls, &args);
|
||||
luaK_setcallreturns(fs, &args, LUA_MULTRET);
|
||||
}
|
||||
check_match(ls, ')', '(', line);
|
||||
break;
|
||||
}
|
||||
case '{': { /* funcargs -> constructor */
|
||||
constructor(ls, &args);
|
||||
break;
|
||||
}
|
||||
case TK_STRING: { /* funcargs -> STRING */
|
||||
codestring(ls, &args, ls->t.seminfo.ts);
|
||||
next(ls); /* must use `seminfo' before `next' */
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
luaX_syntaxerror(ls, "function arguments expected");
|
||||
return;
|
||||
}
|
||||
}
|
||||
lua_assert(f->k == VNONRELOC);
|
||||
base = f->info; /* base register for call */
|
||||
if (args.k == VCALL)
|
||||
nparams = LUA_MULTRET; /* open call */
|
||||
else {
|
||||
if (args.k != VVOID)
|
||||
luaK_exp2nextreg(fs, &args); /* close last argument */
|
||||
nparams = fs->freereg - (base+1);
|
||||
}
|
||||
init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
|
||||
fs->f->lineinfo[f->info] = line;
|
||||
fs->freereg = base+1; /* call remove function and arguments and leaves
|
||||
(unless changed) one result */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================================
|
||||
** Rules for Constructors
|
||||
@@ -489,8 +431,8 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
|
||||
check(ls, '=');
|
||||
luaK_exp2RK(fs, &key);
|
||||
expr(ls, &val);
|
||||
luaK_exp2anyreg(fs, &val);
|
||||
luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key));
|
||||
luaK_codeABC(fs, OP_SETTABLE, cc->t->info, luaK_exp2RK(fs, &key),
|
||||
luaK_exp2RK(fs, &val));
|
||||
fs->freereg = reg; /* free registers */
|
||||
}
|
||||
|
||||
@@ -573,11 +515,107 @@ static void constructor (LexState *ls, expdesc *t) {
|
||||
SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */
|
||||
}
|
||||
|
||||
|
||||
/* }====================================================================== */
|
||||
|
||||
|
||||
|
||||
static void parlist (LexState *ls) {
|
||||
/* parlist -> [ param { `,' param } ] */
|
||||
int nparams = 0;
|
||||
int dots = 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;
|
||||
default: luaX_syntaxerror(ls, "<name> or `...' expected");
|
||||
}
|
||||
} while (!dots && testnext(ls, ','));
|
||||
}
|
||||
code_params(ls, nparams, dots);
|
||||
}
|
||||
|
||||
|
||||
static void body (LexState *ls, expdesc *e, int needself, int line) {
|
||||
/* body -> `(' parlist `)' chunk END */
|
||||
FuncState new_fs;
|
||||
open_func(ls, &new_fs);
|
||||
new_fs.f->lineDefined = line;
|
||||
check(ls, '(');
|
||||
if (needself)
|
||||
create_local(ls, "self");
|
||||
parlist(ls);
|
||||
check(ls, ')');
|
||||
chunk(ls);
|
||||
check_match(ls, TK_END, TK_FUNCTION, line);
|
||||
close_func(ls);
|
||||
pushclosure(ls, &new_fs, e);
|
||||
}
|
||||
|
||||
|
||||
static int explist1 (LexState *ls, expdesc *v) {
|
||||
/* explist1 -> expr { `,' expr } */
|
||||
int n = 1; /* at least one expression */
|
||||
expr(ls, v);
|
||||
while (testnext(ls, ',')) {
|
||||
luaK_exp2nextreg(ls->fs, v);
|
||||
expr(ls, v);
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static void funcargs (LexState *ls, expdesc *f) {
|
||||
FuncState *fs = ls->fs;
|
||||
expdesc args;
|
||||
int base, nparams;
|
||||
int line = ls->linenumber;
|
||||
switch (ls->t.token) {
|
||||
case '(': { /* funcargs -> `(' [ explist1 ] `)' */
|
||||
if (line != ls->lastline)
|
||||
luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
|
||||
next(ls);
|
||||
if (ls->t.token == ')') /* arg list is empty? */
|
||||
args.k = VVOID;
|
||||
else {
|
||||
explist1(ls, &args);
|
||||
luaK_setcallreturns(fs, &args, LUA_MULTRET);
|
||||
}
|
||||
check_match(ls, ')', '(', line);
|
||||
break;
|
||||
}
|
||||
case '{': { /* funcargs -> constructor */
|
||||
constructor(ls, &args);
|
||||
break;
|
||||
}
|
||||
case TK_STRING: { /* funcargs -> STRING */
|
||||
codestring(ls, &args, ls->t.seminfo.ts);
|
||||
next(ls); /* must use `seminfo' before `next' */
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
luaX_syntaxerror(ls, "function arguments expected");
|
||||
return;
|
||||
}
|
||||
}
|
||||
lua_assert(f->k == VNONRELOC);
|
||||
base = f->info; /* base register for call */
|
||||
if (args.k == VCALL)
|
||||
nparams = LUA_MULTRET; /* open call */
|
||||
else {
|
||||
if (args.k != VVOID)
|
||||
luaK_exp2nextreg(fs, &args); /* close last argument */
|
||||
nparams = fs->freereg - (base+1);
|
||||
}
|
||||
init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
|
||||
luaK_fixline(fs, line);
|
||||
fs->freereg = base+1; /* call remove function and arguments and leaves
|
||||
(unless changed) one result */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================================
|
||||
@@ -698,8 +736,6 @@ static void simpleexp (LexState *ls, expdesc *v) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static UnOpr getunopr (int op) {
|
||||
switch (op) {
|
||||
case TK_NOT: return OPR_NOT;
|
||||
@@ -735,7 +771,7 @@ static const struct {
|
||||
lu_byte right; /* right priority */
|
||||
} priority[] = { /* ORDER OPR */
|
||||
{6, 6}, {6, 6}, {7, 7}, {7, 7}, /* arithmetic */
|
||||
{10, 9}, {5, 4}, /* power and concat (right associative) */
|
||||
{10, 9}, {5, 4}, /* power and concat (right associative) */
|
||||
{3, 3}, {3, 3}, /* equality */
|
||||
{3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
|
||||
{2, 2}, {1, 1} /* logical (and/or) */
|
||||
@@ -750,7 +786,9 @@ static const struct {
|
||||
*/
|
||||
static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
|
||||
BinOpr op;
|
||||
UnOpr uop = getunopr(ls->t.token);
|
||||
UnOpr uop;
|
||||
enterlevel(ls);
|
||||
uop = getunopr(ls->t.token);
|
||||
if (uop != OPR_NOUNOPR) {
|
||||
next(ls);
|
||||
subexpr(ls, v, UNARY_PRIORITY);
|
||||
@@ -769,6 +807,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
|
||||
luaK_posfix(ls->fs, op, v, &v2);
|
||||
op = nextop;
|
||||
}
|
||||
leavelevel(ls);
|
||||
return op; /* return first untreated operator */
|
||||
}
|
||||
|
||||
@@ -780,6 +819,7 @@ static void expr (LexState *ls, expdesc *v) {
|
||||
/* }==================================================================== */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================================
|
||||
** Rules for Statements
|
||||
@@ -974,10 +1014,27 @@ static int exp1 (LexState *ls) {
|
||||
}
|
||||
|
||||
|
||||
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
|
||||
BlockCnt bl;
|
||||
FuncState *fs = ls->fs;
|
||||
int prep, endfor;
|
||||
adjustlocalvars(ls, nvars); /* scope for all variables */
|
||||
check(ls, TK_DO);
|
||||
enterblock(fs, &bl, 1); /* loop block */
|
||||
prep = luaK_getlabel(fs);
|
||||
block(ls);
|
||||
luaK_patchtohere(fs, prep-1);
|
||||
endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
|
||||
luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
|
||||
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
|
||||
luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep);
|
||||
leaveblock(fs);
|
||||
}
|
||||
|
||||
|
||||
static void fornum (LexState *ls, TString *varname, int line) {
|
||||
/* fornum -> NAME = exp1,exp1[,exp1] DO body */
|
||||
FuncState *fs = ls->fs;
|
||||
int prep, endfor;
|
||||
int base = fs->freereg;
|
||||
new_localvar(ls, varname, 0);
|
||||
new_localvarstr(ls, "(for limit)", 1);
|
||||
@@ -992,16 +1049,9 @@ static void fornum (LexState *ls, TString *varname, int line) {
|
||||
luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
|
||||
luaK_reserveregs(fs, 1);
|
||||
}
|
||||
adjustlocalvars(ls, 3); /* scope for control variables */
|
||||
luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
|
||||
luaK_jump(fs);
|
||||
prep = luaK_getlabel(fs);
|
||||
check(ls, TK_DO);
|
||||
block(ls);
|
||||
luaK_patchtohere(fs, prep-1);
|
||||
endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
|
||||
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
|
||||
luaK_patchlist(fs, endfor, prep);
|
||||
forbody(ls, base, line, 3, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1009,9 +1059,8 @@ static void forlist (LexState *ls, TString *indexname) {
|
||||
/* forlist -> NAME {,NAME} IN explist1 DO body */
|
||||
FuncState *fs = ls->fs;
|
||||
expdesc e;
|
||||
int line;
|
||||
int nvars = 0;
|
||||
int prep;
|
||||
int line;
|
||||
int base = fs->freereg;
|
||||
new_localvarstr(ls, "(for generator)", nvars++);
|
||||
new_localvarstr(ls, "(for state)", nvars++);
|
||||
@@ -1020,18 +1069,10 @@ static void forlist (LexState *ls, TString *indexname) {
|
||||
new_localvar(ls, str_checkname(ls), nvars++);
|
||||
check(ls, TK_IN);
|
||||
line = ls->linenumber;
|
||||
adjust_assign(ls, 3, explist1(ls, &e), &e);
|
||||
luaK_reserveregs(fs, nvars - 3); /* registers for other variables */
|
||||
adjust_assign(ls, nvars, explist1(ls, &e), &e);
|
||||
luaK_checkstack(fs, 3); /* extra space to call generator */
|
||||
luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP);
|
||||
adjustlocalvars(ls, nvars); /* scope for all variables */
|
||||
check(ls, TK_DO);
|
||||
prep = luaK_getlabel(fs);
|
||||
block(ls);
|
||||
luaK_patchtohere(fs, prep-1);
|
||||
removevars(fs->ls, fs->nactvar - nvars); /* deactivate locals for next op. */
|
||||
luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);
|
||||
luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
|
||||
luaK_patchlist(fs, luaK_jump(fs), prep);
|
||||
forbody(ls, base, line, nvars, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1040,7 +1081,7 @@ static void forstat (LexState *ls, int line) {
|
||||
FuncState *fs = ls->fs;
|
||||
TString *varname;
|
||||
BlockCnt bl;
|
||||
enterblock(fs, &bl, 1);
|
||||
enterblock(fs, &bl, 0); /* block to control variable scope */
|
||||
next(ls); /* skip `for' */
|
||||
varname = str_checkname(ls); /* first variable name */
|
||||
switch (ls->t.token) {
|
||||
@@ -1137,6 +1178,7 @@ static void funcstat (LexState *ls, int line) {
|
||||
needself = funcname(ls, &v);
|
||||
body(ls, &b, needself, line);
|
||||
luaK_storevar(ls->fs, &v, &b);
|
||||
luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
|
||||
}
|
||||
|
||||
|
||||
@@ -1259,51 +1301,17 @@ static int statement (LexState *ls) {
|
||||
}
|
||||
|
||||
|
||||
static void parlist (LexState *ls) {
|
||||
/* parlist -> [ param { `,' param } ] */
|
||||
int nparams = 0;
|
||||
int dots = 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;
|
||||
default: luaX_syntaxerror(ls, "<name> or `...' expected");
|
||||
}
|
||||
} while (!dots && testnext(ls, ','));
|
||||
}
|
||||
code_params(ls, nparams, dots);
|
||||
}
|
||||
|
||||
|
||||
static void body (LexState *ls, expdesc *e, int needself, int line) {
|
||||
/* body -> `(' parlist `)' chunk END */
|
||||
FuncState new_fs;
|
||||
open_func(ls, &new_fs);
|
||||
new_fs.f->lineDefined = line;
|
||||
check(ls, '(');
|
||||
if (needself)
|
||||
create_local(ls, "self");
|
||||
parlist(ls);
|
||||
check(ls, ')');
|
||||
chunk(ls);
|
||||
check_match(ls, TK_END, TK_FUNCTION, line);
|
||||
close_func(ls);
|
||||
pushclosure(ls, &new_fs, e);
|
||||
}
|
||||
|
||||
|
||||
/* }====================================================================== */
|
||||
|
||||
|
||||
static void chunk (LexState *ls) {
|
||||
/* chunk -> { stat [`;'] } */
|
||||
int islast = 0;
|
||||
enterlevel(ls);
|
||||
while (!islast && !block_follow(ls->t.token)) {
|
||||
islast = statement(ls);
|
||||
testnext(ls, ';');
|
||||
lua_assert(ls->fs->freereg >= ls->fs->nactvar);
|
||||
ls->fs->freereg = ls->fs->nactvar; /* free registers */
|
||||
}
|
||||
leavelevel(ls);
|
||||
}
|
||||
|
||||
/* }====================================================================== */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lparser.h,v 1.43 2002/05/10 19:22:11 roberto Exp roberto $
|
||||
** $Id: lparser.h,v 1.44 2002/05/14 17:52:22 roberto Exp roberto $
|
||||
** Lua Parser
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -65,7 +65,7 @@ typedef struct FuncState {
|
||||
} FuncState;
|
||||
|
||||
|
||||
Proto *luaY_parser (lua_State *L, ZIO *z);
|
||||
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
213
lstate.c
213
lstate.c
@@ -1,10 +1,14 @@
|
||||
/*
|
||||
** $Id: lstate.c,v 1.102 2002/08/06 15:32:22 roberto Exp roberto $
|
||||
** $Id: lstate.c,v 1.116 2002/11/22 17:16:52 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define lstate_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
@@ -19,13 +23,20 @@
|
||||
#include "ltm.h"
|
||||
|
||||
|
||||
/*
|
||||
** macro to allow the inclusion of user information in Lua state
|
||||
*/
|
||||
#ifndef LUA_USERSTATE
|
||||
#define EXTRASPACE 0
|
||||
#else
|
||||
union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;};
|
||||
#define EXTRASPACE (sizeof(union UEXTRASPACE))
|
||||
#endif
|
||||
|
||||
|
||||
static void close_state (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** you can change this function through the official API
|
||||
** you can change this function through the official API:
|
||||
** call `lua_setpanicf'
|
||||
*/
|
||||
static int default_panic (lua_State *L) {
|
||||
@@ -34,19 +45,41 @@ static int default_panic (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static void stack_init (lua_State *L, lua_State *OL) {
|
||||
L->stack = luaM_newvector(OL, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
|
||||
L->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
|
||||
L->top = L->stack;
|
||||
L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1;
|
||||
L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
|
||||
L->ci = L->base_ci;
|
||||
L->ci->state = CI_C; /* not a Lua function */
|
||||
setnilvalue(L->top++); /* `function' entry for this `ci' */
|
||||
L->ci->base = L->top;
|
||||
L->ci->top = L->top + LUA_MINSTACK;
|
||||
L->size_ci = BASIC_CI_SIZE;
|
||||
L->end_ci = L->base_ci + L->size_ci;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static void stack_init (lua_State *L1, lua_State *L) {
|
||||
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
|
||||
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;
|
||||
L1->size_ci = BASIC_CI_SIZE;
|
||||
L1->end_ci = L1->base_ci + L1->size_ci;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,29 +87,30 @@ static void stack_init (lua_State *L, lua_State *OL) {
|
||||
** open parts that may cause memory-allocation errors
|
||||
*/
|
||||
static void f_luaopen (lua_State *L, void *ud) {
|
||||
UNUSED(ud);
|
||||
/* create a new global state */
|
||||
L->l_G = luaM_new(L, global_State);
|
||||
G(L)->GCthreshold = 0; /* mark it as unfinished state */
|
||||
G(L)->strt.size = 0;
|
||||
G(L)->strt.nuse = 0;
|
||||
G(L)->strt.hash = NULL;
|
||||
G(L)->Mbuffer = NULL;
|
||||
G(L)->Mbuffsize = 0;
|
||||
G(L)->panic = &default_panic;
|
||||
G(L)->rootproto = NULL;
|
||||
G(L)->rootcl = NULL;
|
||||
G(L)->roottable = NULL;
|
||||
G(L)->rootupval = NULL;
|
||||
G(L)->rootudata = NULL;
|
||||
G(L)->tmudata = NULL;
|
||||
setnilvalue(key(G(L)->dummynode));
|
||||
setnilvalue(val(G(L)->dummynode));
|
||||
G(L)->dummynode->next = NULL;
|
||||
G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
|
||||
global_State *g = luaM_new(NULL, global_State);
|
||||
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(key(g->dummynode));
|
||||
setnilvalue(val(g->dummynode));
|
||||
g->dummynode->next = NULL;
|
||||
g->nblocks = sizeof(lua_State) + sizeof(global_State);
|
||||
stack_init(L, L); /* init stack */
|
||||
/* create default meta table with a dummy table, and then close the loop */
|
||||
sethvalue(defaultmeta(L), NULL);
|
||||
defaultmeta(L)->tt = LUA_TTABLE;
|
||||
sethvalue(defaultmeta(L), luaH_new(L, 0, 4));
|
||||
hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L));
|
||||
sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */
|
||||
@@ -85,7 +119,7 @@ static void f_luaopen (lua_State *L, void *ud) {
|
||||
luaT_init(L);
|
||||
luaX_init(L);
|
||||
luaS_fix(luaS_newliteral(L, MEMERRMSG));
|
||||
G(L)->GCthreshold = 4*G(L)->nblocks;
|
||||
g->GCthreshold = 4*G(L)->nblocks;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,46 +128,62 @@ static void preinit_state (lua_State *L) {
|
||||
L->stacksize = 0;
|
||||
L->errorJmp = NULL;
|
||||
L->hook = NULL;
|
||||
L->hookmask = 0;
|
||||
setallowhook(L, 1);
|
||||
L->hookmask = L->hookinit = 0;
|
||||
L->basehookcount = 0;
|
||||
L->allowhook = 1;
|
||||
resethookcount(L);
|
||||
L->openupval = NULL;
|
||||
L->size_ci = 0;
|
||||
L->nCcalls = 0;
|
||||
L->base_ci = L->ci = NULL;
|
||||
L->errfunc = 0;
|
||||
setnilvalue(defaultmeta(L));
|
||||
setnilvalue(gt(L));
|
||||
setnilvalue(registry(L));
|
||||
}
|
||||
|
||||
|
||||
LUA_API lua_State *lua_newthread (lua_State *OL) {
|
||||
lua_State *L;
|
||||
lua_lock(OL);
|
||||
L = luaM_new(OL, lua_State);
|
||||
preinit_state(L);
|
||||
L->l_G = OL->l_G;
|
||||
OL->next->previous = L; /* insert L into linked list */
|
||||
L->next = OL->next;
|
||||
OL->next = L;
|
||||
L->previous = OL;
|
||||
stack_init(L, OL); /* init stack */
|
||||
setobj(defaultmeta(L), defaultmeta(OL)); /* share default meta table */
|
||||
setobj(gt(L), gt(OL)); /* share table of globals */
|
||||
setobj(registry(L), registry(OL)); /* share registry */
|
||||
lua_unlock(OL);
|
||||
lua_userstateopen(L);
|
||||
return L;
|
||||
static void close_state (lua_State *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);
|
||||
}
|
||||
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_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;
|
||||
stack_init(L1, L); /* init stack */
|
||||
setobj2n(gt(L1), gt(L)); /* share table of globals */
|
||||
return L1;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
LUA_API lua_State *lua_open (void) {
|
||||
lua_State *L;
|
||||
L = luaM_new(NULL, lua_State);
|
||||
lua_State *L = mallocstate(NULL);
|
||||
if (L) { /* allocation OK? */
|
||||
L->tt = LUA_TTHREAD;
|
||||
preinit_state(L);
|
||||
L->l_G = NULL;
|
||||
L->next = L->previous = L;
|
||||
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
|
||||
/* memory allocation error: free partial state */
|
||||
close_state(L);
|
||||
@@ -145,48 +195,11 @@ LUA_API lua_State *lua_open (void) {
|
||||
}
|
||||
|
||||
|
||||
void luaE_closethread (lua_State *OL, lua_State *L) {
|
||||
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
||||
lua_assert(L->openupval == NULL);
|
||||
L->previous->next = L->next;
|
||||
L->next->previous = L->previous;
|
||||
luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
|
||||
luaM_freearray(OL, L->stack, L->stacksize, TObject);
|
||||
luaM_freelem(OL, L);
|
||||
}
|
||||
|
||||
|
||||
static void close_state (lua_State *L) {
|
||||
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
||||
if (G(L)) { /* close global state */
|
||||
luaC_collect(L, 1); /* collect all elements */
|
||||
lua_assert(G(L)->rootproto == NULL);
|
||||
lua_assert(G(L)->rootudata == NULL);
|
||||
lua_assert(G(L)->rootcl == NULL);
|
||||
lua_assert(G(L)->rootupval == NULL);
|
||||
lua_assert(G(L)->roottable == NULL);
|
||||
luaS_freeall(L);
|
||||
luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
|
||||
luaM_freelem(NULL, L->l_G);
|
||||
}
|
||||
luaE_closethread(NULL, L);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_closethread (lua_State *L, lua_State *thread) {
|
||||
lua_lock(L);
|
||||
if (L == thread) luaG_runerror(L, "cannot close only thread of a state");
|
||||
luaE_closethread(L, thread);
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_close (lua_State *L) {
|
||||
lua_lock(L);
|
||||
L = G(L)->mainthread; /* only the main thread can be closed */
|
||||
luaC_callallgcTM(L); /* call GC tag methods for all udata */
|
||||
lua_assert(G(L)->tmudata == NULL);
|
||||
while (L->next != L) /* then, close all other threads */
|
||||
luaE_closethread(L, L->next);
|
||||
close_state(L);
|
||||
}
|
||||
|
||||
|
||||
112
lstate.h
112
lstate.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstate.h,v 1.93 2002/08/07 19:22:39 roberto Exp roberto $
|
||||
** $Id: lstate.h,v 1.107 2002/11/22 18:01:46 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -11,15 +11,16 @@
|
||||
|
||||
#include "lobject.h"
|
||||
#include "ltm.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
/*
|
||||
** macros for thread syncronization inside Lua core machine:
|
||||
** all accesses to the global state and to global objects are syncronized.
|
||||
** macros for thread synchronization inside Lua core machine:
|
||||
** all accesses to the global state and to global objects are synchronized.
|
||||
** Because threads can read the stack of other threads
|
||||
** (when running garbage collection),
|
||||
** a thread must also syncronize any write-access to its own stack.
|
||||
** Unsyncronized accesses are allowed only when reading its own stack,
|
||||
** a thread must also synchronize any write-access to its own stack.
|
||||
** Unsynchronized accesses are allowed only when reading its own stack,
|
||||
** or when reading immutable fields from global objects
|
||||
** (such as string values and udata values).
|
||||
*/
|
||||
@@ -31,12 +32,6 @@
|
||||
#define lua_unlock(L) ((void) 0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** macro to allow the inclusion of user information in Lua state
|
||||
*/
|
||||
#ifndef LUA_USERSTATE
|
||||
#define LUA_USERSTATE
|
||||
#endif
|
||||
|
||||
#ifndef lua_userstateopen
|
||||
#define lua_userstateopen(l)
|
||||
@@ -47,21 +42,14 @@
|
||||
struct lua_longjmp; /* defined in ldo.c */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** array of `global' objects
|
||||
*/
|
||||
|
||||
#define NUMGLOBS 3
|
||||
|
||||
/* default meta table (both for tables and udata) */
|
||||
#define defaultmeta(L) (L->globs)
|
||||
#define defaultmeta(L) (&G(L)->_defaultmeta)
|
||||
|
||||
/* table of globals */
|
||||
#define gt(L) (L->globs + 1)
|
||||
#define gt(L) (&L->_gt)
|
||||
|
||||
/* registry */
|
||||
#define registry(L) (L->globs + 2)
|
||||
#define registry(L) (&G(L)->_registry)
|
||||
|
||||
|
||||
/* extra stack space to handle TM calls and some other extras */
|
||||
@@ -75,7 +63,7 @@ struct lua_longjmp; /* defined in ldo.c */
|
||||
|
||||
|
||||
typedef struct stringtable {
|
||||
TString **hash;
|
||||
GCObject **hash;
|
||||
ls_nstr nuse; /* number of elements */
|
||||
int size;
|
||||
} stringtable;
|
||||
@@ -92,10 +80,9 @@ typedef struct CallInfo {
|
||||
struct { /* for Lua functions */
|
||||
const Instruction *savedpc;
|
||||
const Instruction **pc; /* points to `pc' variable in `luaV_execute' */
|
||||
StkId *pb; /* points to `base' variable in `luaV_execute' */
|
||||
} l;
|
||||
struct { /* for C functions */
|
||||
int yield_results;
|
||||
int dummy; /* just to avoid an empty struct */
|
||||
} c;
|
||||
} u;
|
||||
} CallInfo;
|
||||
@@ -104,13 +91,14 @@ typedef struct CallInfo {
|
||||
/*
|
||||
** bit fields for `CallInfo.state'
|
||||
*/
|
||||
#define CI_C 1 /* 1 if function is a C function */
|
||||
#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 2
|
||||
#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 4
|
||||
#define CI_SAVEDPC 8 /* 1 if `savedpc' is updated */
|
||||
#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 ci_func(ci) (clvalue((ci)->base - 1))
|
||||
@@ -121,17 +109,16 @@ typedef struct CallInfo {
|
||||
*/
|
||||
typedef struct global_State {
|
||||
stringtable strt; /* hash table for strings */
|
||||
Proto *rootproto; /* list of all prototypes */
|
||||
Closure *rootcl; /* list of all closures */
|
||||
Table *roottable; /* list of all tables */
|
||||
UpVal *rootupval; /* list of closed up values */
|
||||
Udata *rootudata; /* list of all userdata */
|
||||
Udata *tmudata; /* list of userdata to be GC */
|
||||
void *Mbuffer; /* global buffer */
|
||||
size_t Mbuffsize; /* size of Mbuffer */
|
||||
GCObject *rootgc; /* list of (almost) all collectable objects */
|
||||
GCObject *rootudata; /* (separated) list of all userdata */
|
||||
GCObject *tmudata; /* list of userdata to be GC */
|
||||
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;
|
||||
struct lua_State *mainthread;
|
||||
Node dummynode[1]; /* common node array for all empty tables */
|
||||
TString *tmname[TM_N]; /* array with tag-method names */
|
||||
} global_State;
|
||||
@@ -141,8 +128,9 @@ typedef struct global_State {
|
||||
** `per thread' state
|
||||
*/
|
||||
struct lua_State {
|
||||
LUA_USERSTATE
|
||||
CommonHeader;
|
||||
StkId top; /* first free slot in the stack */
|
||||
StkId base; /* base of current function */
|
||||
global_State *l_G;
|
||||
CallInfo *ci; /* call info for current function */
|
||||
StkId stack_last; /* last free slot in the stack */
|
||||
@@ -150,23 +138,57 @@ struct lua_State {
|
||||
int stacksize;
|
||||
CallInfo *end_ci; /* points after end of ci array*/
|
||||
CallInfo *base_ci; /* array of CallInfo's */
|
||||
int size_ci; /* size of array `base_ci' */
|
||||
unsigned long hookmask;
|
||||
ls_count hookcount;
|
||||
unsigned short size_ci; /* size of array `base_ci' */
|
||||
unsigned short nCcalls; /* number of nested C calls */
|
||||
lu_byte hookmask;
|
||||
lu_byte allowhook;
|
||||
lu_byte hookinit;
|
||||
int basehookcount;
|
||||
int hookcount;
|
||||
lua_Hook hook;
|
||||
UpVal *openupval; /* list of open upvalues in this stack */
|
||||
TObject _gt; /* table of globals */
|
||||
GCObject *openupval; /* list of open upvalues in this stack */
|
||||
GCObject *gclist;
|
||||
struct lua_longjmp *errorJmp; /* current error recover point */
|
||||
ptrdiff_t errfunc; /* current error handling function (stack index) */
|
||||
lua_State *next; /* circular double linked list of states */
|
||||
lua_State *previous;
|
||||
TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */
|
||||
};
|
||||
|
||||
|
||||
#define G(L) (L->l_G)
|
||||
|
||||
|
||||
void luaE_closethread (lua_State *OL, lua_State *L);
|
||||
/*
|
||||
** Union of all collectable objects
|
||||
*/
|
||||
union GCObject {
|
||||
GCheader gch;
|
||||
union TString ts;
|
||||
union Udata u;
|
||||
union Closure cl;
|
||||
struct Table h;
|
||||
struct Proto p;
|
||||
struct UpVal uv;
|
||||
struct lua_State th; /* thread */
|
||||
};
|
||||
|
||||
|
||||
/* 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 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))
|
||||
|
||||
/* macro to convert any value into a GCObject */
|
||||
#define valtogco(v) (cast(GCObject *, (v)))
|
||||
|
||||
|
||||
lua_State *luaE_newthread (lua_State *L);
|
||||
void luaE_freethread (lua_State *L, lua_State *L1);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
35
lstring.c
35
lstring.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstring.c,v 1.73 2002/03/20 18:37:13 roberto Exp roberto $
|
||||
** $Id: lstring.c,v 1.77 2002/11/13 11:32:26 roberto Exp roberto $
|
||||
** String table (keeps all strings handled by Lua)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define lstring_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lmem.h"
|
||||
@@ -23,19 +25,19 @@ void luaS_freeall (lua_State *L) {
|
||||
|
||||
|
||||
void luaS_resize (lua_State *L, int newsize) {
|
||||
TString **newhash = luaM_newvector(L, newsize, TString *);
|
||||
GCObject **newhash = luaM_newvector(L, newsize, GCObject *);
|
||||
stringtable *tb = &G(L)->strt;
|
||||
int i;
|
||||
for (i=0; i<newsize; i++) newhash[i] = NULL;
|
||||
/* rehash */
|
||||
for (i=0; i<tb->size; i++) {
|
||||
TString *p = tb->hash[i];
|
||||
GCObject *p = tb->hash[i];
|
||||
while (p) { /* for each node in the list */
|
||||
TString *next = p->tsv.nexthash; /* save next */
|
||||
lu_hash h = p->tsv.hash;
|
||||
GCObject *next = p->gch.next; /* save next */
|
||||
lu_hash h = gcotots(p)->tsv.hash;
|
||||
int h1 = lmod(h, newsize); /* new position */
|
||||
lua_assert(cast(int, h%newsize) == lmod(h, newsize));
|
||||
p->tsv.nexthash = newhash[h1]; /* chain it in new position */
|
||||
p->gch.next = newhash[h1]; /* chain it */
|
||||
newhash[h1] = p;
|
||||
p = next;
|
||||
}
|
||||
@@ -49,16 +51,17 @@ void luaS_resize (lua_State *L, int newsize) {
|
||||
static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
|
||||
TString *ts = cast(TString *, luaM_malloc(L, sizestring(l)));
|
||||
stringtable *tb;
|
||||
ts->tsv.nexthash = NULL;
|
||||
ts->tsv.len = l;
|
||||
ts->tsv.hash = h;
|
||||
ts->tsv.marked = 0;
|
||||
ts->tsv.tt = LUA_TSTRING;
|
||||
ts->tsv.reserved = 0;
|
||||
memcpy(ts+1, str, l*sizeof(char));
|
||||
((char *)(ts+1))[l] = '\0'; /* ending 0 */
|
||||
tb = &G(L)->strt;
|
||||
h = lmod(h, tb->size);
|
||||
ts->tsv.nexthash = tb->hash[h]; /* chain new entry */
|
||||
tb->hash[h] = ts;
|
||||
ts->tsv.next = tb->hash[h]; /* chain new entry */
|
||||
tb->hash[h] = valtogco(ts);
|
||||
tb->nuse++;
|
||||
if (tb->nuse > cast(ls_nstr, tb->size) && tb->size <= MAX_INT/2)
|
||||
luaS_resize(L, tb->size*2); /* too crowded */
|
||||
@@ -67,15 +70,16 @@ 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) {
|
||||
TString *ts;
|
||||
GCObject *o;
|
||||
lu_hash h = (lu_hash)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 */
|
||||
h = h ^ ((h<<5)+(h>>2)+(unsigned char)(str[l1-1]));
|
||||
for (ts = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
|
||||
ts != NULL;
|
||||
ts = ts->tsv.nexthash) {
|
||||
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))
|
||||
return ts;
|
||||
}
|
||||
@@ -85,13 +89,14 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
|
||||
|
||||
Udata *luaS_newudata (lua_State *L, size_t s) {
|
||||
Udata *u;
|
||||
s = (s+3) & (~(size_t)3); /* make sure size is multiple of 4 */
|
||||
u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
|
||||
u->uv.marked = (1<<1); /* is not finalized */
|
||||
u->uv.tt = LUA_TUSERDATA;
|
||||
u->uv.len = s;
|
||||
u->uv.metatable = hvalue(defaultmeta(L));
|
||||
/* chain it on udata list */
|
||||
u->uv.next = G(L)->rootudata;
|
||||
G(L)->rootudata = u;
|
||||
G(L)->rootudata = valtogco(u);
|
||||
return u;
|
||||
}
|
||||
|
||||
|
||||
12
lstring.h
12
lstring.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstring.h,v 1.35 2001/11/28 20:13:13 roberto Exp roberto $
|
||||
** $Id: lstring.h,v 1.36 2002/04/30 13:01:48 roberto Exp roberto $
|
||||
** String table (keep all strings handled by Lua)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -13,14 +13,6 @@
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** any TString with mark>=FIXMARK is never collected.
|
||||
** Marks>=RESERVEDMARK are used to identify reserved words.
|
||||
*/
|
||||
#define FIXMARK 2
|
||||
#define RESERVEDMARK 3
|
||||
|
||||
|
||||
#define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \
|
||||
(cast(lu_mem, l)+1)*sizeof(char))
|
||||
|
||||
@@ -30,7 +22,7 @@
|
||||
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
|
||||
(sizeof(s)/sizeof(char))-1))
|
||||
|
||||
#define luaS_fix(s) ((s)->tsv.marked = FIXMARK)
|
||||
#define luaS_fix(s) ((s)->tsv.marked |= (1<<4))
|
||||
|
||||
void luaS_resize (lua_State *L, int newsize);
|
||||
Udata *luaS_newudata (lua_State *L, size_t s);
|
||||
|
||||
196
lstrlib.c
196
lstrlib.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstrlib.c,v 1.86 2002/06/25 19:16:44 roberto Exp roberto $
|
||||
** $Id: lstrlib.c,v 1.91 2002/11/25 17:33:33 roberto Exp roberto $
|
||||
** Standard library for string operations and pattern-matching
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define lstrlib_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
@@ -28,7 +30,7 @@ typedef long sint32; /* a signed version for size_t */
|
||||
|
||||
static int str_len (lua_State *L) {
|
||||
size_t l;
|
||||
luaL_check_lstr(L, 1, &l);
|
||||
luaL_checklstring(L, 1, &l);
|
||||
lua_pushnumber(L, l);
|
||||
return 1;
|
||||
}
|
||||
@@ -42,9 +44,9 @@ static sint32 posrelat (sint32 pos, size_t len) {
|
||||
|
||||
static int str_sub (lua_State *L) {
|
||||
size_t l;
|
||||
const char *s = luaL_check_lstr(L, 1, &l);
|
||||
sint32 start = posrelat(luaL_check_long(L, 2), l);
|
||||
sint32 end = posrelat(luaL_opt_long(L, 3, -1), 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);
|
||||
if (start < 1) start = 1;
|
||||
if (end > (sint32)l) end = l;
|
||||
if (start <= end)
|
||||
@@ -58,7 +60,7 @@ static int str_lower (lua_State *L) {
|
||||
size_t l;
|
||||
size_t i;
|
||||
luaL_Buffer b;
|
||||
const char *s = luaL_check_lstr(L, 1, &l);
|
||||
const char *s = luaL_checklstring(L, 1, &l);
|
||||
luaL_buffinit(L, &b);
|
||||
for (i=0; i<l; i++)
|
||||
luaL_putchar(&b, tolower(uchar(s[i])));
|
||||
@@ -71,7 +73,7 @@ static int str_upper (lua_State *L) {
|
||||
size_t l;
|
||||
size_t i;
|
||||
luaL_Buffer b;
|
||||
const char *s = luaL_check_lstr(L, 1, &l);
|
||||
const char *s = luaL_checklstring(L, 1, &l);
|
||||
luaL_buffinit(L, &b);
|
||||
for (i=0; i<l; i++)
|
||||
luaL_putchar(&b, toupper(uchar(s[i])));
|
||||
@@ -82,8 +84,8 @@ static int str_upper (lua_State *L) {
|
||||
static int str_rep (lua_State *L) {
|
||||
size_t l;
|
||||
luaL_Buffer b;
|
||||
const char *s = luaL_check_lstr(L, 1, &l);
|
||||
int n = luaL_check_int(L, 2);
|
||||
const char *s = luaL_checklstring(L, 1, &l);
|
||||
int n = luaL_checkint(L, 2);
|
||||
luaL_buffinit(L, &b);
|
||||
while (n-- > 0)
|
||||
luaL_addlstring(&b, s, l);
|
||||
@@ -94,9 +96,9 @@ static int str_rep (lua_State *L) {
|
||||
|
||||
static int str_byte (lua_State *L) {
|
||||
size_t l;
|
||||
const char *s = luaL_check_lstr(L, 1, &l);
|
||||
sint32 pos = posrelat(luaL_opt_long(L, 2, 1), l);
|
||||
luaL_arg_check(L, 0 < pos && (size_t)(pos) <= l, 2, "out of range");
|
||||
const char *s = luaL_checklstring(L, 1, &l);
|
||||
sint32 pos = posrelat(luaL_optlong(L, 2, 1), l);
|
||||
luaL_argcheck(L, 0 < pos && (size_t)(pos) <= l, 2, "out of range");
|
||||
lua_pushnumber(L, uchar(s[pos-1]));
|
||||
return 1;
|
||||
}
|
||||
@@ -108,8 +110,8 @@ static int str_char (lua_State *L) {
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
for (i=1; i<=n; i++) {
|
||||
int c = luaL_check_int(L, i);
|
||||
luaL_arg_check(L, uchar(c) == c, i, "invalid value");
|
||||
int c = luaL_checkint(L, i);
|
||||
luaL_argcheck(L, uchar(c) == c, i, "invalid value");
|
||||
luaL_putchar(&b, uchar(c));
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
@@ -117,6 +119,24 @@ static int str_char (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int writer (lua_State *L, const void* b, size_t size, void* B) {
|
||||
(void)L;
|
||||
luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int str_dump (lua_State *L) {
|
||||
luaL_Buffer b;
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
luaL_buffinit(L,&b);
|
||||
if (!lua_dump(L, writer, &b))
|
||||
luaL_error(L, "unable to dump given function");
|
||||
luaL_pushresult(&b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
@@ -166,11 +186,12 @@ static int capture_to_close (MatchState *ms) {
|
||||
|
||||
static const char *luaI_classend (MatchState *ms, const char *p) {
|
||||
switch (*p++) {
|
||||
case ESC:
|
||||
case ESC: {
|
||||
if (*p == '\0')
|
||||
luaL_error(ms->L, "malformed pattern (ends with `%')");
|
||||
return p+1;
|
||||
case '[':
|
||||
}
|
||||
case '[': {
|
||||
if (*p == '^') p++;
|
||||
do { /* look for a `]' */
|
||||
if (*p == '\0')
|
||||
@@ -179,8 +200,10 @@ static const char *luaI_classend (MatchState *ms, const char *p) {
|
||||
p++; /* skip escapes (e.g. `%]') */
|
||||
} while (*p != ']');
|
||||
return p+1;
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,14 +252,10 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
|
||||
|
||||
static int luaI_singlematch (int c, const char *p, const char *ep) {
|
||||
switch (*p) {
|
||||
case '.': /* matches any char */
|
||||
return 1;
|
||||
case ESC:
|
||||
return match_class(c, *(p+1));
|
||||
case '[':
|
||||
return matchbracketclass(c, p, ep-1);
|
||||
default:
|
||||
return (uchar(*p) == c);
|
||||
case '.': return 1; /* matches any char */
|
||||
case ESC: return match_class(c, *(p+1));
|
||||
case '[': return matchbracketclass(c, p, ep-1);
|
||||
default: return (uchar(*p) == c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,31 +350,51 @@ static const char *match_capture (MatchState *ms, const char *s, int l) {
|
||||
static const char *match (MatchState *ms, const char *s, const char *p) {
|
||||
init: /* using goto's to optimize tail recursion */
|
||||
switch (*p) {
|
||||
case '(': /* start capture */
|
||||
case '(': { /* start capture */
|
||||
if (*(p+1) == ')') /* position capture? */
|
||||
return start_capture(ms, s, p+2, CAP_POSITION);
|
||||
else
|
||||
return start_capture(ms, s, p+1, CAP_UNFINISHED);
|
||||
case ')': /* end capture */
|
||||
}
|
||||
case ')': { /* end capture */
|
||||
return end_capture(ms, s, p+1);
|
||||
case ESC: /* may be %[0-9] or %b */
|
||||
if (isdigit(uchar(*(p+1)))) { /* capture? */
|
||||
s = match_capture(ms, s, *(p+1));
|
||||
if (s == NULL) return NULL;
|
||||
p+=2; goto init; /* else return match(ms, s, p+2) */
|
||||
}
|
||||
case ESC: {
|
||||
switch (*(p+1)) {
|
||||
case 'b': { /* balanced string? */
|
||||
s = matchbalance(ms, s, p+2);
|
||||
if (s == NULL) return NULL;
|
||||
p+=4; goto init; /* else return match(ms, s, p+4); */
|
||||
}
|
||||
case 'f': { /* frontier? */
|
||||
const char *ep; char previous;
|
||||
p += 2;
|
||||
if (*p != '[')
|
||||
luaL_error(ms->L, "missing `[' after `%%f' in pattern");
|
||||
ep = luaI_classend(ms, p); /* points to what is next */
|
||||
previous = (s == ms->src_init) ? '\0' : *(s-1);
|
||||
if (matchbracketclass(uchar(previous), p, ep-1) ||
|
||||
!matchbracketclass(uchar(*s), p, ep-1)) return NULL;
|
||||
p=ep; goto init; /* else return match(ms, s, ep); */
|
||||
}
|
||||
default: {
|
||||
if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
|
||||
s = match_capture(ms, s, *(p+1));
|
||||
if (s == NULL) return NULL;
|
||||
p+=2; goto init; /* else return match(ms, s, p+2) */
|
||||
}
|
||||
goto dflt; /* case default */
|
||||
}
|
||||
}
|
||||
else if (*(p+1) == 'b') { /* balanced string? */
|
||||
s = matchbalance(ms, s, p+2);
|
||||
if (s == NULL) return NULL;
|
||||
p+=4; goto init; /* else return match(ms, s, p+4); */
|
||||
}
|
||||
else goto dflt; /* case default */
|
||||
case '\0': /* end of pattern */
|
||||
}
|
||||
case '\0': { /* end of pattern */
|
||||
return s; /* match succeeded */
|
||||
case '$':
|
||||
}
|
||||
case '$': {
|
||||
if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
|
||||
return (s == ms->src_end) ? s : NULL; /* check end of string */
|
||||
else goto dflt;
|
||||
}
|
||||
default: dflt: { /* it is a pattern item */
|
||||
const char *ep = luaI_classend(ms, p); /* points to what is next */
|
||||
int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep);
|
||||
@@ -366,15 +405,19 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
|
||||
return res;
|
||||
p=ep+1; goto init; /* else return match(ms, s, ep+1); */
|
||||
}
|
||||
case '*': /* 0 or more repetitions */
|
||||
case '*': { /* 0 or more repetitions */
|
||||
return max_expand(ms, s, p, ep);
|
||||
case '+': /* 1 or more repetitions */
|
||||
}
|
||||
case '+': { /* 1 or more repetitions */
|
||||
return (m ? max_expand(ms, s+1, p, ep) : NULL);
|
||||
case '-': /* 0 or more repetitions (minimum) */
|
||||
}
|
||||
case '-': { /* 0 or more repetitions (minimum) */
|
||||
return min_expand(ms, s, p, ep);
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
if (!m) return NULL;
|
||||
s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -416,7 +459,7 @@ static void push_onecapture (MatchState *ms, int i) {
|
||||
|
||||
static int push_captures (MatchState *ms, const char *s, const char *e) {
|
||||
int i;
|
||||
luaL_check_stack(ms->L, ms->level, "too many captures");
|
||||
luaL_checkstack(ms->L, ms->level, "too many captures");
|
||||
if (ms->level == 0 && s) { /* no explicit captures? */
|
||||
lua_pushlstring(ms->L, s, e-s); /* return whole match */
|
||||
return 1;
|
||||
@@ -431,10 +474,10 @@ static int push_captures (MatchState *ms, const char *s, const char *e) {
|
||||
|
||||
static int str_find (lua_State *L) {
|
||||
size_t l1, l2;
|
||||
const char *s = luaL_check_lstr(L, 1, &l1);
|
||||
const char *p = luaL_check_lstr(L, 2, &l2);
|
||||
sint32 init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1;
|
||||
luaL_arg_check(L, 0 <= init && (size_t)(init) <= l1, 3, "out of range");
|
||||
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;
|
||||
luaL_argcheck(L, 0 <= init && (size_t)(init) <= l1, 3, "out of range");
|
||||
if (lua_toboolean(L, 4) || /* explicit request? */
|
||||
strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */
|
||||
/* do a plain search */
|
||||
@@ -494,8 +537,8 @@ static int gfind_aux (lua_State *L) {
|
||||
|
||||
|
||||
static int gfind (lua_State *L) {
|
||||
luaL_check_string(L, 1);
|
||||
luaL_check_string(L, 2);
|
||||
luaL_checkstring(L, 1);
|
||||
luaL_checkstring(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_pushnumber(L, 0);
|
||||
lua_pushcclosure(L, gfind_aux, 3);
|
||||
@@ -540,14 +583,14 @@ static void add_s (MatchState *ms, luaL_Buffer *b,
|
||||
|
||||
static int str_gsub (lua_State *L) {
|
||||
size_t srcl;
|
||||
const char *src = luaL_check_lstr(L, 1, &srcl);
|
||||
const char *p = luaL_check_string(L, 2);
|
||||
int max_s = luaL_opt_int(L, 4, srcl+1);
|
||||
const char *src = luaL_checklstring(L, 1, &srcl);
|
||||
const char *p = luaL_checkstring(L, 2);
|
||||
int max_s = luaL_optint(L, 4, srcl+1);
|
||||
int anchor = (*p == '^') ? (p++, 1) : 0;
|
||||
int n = 0;
|
||||
MatchState ms;
|
||||
luaL_Buffer b;
|
||||
luaL_arg_check(L,
|
||||
luaL_argcheck(L,
|
||||
lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)),
|
||||
3, "string or function expected");
|
||||
luaL_buffinit(L, &b);
|
||||
@@ -586,16 +629,23 @@ static int str_gsub (lua_State *L) {
|
||||
|
||||
static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
|
||||
size_t l;
|
||||
const char *s = luaL_check_lstr(L, arg, &l);
|
||||
const char *s = luaL_checklstring(L, arg, &l);
|
||||
luaL_putchar(b, '"');
|
||||
while (l--) {
|
||||
switch (*s) {
|
||||
case '"': case '\\': case '\n':
|
||||
case '"': case '\\': case '\n': {
|
||||
luaL_putchar(b, '\\');
|
||||
luaL_putchar(b, *s);
|
||||
break;
|
||||
case '\0': luaL_addlstring(b, "\\000", 4); break;
|
||||
default: luaL_putchar(b, *s);
|
||||
}
|
||||
case '\0': {
|
||||
luaL_addlstring(b, "\\000", 4);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
luaL_putchar(b, *s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
}
|
||||
@@ -629,7 +679,7 @@ static const char *scanformat (lua_State *L, const char *strfrmt,
|
||||
static int str_format (lua_State *L) {
|
||||
int arg = 1;
|
||||
size_t sfl;
|
||||
const char *strfrmt = luaL_check_lstr(L, arg, &sfl);
|
||||
const char *strfrmt = luaL_checklstring(L, arg, &sfl);
|
||||
const char *strfrmt_end = strfrmt+sfl;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
@@ -647,22 +697,26 @@ static int str_format (lua_State *L) {
|
||||
arg++;
|
||||
strfrmt = scanformat(L, strfrmt, form, &hasprecision);
|
||||
switch (*strfrmt++) {
|
||||
case 'c': case 'd': case 'i':
|
||||
sprintf(buff, form, luaL_check_int(L, arg));
|
||||
case 'c': case 'd': case 'i': {
|
||||
sprintf(buff, form, luaL_checkint(L, arg));
|
||||
break;
|
||||
case 'o': case 'u': case 'x': case 'X':
|
||||
sprintf(buff, form, (unsigned int)(luaL_check_number(L, arg)));
|
||||
}
|
||||
case 'o': case 'u': case 'x': case 'X': {
|
||||
sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg)));
|
||||
break;
|
||||
}
|
||||
case 'e': case 'E': case 'f':
|
||||
case 'g': case 'G':
|
||||
sprintf(buff, form, luaL_check_number(L, arg));
|
||||
case 'g': case 'G': {
|
||||
sprintf(buff, form, luaL_checknumber(L, arg));
|
||||
break;
|
||||
case 'q':
|
||||
}
|
||||
case 'q': {
|
||||
luaI_addquoted(L, &b, arg);
|
||||
continue; /* skip the `addsize' at the end */
|
||||
}
|
||||
case 's': {
|
||||
size_t l;
|
||||
const char *s = luaL_check_lstr(L, arg, &l);
|
||||
const char *s = luaL_checklstring(L, arg, &l);
|
||||
if (!hasprecision && l >= 100) {
|
||||
/* no precision and string is too long to be formatted;
|
||||
keep original string */
|
||||
@@ -675,8 +729,9 @@ static int str_format (lua_State *L) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
default: /* also treat cases `pnLlh' */
|
||||
default: { /* also treat cases `pnLlh' */
|
||||
return luaL_error(L, "invalid option in `format'");
|
||||
}
|
||||
}
|
||||
luaL_addlstring(&b, buff, strlen(buff));
|
||||
}
|
||||
@@ -695,6 +750,7 @@ static const luaL_reg strlib[] = {
|
||||
{"rep", str_rep},
|
||||
{"byte", str_byte},
|
||||
{"format", str_format},
|
||||
{"dump", str_dump},
|
||||
{"find", str_find},
|
||||
{"gfind", gfind},
|
||||
{"gsub", str_gsub},
|
||||
@@ -706,7 +762,7 @@ static const luaL_reg strlib[] = {
|
||||
** Open string library
|
||||
*/
|
||||
LUALIB_API int lua_strlibopen (lua_State *L) {
|
||||
luaL_opennamedlib(L, LUA_STRLIBNAME, strlib, 0);
|
||||
luaL_openlib(L, LUA_STRLIBNAME, strlib, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
43
ltable.c
43
ltable.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltable.c,v 1.115 2002/08/05 14:45:32 roberto Exp roberto $
|
||||
** $Id: ltable.c,v 1.125 2002/12/02 12:06:10 roberto Exp roberto $
|
||||
** Lua tables (hash)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -22,11 +22,13 @@
|
||||
*/
|
||||
|
||||
|
||||
#define ltable_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lgc.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
@@ -54,15 +56,15 @@
|
||||
|
||||
|
||||
#define hashnum(t,n) \
|
||||
(node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t))))
|
||||
#define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t))))
|
||||
#define hashboolean(t,p) (node(t, lmod(p, sizenode(t))))
|
||||
(node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t))))
|
||||
#define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t))))
|
||||
#define hashboolean(t,p) (node(t, lmod(p, sizenode(t))))
|
||||
|
||||
/*
|
||||
** avoid modulus by power of 2 for pointers, as they tend to have many
|
||||
** 2 factors.
|
||||
*/
|
||||
#define hashpointer(t,p) (node(t, (IntPoint(p) % ((sizenode(t)-1)|1))))
|
||||
#define hashpointer(t,p) (node(t, (IntPoint(p) % ((sizenode(t)-1)|1))))
|
||||
|
||||
|
||||
/*
|
||||
@@ -82,15 +84,9 @@ Node *luaH_mainposition (const Table *t, const TObject *key) {
|
||||
return hashboolean(t, bvalue(key));
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
return hashpointer(t, pvalue(key));
|
||||
case LUA_TUSERDATA:
|
||||
return hashpointer(t, uvalue(key));
|
||||
case LUA_TFUNCTION:
|
||||
return hashpointer(t, clvalue(key));
|
||||
case LUA_TTABLE:
|
||||
return hashpointer(t, hvalue(key));
|
||||
default:
|
||||
return hashpointer(t, gcvalue(key));
|
||||
}
|
||||
lua_assert(0);
|
||||
return 0; /* to avoid warnings */
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +110,7 @@ static int arrayindex (const TObject *key) {
|
||||
** elements in the array part, then elements in the hash part. The
|
||||
** beginning and end of a traversal are signalled by -1.
|
||||
*/
|
||||
static int luaH_index (lua_State *L, Table *t, 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);
|
||||
@@ -132,19 +128,19 @@ static int luaH_index (lua_State *L, Table *t, const TObject *key) {
|
||||
}
|
||||
|
||||
|
||||
int luaH_next (lua_State *L, Table *t, TObject *key) {
|
||||
int luaH_next (lua_State *L, Table *t, StkId key) {
|
||||
int i = luaH_index(L, t, key); /* find original element */
|
||||
for (i++; i < t->sizearray; i++) { /* try first array part */
|
||||
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
|
||||
setnvalue(key, i+1);
|
||||
setobj(key+1, &t->array[i]);
|
||||
setobj2s(key+1, &t->array[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */
|
||||
if (!ttisnil(val(node(t, i)))) { /* a non-nil value? */
|
||||
setobj(key, key(node(t, i)));
|
||||
setobj(key+1, val(node(t, i)));
|
||||
setobj2s(key, key(node(t, i)));
|
||||
setobj2s(key+1, val(node(t, i)));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -273,7 +269,7 @@ 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]))
|
||||
setobj(luaH_setnum(L, t, i+1), &t->array[i]);
|
||||
setobjt2t(luaH_setnum(L, t, i+1), &t->array[i]);
|
||||
}
|
||||
/* shrink array */
|
||||
luaM_reallocvector(L, t->array, oldasize, nasize, TObject);
|
||||
@@ -282,7 +278,7 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
|
||||
for (i = twoto(oldhsize) - 1; i >= 0; i--) {
|
||||
Node *old = nold+i;
|
||||
if (!ttisnil(val(old)))
|
||||
setobj(luaH_set(L, t, key(old)), val(old));
|
||||
setobjt2t(luaH_set(L, t, key(old)), val(old));
|
||||
}
|
||||
if (oldhsize)
|
||||
luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
|
||||
@@ -304,12 +300,9 @@ 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));
|
||||
t->next = G(L)->roottable;
|
||||
G(L)->roottable = t;
|
||||
t->mark = t;
|
||||
t->flags = cast(lu_byte, ~0);
|
||||
t->mode = 0;
|
||||
/* temporary values (kept only if some malloc fails) */
|
||||
t->array = NULL;
|
||||
t->sizearray = 0;
|
||||
@@ -378,7 +371,7 @@ static TObject *newkey (lua_State *L, Table *t, const TObject *key) {
|
||||
mp = n;
|
||||
}
|
||||
}
|
||||
setobj(key(mp), key);
|
||||
setobj2t(key(mp), key); /* write barrier */
|
||||
lua_assert(ttisnil(val(mp)));
|
||||
for (;;) { /* correct `firstfree' */
|
||||
if (ttisnil(key(t->firstfree)))
|
||||
|
||||
4
ltable.h
4
ltable.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltable.h,v 1.41 2002/03/11 12:45:00 roberto Exp roberto $
|
||||
** $Id: ltable.h,v 1.42 2002/05/27 20:35:40 roberto Exp roberto $
|
||||
** Lua tables (hash)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -22,7 +22,7 @@ const TObject *luaH_get (Table *t, const TObject *key);
|
||||
TObject *luaH_set (lua_State *L, Table *t, const TObject *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, TObject *key);
|
||||
int luaH_next (lua_State *L, Table *t, StkId key);
|
||||
|
||||
/* exported only for debugging */
|
||||
Node *luaH_mainposition (const Table *t, const TObject *key);
|
||||
|
||||
45
ltablib.c
45
ltablib.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltablib.c,v 1.11 2002/08/06 17:06:56 roberto Exp roberto $
|
||||
** $Id: ltablib.c,v 1.16 2002/11/14 15:41:38 roberto Exp roberto $
|
||||
** Library for Table Manipulation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define ltablib_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
@@ -40,7 +42,7 @@ static void aux_setn (lua_State *L, int t, int n) {
|
||||
|
||||
static int aux_getn (lua_State *L, int t) {
|
||||
int n;
|
||||
luaL_check_type(L, t, LUA_TTABLE);
|
||||
luaL_checktype(L, t, LUA_TTABLE);
|
||||
lua_pushliteral(L, "n"); /* try t.n */
|
||||
lua_rawget(L, t);
|
||||
if ((n = checkint(L)) >= 0) return n;
|
||||
@@ -64,7 +66,7 @@ static int aux_getn (lua_State *L, int t) {
|
||||
static int luaB_foreachi (lua_State *L) {
|
||||
int i;
|
||||
int n = aux_getn(L, 1);
|
||||
luaL_check_type(L, 2, LUA_TFUNCTION);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
for (i=1; i<=n; i++) {
|
||||
lua_pushvalue(L, 2); /* function */
|
||||
lua_pushnumber(L, i); /* 1st argument */
|
||||
@@ -79,8 +81,8 @@ static int luaB_foreachi (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_foreach (lua_State *L) {
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
luaL_check_type(L, 2, LUA_TFUNCTION);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
lua_pushnil(L); /* first key */
|
||||
for (;;) {
|
||||
if (lua_next(L, 1) == 0)
|
||||
@@ -103,8 +105,8 @@ static int luaB_getn (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_setn (lua_State *L) {
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
aux_setn(L, 1, luaL_check_int(L, 2));
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
aux_setn(L, 1, luaL_checkint(L, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -116,7 +118,7 @@ static int luaB_tinsert (lua_State *L) {
|
||||
if (v == 2) /* called with only 2 arguments */
|
||||
pos = n; /* insert new element at the end */
|
||||
else {
|
||||
pos = luaL_check_int(L, 2); /* 2nd argument is the position */
|
||||
pos = luaL_checkint(L, 2); /* 2nd argument is the position */
|
||||
if (pos > n) n = pos; /* `grow' array if necessary */
|
||||
v = 3; /* function may be called with more than 3 args */
|
||||
}
|
||||
@@ -133,7 +135,7 @@ static int luaB_tinsert (lua_State *L) {
|
||||
|
||||
static int luaB_tremove (lua_State *L) {
|
||||
int n = aux_getn(L, 1);
|
||||
int pos = luaL_opt_int(L, 2, n);
|
||||
int pos = luaL_optint(L, 2, n);
|
||||
if (n <= 0) return 0; /* table is `empty' */
|
||||
aux_setn(L, 1, n-1); /* t.n = n-1 */
|
||||
lua_rawgeti(L, 1, pos); /* result = t[pos] */
|
||||
@@ -149,15 +151,16 @@ static int luaB_tremove (lua_State *L) {
|
||||
|
||||
static int str_concat (lua_State *L) {
|
||||
luaL_Buffer b;
|
||||
int n = aux_getn(L, 1);
|
||||
size_t lsep;
|
||||
const char *sep = luaL_opt_lstr(L, 2, "", &lsep);
|
||||
int i;
|
||||
const char *sep = luaL_optlstring(L, 2, "", &lsep);
|
||||
int i = luaL_optint(L, 3, 1);
|
||||
int n = luaL_optint(L, 4, 0);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
if (n == 0) n = aux_getn(L, 1);
|
||||
luaL_buffinit(L, &b);
|
||||
for (i=1; i<=n; i++) {
|
||||
for (; i <= n; i++) {
|
||||
lua_rawgeti(L, 1, i);
|
||||
luaL_arg_check(L, lua_isstring(L, -1), 1,
|
||||
"table contains non-strings");
|
||||
luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings");
|
||||
luaL_addvalue(&b);
|
||||
if (i != n)
|
||||
luaL_addlstring(&b, sep, lsep);
|
||||
@@ -261,9 +264,9 @@ static void auxsort (lua_State *L, int l, int u) {
|
||||
|
||||
static int luaB_sort (lua_State *L) {
|
||||
int n = aux_getn(L, 1);
|
||||
luaL_check_stack(L, 40, ""); /* assume array is smaller than 2^40 */
|
||||
luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
|
||||
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
|
||||
luaL_check_type(L, 2, LUA_TFUNCTION);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
lua_settop(L, 2); /* make sure there is two arguments */
|
||||
auxsort(L, 1, n);
|
||||
return 0;
|
||||
@@ -287,8 +290,12 @@ static const luaL_reg tab_funcs[] = {
|
||||
|
||||
LUALIB_API int lua_tablibopen (lua_State *L) {
|
||||
lua_newtable(L); /* create N (table to store num. elements in tables) */
|
||||
lua_setmode(L, -1, "k"); /* make it a weak table */
|
||||
luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1);
|
||||
lua_pushvalue(L, -1); /* `N' 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" */
|
||||
luaL_openlib(L, LUA_TABLIBNAME, tab_funcs, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
195
ltests.c
195
ltests.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltests.c,v 1.132 2002/08/06 15:32:22 roberto Exp roberto $
|
||||
** $Id: ltests.c,v 1.147 2002/12/04 17:29:05 roberto Exp roberto $
|
||||
** Internal Module for Debugging of the Lua Implementation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ltests_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
@@ -56,15 +57,25 @@ static void setnameval (lua_State *L, const char *name, int val) {
|
||||
** =======================================================================
|
||||
*/
|
||||
|
||||
|
||||
/* ensures maximum alignment for HEADER */
|
||||
#define HEADER (sizeof(union L_Umaxalign))
|
||||
|
||||
#define MARKSIZE 32
|
||||
#define MARK 0x55 /* 01010101 (a nice pattern) */
|
||||
|
||||
|
||||
#define blocksize(b) (cast(size_t *, b) - HEADER/sizeof(size_t))
|
||||
#ifndef EXTERNMEMCHECK
|
||||
/* full memory check */
|
||||
#define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */
|
||||
#define MARKSIZE 16 /* size of marks after each block */
|
||||
#define blockhead(b) (cast(char *, b) - HEADER)
|
||||
#define setsize(newblock, size) (*cast(size_t *, newblock) = size)
|
||||
#define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b))))
|
||||
#define fillmem(mem,size) memset(mem, -MARK, size)
|
||||
#else
|
||||
/* external memory check: don't do it twice */
|
||||
#define HEADER 0
|
||||
#define MARKSIZE 0
|
||||
#define blockhead(b) (b)
|
||||
#define setsize(newblock, size) /* empty */
|
||||
#define checkblocksize(b,size) (1)
|
||||
#define fillmem(mem,size) /* empty */
|
||||
#endif
|
||||
|
||||
unsigned long memdebug_numblocks = 0;
|
||||
unsigned long memdebug_total = 0;
|
||||
@@ -72,9 +83,8 @@ unsigned long memdebug_maxmem = 0;
|
||||
unsigned long memdebug_memlimit = ULONG_MAX;
|
||||
|
||||
|
||||
static void *checkblock (void *block) {
|
||||
size_t *b = blocksize(block);
|
||||
size_t size = *b;
|
||||
static void *checkblock (void *block, size_t size) {
|
||||
void *b = blockhead(block);
|
||||
int i;
|
||||
for (i=0;i<MARKSIZE;i++)
|
||||
lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */
|
||||
@@ -82,11 +92,11 @@ static void *checkblock (void *block) {
|
||||
}
|
||||
|
||||
|
||||
static void freeblock (void *block) {
|
||||
static void freeblock (void *block, size_t size) {
|
||||
if (block) {
|
||||
size_t size = *blocksize(block);
|
||||
block = checkblock(block);
|
||||
memset(block, -1, size+HEADER+MARKSIZE); /* erase block */
|
||||
lua_assert(checkblocksize(block, size));
|
||||
block = checkblock(block, size);
|
||||
fillmem(block, size+HEADER+MARKSIZE); /* erase block */
|
||||
free(block); /* free original block */
|
||||
memdebug_numblocks--;
|
||||
memdebug_total -= size;
|
||||
@@ -95,35 +105,34 @@ static void freeblock (void *block) {
|
||||
|
||||
|
||||
void *debug_realloc (void *block, size_t oldsize, size_t size) {
|
||||
lua_assert((oldsize == 0) == (block == NULL));
|
||||
lua_assert(oldsize == 0 || oldsize == *blocksize(block));
|
||||
lua_assert(oldsize == 0 || checkblocksize(block, oldsize));
|
||||
/* ISO does not specify what realloc(NULL, 0) does */
|
||||
lua_assert(block != NULL || size > 0);
|
||||
if (size == 0) {
|
||||
freeblock(block);
|
||||
freeblock(block, oldsize);
|
||||
return NULL;
|
||||
}
|
||||
else if (memdebug_total+size-oldsize > memdebug_memlimit)
|
||||
else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit)
|
||||
return NULL; /* to test memory allocation errors */
|
||||
else {
|
||||
void *newblock;
|
||||
int i;
|
||||
size_t realsize = HEADER+size+MARKSIZE;
|
||||
size_t commonsize = (oldsize < size) ? oldsize : size;
|
||||
if (realsize < size) return NULL; /* overflow! */
|
||||
newblock = malloc(realsize); /* alloc a new block */
|
||||
if (newblock == NULL) return NULL;
|
||||
if (oldsize > size) oldsize = size;
|
||||
if (block) {
|
||||
memcpy(cast(char *, newblock)+HEADER, block, oldsize);
|
||||
freeblock(block); /* erase (and check) old copy */
|
||||
memcpy(cast(char *, newblock)+HEADER, block, commonsize);
|
||||
freeblock(block, oldsize); /* erase (and check) old copy */
|
||||
}
|
||||
/* initialize new part of the block with something `weird' */
|
||||
memset(cast(char *, newblock)+HEADER+oldsize, -MARK, size-oldsize);
|
||||
fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize);
|
||||
memdebug_total += size;
|
||||
if (memdebug_total > memdebug_maxmem)
|
||||
memdebug_maxmem = memdebug_total;
|
||||
memdebug_numblocks++;
|
||||
*cast(size_t *, newblock) = size;
|
||||
setsize(newblock, size);
|
||||
for (i=0;i<MARKSIZE;i++)
|
||||
*(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i);
|
||||
return cast(char *, newblock)+HEADER;
|
||||
@@ -179,7 +188,7 @@ void luaI_printcode (Proto *pt, int size) {
|
||||
static int listcode (lua_State *L) {
|
||||
int pc;
|
||||
Proto *p;
|
||||
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
1, "Lua function expected");
|
||||
p = clvalue(index(L, 1))->l.p;
|
||||
lua_newtable(L);
|
||||
@@ -198,7 +207,7 @@ static int listcode (lua_State *L) {
|
||||
static int listk (lua_State *L) {
|
||||
Proto *p;
|
||||
int i;
|
||||
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
1, "Lua function expected");
|
||||
p = clvalue(index(L, 1))->l.p;
|
||||
lua_newtable(L);
|
||||
@@ -213,10 +222,10 @@ static int listk (lua_State *L) {
|
||||
|
||||
static int listlocals (lua_State *L) {
|
||||
Proto *p;
|
||||
int pc = luaL_check_int(L, 2) - 1;
|
||||
int pc = luaL_checkint(L, 2) - 1;
|
||||
int i = 0;
|
||||
const char *name;
|
||||
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
|
||||
1, "Lua function expected");
|
||||
p = clvalue(index(L, 1))->l.p;
|
||||
while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
|
||||
@@ -249,7 +258,7 @@ static int mem_query (lua_State *L) {
|
||||
return 3;
|
||||
}
|
||||
else {
|
||||
memdebug_memlimit = luaL_check_int(L, 1);
|
||||
memdebug_memlimit = luaL_checkint(L, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -257,13 +266,13 @@ static int mem_query (lua_State *L) {
|
||||
|
||||
static int hash_query (lua_State *L) {
|
||||
if (lua_isnone(L, 2)) {
|
||||
luaL_arg_check(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
|
||||
luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
|
||||
lua_pushnumber(L, tsvalue(index(L, 1))->tsv.hash);
|
||||
}
|
||||
else {
|
||||
TObject *o = index(L, 1);
|
||||
Table *t;
|
||||
luaL_check_type(L, 2, LUA_TTABLE);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
t = hvalue(index(L, 2));
|
||||
lua_pushnumber(L, luaH_mainposition(t, o) - t->node);
|
||||
}
|
||||
@@ -284,8 +293,8 @@ static int stacklevel (lua_State *L) {
|
||||
|
||||
static int table_query (lua_State *L) {
|
||||
const Table *t;
|
||||
int i = luaL_opt_int(L, 2, -1);
|
||||
luaL_check_type(L, 1, LUA_TTABLE);
|
||||
int i = luaL_optint(L, 2, -1);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
t = hvalue(index(L, 1));
|
||||
if (i == -1) {
|
||||
lua_pushnumber(L, t->sizearray);
|
||||
@@ -317,17 +326,17 @@ static int table_query (lua_State *L) {
|
||||
|
||||
static int string_query (lua_State *L) {
|
||||
stringtable *tb = &G(L)->strt;
|
||||
int s = luaL_opt_int(L, 2, 0) - 1;
|
||||
int s = luaL_optint(L, 2, 0) - 1;
|
||||
if (s==-1) {
|
||||
lua_pushnumber(L ,tb->nuse);
|
||||
lua_pushnumber(L ,tb->size);
|
||||
return 2;
|
||||
}
|
||||
else if (s < tb->size) {
|
||||
TString *ts;
|
||||
GCObject *ts;
|
||||
int n = 0;
|
||||
for (ts = tb->hash[s]; ts; ts = ts->tsv.nexthash) {
|
||||
setsvalue(L->top, ts);
|
||||
for (ts = tb->hash[s]; ts; ts = ts->gch.next) {
|
||||
setsvalue2s(L->top, gcotots(ts));
|
||||
incr_top(L);
|
||||
n++;
|
||||
}
|
||||
@@ -339,8 +348,8 @@ static int string_query (lua_State *L) {
|
||||
|
||||
static int tref (lua_State *L) {
|
||||
int level = lua_gettop(L);
|
||||
int lock = luaL_opt_int(L, 2, 1);
|
||||
luaL_check_any(L, 1);
|
||||
int lock = luaL_optint(L, 2, 1);
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_pushnumber(L, lua_ref(L, lock));
|
||||
assert(lua_gettop(L) == level+1); /* +1 for result */
|
||||
@@ -349,34 +358,34 @@ static int tref (lua_State *L) {
|
||||
|
||||
static int getref (lua_State *L) {
|
||||
int level = lua_gettop(L);
|
||||
lua_getref(L, luaL_check_int(L, 1));
|
||||
lua_getref(L, luaL_checkint(L, 1));
|
||||
assert(lua_gettop(L) == level+1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int unref (lua_State *L) {
|
||||
int level = lua_gettop(L);
|
||||
lua_unref(L, luaL_check_int(L, 1));
|
||||
lua_unref(L, luaL_checkint(L, 1));
|
||||
assert(lua_gettop(L) == level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int metatable (lua_State *L) {
|
||||
luaL_check_any(L, 1);
|
||||
luaL_checkany(L, 1);
|
||||
if (lua_isnone(L, 2)) {
|
||||
if (lua_getmetatable(L, 1) == 0)
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else {
|
||||
lua_settop(L, 2);
|
||||
luaL_check_type(L, 2, LUA_TTABLE);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
lua_setmetatable(L, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int newuserdata (lua_State *L) {
|
||||
size_t size = luaL_check_int(L, 1);
|
||||
size_t size = luaL_checkint(L, 1);
|
||||
char *p = cast(char *, lua_newuserdata(L, size));
|
||||
while (size--) *p++ = '\0';
|
||||
return 1;
|
||||
@@ -384,7 +393,7 @@ static int newuserdata (lua_State *L) {
|
||||
|
||||
|
||||
static int pushuserdata (lua_State *L) {
|
||||
lua_pushlightuserdata(L, cast(void *, luaL_check_int(L, 1)));
|
||||
lua_pushlightuserdata(L, cast(void *, luaL_checkint(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -398,23 +407,22 @@ static int udataval (lua_State *L) {
|
||||
static int doonnewstack (lua_State *L) {
|
||||
lua_State *L1 = lua_newthread(L);
|
||||
size_t l;
|
||||
const char *s = luaL_check_lstr(L, 1, &l);
|
||||
const char *s = luaL_checklstring(L, 1, &l);
|
||||
int status = luaL_loadbuffer(L1, s, l, s);
|
||||
if (status == 0)
|
||||
status = lua_pcall(L1, 0, 0, 0);
|
||||
lua_pushnumber(L, status);
|
||||
lua_closethread(L, L1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int s2d (lua_State *L) {
|
||||
lua_pushnumber(L, *cast(const double *, luaL_check_string(L, 1)));
|
||||
lua_pushnumber(L, *cast(const double *, luaL_checkstring(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int d2s (lua_State *L) {
|
||||
double d = luaL_check_number(L, 1);
|
||||
double d = luaL_checknumber(L, 1);
|
||||
lua_pushlstring(L, cast(char *, &d), sizeof(d));
|
||||
return 1;
|
||||
}
|
||||
@@ -423,7 +431,7 @@ static int d2s (lua_State *L) {
|
||||
static int newstate (lua_State *L) {
|
||||
lua_State *L1 = lua_open();
|
||||
if (L1) {
|
||||
*cast(int **, L1) = &islocked; /* initialize the lock */
|
||||
lua_userstateopen(L1); /* init lock */
|
||||
lua_pushnumber(L, (unsigned long)L1);
|
||||
}
|
||||
else
|
||||
@@ -432,7 +440,7 @@ static int newstate (lua_State *L) {
|
||||
}
|
||||
|
||||
static int loadlib (lua_State *L) {
|
||||
lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_check_number(L, 1)));
|
||||
lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
|
||||
lua_register(L1, "mathlibopen", lua_mathlibopen);
|
||||
lua_register(L1, "strlibopen", lua_strlibopen);
|
||||
lua_register(L1, "iolibopen", lua_iolibopen);
|
||||
@@ -442,16 +450,16 @@ static int loadlib (lua_State *L) {
|
||||
}
|
||||
|
||||
static int closestate (lua_State *L) {
|
||||
lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_check_number(L, 1)));
|
||||
lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
|
||||
lua_close(L1);
|
||||
lua_unlock(L); /* close cannot unlock that */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int doremote (lua_State *L) {
|
||||
lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_check_number(L, 1)));
|
||||
lua_State *L1 = cast(lua_State *,cast(unsigned long,luaL_checknumber(L, 1)));
|
||||
size_t lcode;
|
||||
const char *code = luaL_check_lstr(L, 2, &lcode);
|
||||
const char *code = luaL_checklstring(L, 2, &lcode);
|
||||
int status;
|
||||
lua_settop(L1, 0);
|
||||
status = luaL_loadbuffer(L1, code, lcode, code);
|
||||
@@ -473,11 +481,22 @@ static int doremote (lua_State *L) {
|
||||
|
||||
|
||||
static int log2_aux (lua_State *L) {
|
||||
lua_pushnumber(L, luaO_log2(luaL_check_int(L, 1)));
|
||||
lua_pushnumber(L, luaO_log2(luaL_checkint(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int test_do (lua_State *L) {
|
||||
const char *p = luaL_checkstring(L, 1);
|
||||
if (*p == '@')
|
||||
lua_dofile(L, p+1);
|
||||
else
|
||||
lua_dostring(L, p);
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** function to test the API with C. It interprets a kind of assembler
|
||||
@@ -527,7 +546,7 @@ static const char *getname_aux (char *buff, const char **pc) {
|
||||
|
||||
static int testC (lua_State *L) {
|
||||
char buff[30];
|
||||
const char *pc = luaL_check_string(L, 1);
|
||||
const char *pc = luaL_checkstring(L, 1);
|
||||
for (;;) {
|
||||
const char *inst = getname;
|
||||
if EQ("") return 0;
|
||||
@@ -648,11 +667,11 @@ static int testC (lua_State *L) {
|
||||
}
|
||||
else if EQ("loadstring") {
|
||||
size_t sl;
|
||||
const char *s = luaL_check_lstr(L, getnum, &sl);
|
||||
const char *s = luaL_checklstring(L, getnum, &sl);
|
||||
luaL_loadbuffer(L, s, sl, s);
|
||||
}
|
||||
else if EQ("loadfile") {
|
||||
luaL_loadfile(L, luaL_check_string(L, getnum));
|
||||
luaL_loadfile(L, luaL_checkstring(L, getnum));
|
||||
}
|
||||
else if EQ("setmetatable") {
|
||||
lua_setmetatable(L, getnum);
|
||||
@@ -672,6 +691,50 @@ static int testC (lua_State *L) {
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** tests for yield inside hooks
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
static void yieldf (lua_State *L, lua_Debug *ar) {
|
||||
lua_yield(L, 0);
|
||||
}
|
||||
|
||||
static int setyhook (lua_State *L) {
|
||||
if (lua_isnoneornil(L, 1))
|
||||
lua_sethook(L, NULL, 0, 0); /* turn off hooks */
|
||||
else {
|
||||
const char *smask = luaL_checkstring(L, 1);
|
||||
int count = luaL_optint(L, 2, 0);
|
||||
int mask = 0;
|
||||
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
|
||||
if (count > 0) mask |= LUA_MASKCOUNT;
|
||||
lua_sethook(L, yieldf, mask, count);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int coresume (lua_State *L) {
|
||||
int status;
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||
status = lua_resume(co, 0);
|
||||
if (status != 0) {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_insert(L, -2);
|
||||
return 2; /* return false + error message */
|
||||
}
|
||||
else {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
static const struct luaL_reg tests_funcs[] = {
|
||||
{"hash", hash_query},
|
||||
@@ -683,6 +746,7 @@ static const struct luaL_reg tests_funcs[] = {
|
||||
{"stacklevel", stacklevel},
|
||||
{"querystr", string_query},
|
||||
{"querytab", table_query},
|
||||
{"doit", test_do},
|
||||
{"testC", testC},
|
||||
{"ref", tref},
|
||||
{"getref", getref},
|
||||
@@ -699,6 +763,8 @@ static const struct luaL_reg tests_funcs[] = {
|
||||
{"doremote", doremote},
|
||||
{"log2", log2_aux},
|
||||
{"totalmem", mem_query},
|
||||
{"resume", coresume},
|
||||
{"setyhook", setyhook},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -712,11 +778,20 @@ static void fim (void) {
|
||||
|
||||
|
||||
int luaB_opentests (lua_State *L) {
|
||||
*cast(int **, L) = &islocked; /* init lock */
|
||||
lua_userstateopen(L); /* init lock */
|
||||
lua_state = L; /* keep first state to be opened */
|
||||
luaL_opennamedlib(L, "T", tests_funcs, 0);
|
||||
luaL_openlib(L, "T", tests_funcs, 0);
|
||||
atexit(fim);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#undef main
|
||||
int main (int argc, char *argv[]) {
|
||||
char *limit = getenv("MEMLIMIT");
|
||||
if (limit)
|
||||
memdebug_memlimit = strtoul(limit, NULL, 10);
|
||||
l_main(argc, argv);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
19
ltests.h
19
ltests.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltests.h,v 1.14 2002/06/13 13:45:31 roberto Exp roberto $
|
||||
** $Id: ltests.h,v 1.19 2002/11/19 17:42:32 roberto Exp roberto $
|
||||
** Internal Header for Debugging of the Lua Implementation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -34,6 +34,7 @@ extern unsigned long memdebug_memlimit;
|
||||
|
||||
|
||||
#define l_realloc(b, os, s) debug_realloc(b, os, s)
|
||||
#define l_free(b, os) debug_realloc(b, os, 0)
|
||||
|
||||
void *debug_realloc (void *block, size_t oldsize, size_t size);
|
||||
|
||||
@@ -41,15 +42,21 @@ void *debug_realloc (void *block, size_t oldsize, size_t size);
|
||||
|
||||
/* test for lock/unlock */
|
||||
extern int islocked;
|
||||
#define LUA_USERSTATE int *lock;
|
||||
#define lua_userstateopen(l) if (l != NULL) *cast(int **, l) = &islocked;
|
||||
#define lua_lock(L) lua_assert((**cast(int **, L))++ == 0)
|
||||
#define lua_unlock(L) lua_assert(--(**cast(int **, L)) == 0)
|
||||
#define LUA_USERSTATE int *
|
||||
#define getlock(l) (*(cast(LUA_USERSTATE *, l) - 1))
|
||||
#define lua_userstateopen(l) if (l != NULL) getlock(l) = &islocked;
|
||||
#define lua_lock(l) lua_assert((*getlock(l))++ == 0)
|
||||
#define lua_unlock(l) lua_assert(--(*getlock(l)) == 0)
|
||||
|
||||
|
||||
int luaB_opentests (lua_State *L);
|
||||
|
||||
#define lua_userinit(L) (luaB_opentests(L) + openstdlibs(L))
|
||||
#define LUA_EXTRALIBS { "tests", luaB_opentests },
|
||||
|
||||
|
||||
/* real main will be defined at `ltests.c' */
|
||||
int l_main (int argc, char *argv[]);
|
||||
#define main l_main
|
||||
|
||||
|
||||
|
||||
|
||||
11
ltm.c
11
ltm.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltm.c,v 1.99 2002/08/05 14:09:06 roberto Exp roberto $
|
||||
** $Id: ltm.c,v 1.104 2002/11/14 11:51:50 roberto Exp roberto $
|
||||
** Tag methods
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ltm_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lobject.h"
|
||||
@@ -18,16 +20,15 @@
|
||||
|
||||
|
||||
const char *const luaT_typenames[] = {
|
||||
"nil", "number", "string", "boolean", "table",
|
||||
"function", "userdata", "userdata"
|
||||
"nil", "boolean", "userdata", "number",
|
||||
"string", "table", "function", "userdata", "thread"
|
||||
};
|
||||
|
||||
|
||||
void luaT_init (lua_State *L) {
|
||||
static const char *const luaT_eventname[] = { /* ORDER TM */
|
||||
"__index", "__newindex",
|
||||
"__gc", "__eq",
|
||||
"__gettable", "__settable",
|
||||
"__gc", "__mode", "__eq",
|
||||
"__add", "__sub", "__mul", "__div",
|
||||
"__pow", "__unm", "__lt", "__le",
|
||||
"__concat", "__call"
|
||||
|
||||
11
ltm.h
11
ltm.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltm.h,v 1.38 2002/07/01 17:06:58 roberto Exp roberto $
|
||||
** $Id: ltm.h,v 1.40 2002/09/19 20:12:47 roberto Exp roberto $
|
||||
** Tag methods
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -19,9 +19,8 @@ typedef enum {
|
||||
TM_INDEX,
|
||||
TM_NEWINDEX,
|
||||
TM_GC,
|
||||
TM_MODE,
|
||||
TM_EQ, /* last tag method with `fast' access */
|
||||
TM_GETTABLE,
|
||||
TM_SETTABLE,
|
||||
TM_ADD,
|
||||
TM_SUB,
|
||||
TM_MUL,
|
||||
@@ -37,8 +36,10 @@ typedef enum {
|
||||
|
||||
|
||||
|
||||
#define fasttm(l,et,e) \
|
||||
(((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, G(l)->tmname[e]))
|
||||
#define gfasttm(g,et,e) \
|
||||
(((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);
|
||||
|
||||
154
lua.c
154
lua.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lua.c,v 1.102 2002/08/12 17:23:12 roberto Exp roberto $
|
||||
** $Id: lua.c,v 1.112 2002/12/04 17:28:27 roberto Exp roberto $
|
||||
** Lua stand-alone interpreter
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define lua_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
@@ -47,18 +49,34 @@ static int isatty (int x) { return x==0; } /* assume stdin is a tty */
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef LUA_EXTRALIBS
|
||||
#define LUA_EXTRALIBS /* empty */
|
||||
#endif
|
||||
|
||||
|
||||
static lua_State *L = NULL;
|
||||
|
||||
static const char *progname;
|
||||
|
||||
|
||||
static lua_Hook old_hook = NULL;
|
||||
static unsigned long old_mask = 0;
|
||||
|
||||
static const luaL_reg lualibs[] = {
|
||||
{"baselib", lua_baselibopen},
|
||||
{"tablib", lua_tablibopen},
|
||||
{"iolib", lua_iolibopen},
|
||||
{"strlib", lua_strlibopen},
|
||||
{"mathlib", lua_mathlibopen},
|
||||
{"dblib", lua_dblibopen},
|
||||
/* add your libraries here */
|
||||
LUA_EXTRALIBS
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void lstop (lua_State *l, lua_Debug *ar) {
|
||||
(void)ar; /* unused arg. */
|
||||
lua_sethook(l, old_hook, old_mask);
|
||||
lua_sethook(l, NULL, 0, 0);
|
||||
luaL_error(l, "interrupted!");
|
||||
}
|
||||
|
||||
@@ -66,36 +84,31 @@ static void lstop (lua_State *l, lua_Debug *ar) {
|
||||
static void laction (int i) {
|
||||
signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
|
||||
terminate process (default action) */
|
||||
old_hook = lua_gethook(L);
|
||||
old_mask = lua_gethookmask(L);
|
||||
lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT(1));
|
||||
lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
|
||||
}
|
||||
|
||||
|
||||
static void print_usage (void) {
|
||||
fprintf(stderr,
|
||||
"usage: %s [options] [prog [args]].\n"
|
||||
"usage: %s [options] [script [args]].\n"
|
||||
"Available options are:\n"
|
||||
" - execute stdin as a file\n"
|
||||
" -e stat execute string `stat'\n"
|
||||
" -i enter interactive mode after executing `prog'\n"
|
||||
" -l name execute file `name'\n"
|
||||
" -v print version information\n"
|
||||
" -i enter interactive mode after executing `script'\n"
|
||||
" -l name load and run library `name'\n"
|
||||
" -v show version information\n"
|
||||
" -- stop handling options\n" ,
|
||||
progname);
|
||||
}
|
||||
|
||||
|
||||
static void l_message (const char *pname, const char *msg) {
|
||||
size_t l = strlen(msg);
|
||||
if (pname) fprintf(stderr, "%s: ", pname);
|
||||
fprintf(stderr, "%s", msg);
|
||||
if (l > 0 && msg[l-1] != '\n') /* does not end with newline? */
|
||||
fprintf(stderr, "\n"); /* add a newline */
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
}
|
||||
|
||||
|
||||
static void report (int status) {
|
||||
static int report (int status) {
|
||||
const char *msg;
|
||||
if (status) {
|
||||
msg = lua_tostring(L, -1);
|
||||
@@ -103,20 +116,20 @@ static void report (int status) {
|
||||
l_message(progname, msg);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int lcall (int clear) {
|
||||
static int lcall (int narg, int clear) {
|
||||
int status;
|
||||
int top = lua_gettop(L);
|
||||
lua_getglobal(L, "_TRACEBACK"); /* get traceback function */
|
||||
lua_insert(L, top); /* put it under chunk */
|
||||
int base = lua_gettop(L) - narg; /* function index */
|
||||
lua_pushliteral(L, "_TRACEBACK");
|
||||
lua_rawget(L, LUA_GLOBALSINDEX); /* get traceback function */
|
||||
lua_insert(L, base); /* put it under chunk and args */
|
||||
signal(SIGINT, laction);
|
||||
status = lua_pcall(L, 0, LUA_MULTRET, -2);
|
||||
status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
lua_remove(L, top); /* remove traceback function */
|
||||
if (status == 0 && clear)
|
||||
lua_settop(L, top); /* remove eventual results */
|
||||
lua_remove(L, base); /* remove traceback function */
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -149,9 +162,8 @@ static void getargs (char *argv[], int n) {
|
||||
|
||||
|
||||
static int docall (int status) {
|
||||
if (status == 0) status = lcall(1);
|
||||
report(status);
|
||||
return status;
|
||||
if (status == 0) status = lcall(0, 1);
|
||||
return report(status);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,6 +177,20 @@ static int dostring (const char *s, const char *name) {
|
||||
}
|
||||
|
||||
|
||||
static int load_file (const char *name) {
|
||||
lua_pushliteral(L, "require");
|
||||
lua_rawget(L, LUA_GLOBALSINDEX);
|
||||
if (!lua_isfunction(L, -1)) { /* no `require' defined? */
|
||||
lua_pop(L, 1);
|
||||
return file_input(name);
|
||||
}
|
||||
else {
|
||||
lua_pushstring(L, name);
|
||||
return report(lcall(1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** this macro can be used by some `history' system to save lines
|
||||
** read in manual input
|
||||
@@ -206,7 +232,8 @@ static int readline (lua_State *l, const char *prompt) {
|
||||
|
||||
static const char *get_prompt (int firstline) {
|
||||
const char *p = NULL;
|
||||
lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
|
||||
lua_pushstring(L, firstline ? "_PROMPT" : "_PROMPT2");
|
||||
lua_rawget(L, LUA_GLOBALSINDEX);
|
||||
p = lua_tostring(L, -1);
|
||||
if (p == NULL) p = (firstline ? PROMPT : PROMPT2);
|
||||
lua_pop(L, 1); /* remove global */
|
||||
@@ -252,7 +279,7 @@ static void manual_input (void) {
|
||||
const char *oldprogname = progname;
|
||||
progname = NULL;
|
||||
while ((status = load_string()) != -1) {
|
||||
if (status == 0) status = lcall(0);
|
||||
if (status == 0) status = lcall(0, 0);
|
||||
report(status);
|
||||
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
|
||||
lua_getglobal(L, "print");
|
||||
@@ -315,7 +342,7 @@ static int handle_argv (char *argv[], int *interactive) {
|
||||
print_usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (file_input(filename))
|
||||
if (load_file(filename))
|
||||
return EXIT_FAILURE; /* stop if file fails */
|
||||
break;
|
||||
}
|
||||
@@ -335,25 +362,21 @@ static int handle_argv (char *argv[], int *interactive) {
|
||||
} endloop:
|
||||
if (argv[i] != NULL) {
|
||||
const char *filename = argv[i];
|
||||
getargs(argv, i); /* collect remaining arguments */
|
||||
getargs(argv, i); /* collect arguments */
|
||||
lua_setglobal(L, "arg");
|
||||
return file_input(filename); /* stop scanning arguments */
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int openstdlibs (lua_State *l) {
|
||||
int res = 0;
|
||||
res += lua_baselibopen(l);
|
||||
res += lua_tablibopen(l);
|
||||
res += lua_iolibopen(l);
|
||||
res += lua_strlibopen(l);
|
||||
res += lua_mathlibopen(l);
|
||||
res += lua_dblibopen(l);
|
||||
/* add your libraries here */
|
||||
return res;
|
||||
static void openstdlibs (lua_State *l) {
|
||||
const luaL_reg *lib = lualibs;
|
||||
for (; lib->name; lib++) {
|
||||
lib->func(l); /* open library */
|
||||
lua_settop(l, 0); /* discard any results */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -367,19 +390,44 @@ static int handle_luainit (void) {
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
struct Smain {
|
||||
int argc;
|
||||
char **argv;
|
||||
int status;
|
||||
};
|
||||
|
||||
|
||||
static int pmain (lua_State *l) {
|
||||
struct Smain *s = (struct Smain *)lua_touserdata(l, 1);
|
||||
int status;
|
||||
int interactive = 0;
|
||||
(void)argc; /* to avoid warnings */
|
||||
progname = argv[0];
|
||||
L = lua_open(); /* create state */
|
||||
lua_atpanic(L, l_panic);
|
||||
lua_pop(L, lua_userinit(L)); /* open libraries, discard any results */
|
||||
progname = s->argv[0];
|
||||
L = l;
|
||||
lua_userinit(l); /* open libraries */
|
||||
status = handle_luainit();
|
||||
if (status != 0) return status;
|
||||
status = handle_argv(argv, &interactive);
|
||||
if (status == 0 && interactive) manual_input();
|
||||
lua_close(L);
|
||||
return status;
|
||||
if (status == 0) {
|
||||
status = handle_argv(s->argv, &interactive);
|
||||
if (status == 0 && interactive) manual_input();
|
||||
}
|
||||
s->status = status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
int status;
|
||||
struct Smain s;
|
||||
lua_State *l = lua_open(); /* create state */
|
||||
if (l == NULL) {
|
||||
l_message(argv[0], "cannot create state: not enough memory");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
s.argc = argc;
|
||||
s.argv = argv;
|
||||
lua_atpanic(l, l_panic);
|
||||
status = lua_cpcall(l, &pmain, &s);
|
||||
report(status);
|
||||
lua_close(l);
|
||||
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
161
lua.h
161
lua.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lua.h,v 1.153 2002/08/06 18:54:18 roberto Exp roberto $
|
||||
** $Id: lua.h,v 1.168 2002/11/26 12:53:29 roberto Exp roberto $
|
||||
** Lua - An Extensible Extension Language
|
||||
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
|
||||
** http://www.lua.org mailto:info@lua.org
|
||||
@@ -10,18 +10,13 @@
|
||||
#ifndef lua_h
|
||||
#define lua_h
|
||||
|
||||
|
||||
/* definition of `va_list' */
|
||||
#include <stdarg.h>
|
||||
|
||||
/* definition of `size_t' */
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
|
||||
#define LUA_VERSION "Lua 5.0 (alpha)"
|
||||
#define LUA_VERSION "Lua 5.0 (beta)"
|
||||
#define LUA_COPYRIGHT "Copyright (C) 1994-2002 Tecgraf, PUC-Rio"
|
||||
#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo"
|
||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +38,6 @@
|
||||
#define LUA_ERRSYNTAX 3
|
||||
#define LUA_ERRMEM 4
|
||||
#define LUA_ERRERR 5
|
||||
#define LUA_ERRTHROW 6
|
||||
|
||||
|
||||
typedef struct lua_State lua_State;
|
||||
@@ -52,9 +46,12 @@ typedef int (*lua_CFunction) (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** functions that read blocks when loading Lua chunk
|
||||
** functions that read/write blocks when loading/dumping Lua chunks
|
||||
*/
|
||||
typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *size);
|
||||
typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz);
|
||||
|
||||
typedef int (*lua_Chunkwriter) (lua_State *L, const void* p,
|
||||
size_t sz, void* ud);
|
||||
|
||||
|
||||
/*
|
||||
@@ -63,13 +60,14 @@ typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *size);
|
||||
#define LUA_TNONE (-1)
|
||||
|
||||
#define LUA_TNIL 0
|
||||
#define LUA_TNUMBER 1
|
||||
#define LUA_TSTRING 2
|
||||
#define LUA_TBOOLEAN 3
|
||||
#define LUA_TTABLE 4
|
||||
#define LUA_TFUNCTION 5
|
||||
#define LUA_TUSERDATA 6
|
||||
#define LUA_TLIGHTUSERDATA 7
|
||||
#define LUA_TBOOLEAN 1
|
||||
#define LUA_TLIGHTUSERDATA 2
|
||||
#define LUA_TNUMBER 3
|
||||
#define LUA_TSTRING 4
|
||||
#define LUA_TTABLE 5
|
||||
#define LUA_TFUNCTION 6
|
||||
#define LUA_TUSERDATA 7
|
||||
#define LUA_TTHREAD 8
|
||||
|
||||
|
||||
/* minimum Lua stack available to a C function */
|
||||
@@ -84,11 +82,12 @@ typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *size);
|
||||
#endif
|
||||
|
||||
|
||||
/* type of Numbers in Lua */
|
||||
/* type of numbers in Lua */
|
||||
#ifndef LUA_NUMBER
|
||||
#define LUA_NUMBER double
|
||||
#endif
|
||||
typedef double lua_Number;
|
||||
#else
|
||||
typedef LUA_NUMBER lua_Number;
|
||||
#endif
|
||||
|
||||
|
||||
/* mark for all API functions */
|
||||
@@ -103,7 +102,6 @@ typedef LUA_NUMBER lua_Number;
|
||||
LUA_API lua_State *lua_open (void);
|
||||
LUA_API void lua_close (lua_State *L);
|
||||
LUA_API lua_State *lua_newthread (lua_State *L);
|
||||
LUA_API void lua_closethread (lua_State *L, lua_State *thread);
|
||||
|
||||
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
|
||||
|
||||
@@ -112,35 +110,39 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
|
||||
** basic stack manipulation
|
||||
*/
|
||||
LUA_API int lua_gettop (lua_State *L);
|
||||
LUA_API void lua_settop (lua_State *L, int index);
|
||||
LUA_API void lua_pushvalue (lua_State *L, int index);
|
||||
LUA_API void lua_remove (lua_State *L, int index);
|
||||
LUA_API void lua_insert (lua_State *L, int index);
|
||||
LUA_API void lua_replace (lua_State *L, int index);
|
||||
LUA_API int lua_checkstack (lua_State *L, int size);
|
||||
LUA_API void lua_settop (lua_State *L, int idx);
|
||||
LUA_API void lua_pushvalue (lua_State *L, int idx);
|
||||
LUA_API void lua_remove (lua_State *L, int idx);
|
||||
LUA_API void lua_insert (lua_State *L, int idx);
|
||||
LUA_API void lua_replace (lua_State *L, int idx);
|
||||
LUA_API int lua_checkstack (lua_State *L, int sz);
|
||||
|
||||
LUA_API void lua_xmove (lua_State *from, lua_State *to, int n);
|
||||
|
||||
|
||||
/*
|
||||
** access functions (stack -> C)
|
||||
*/
|
||||
|
||||
LUA_API int lua_isnumber (lua_State *L, int index);
|
||||
LUA_API int lua_isstring (lua_State *L, int index);
|
||||
LUA_API int lua_iscfunction (lua_State *L, int index);
|
||||
LUA_API int lua_type (lua_State *L, int index);
|
||||
LUA_API const char *lua_typename (lua_State *L, int type);
|
||||
LUA_API int lua_isnumber (lua_State *L, int idx);
|
||||
LUA_API int lua_isstring (lua_State *L, int idx);
|
||||
LUA_API int lua_iscfunction (lua_State *L, int idx);
|
||||
LUA_API int lua_isuserdata (lua_State *L, int idx);
|
||||
LUA_API int lua_type (lua_State *L, int idx);
|
||||
LUA_API const char *lua_typename (lua_State *L, int tp);
|
||||
|
||||
LUA_API int lua_equal (lua_State *L, int index1, int index2);
|
||||
LUA_API int lua_rawequal (lua_State *L, int index1, int index2);
|
||||
LUA_API int lua_lessthan (lua_State *L, int index1, int index2);
|
||||
LUA_API int lua_equal (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int lua_rawequal (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int lua_lessthan (lua_State *L, int idx1, int idx2);
|
||||
|
||||
LUA_API lua_Number lua_tonumber (lua_State *L, int index);
|
||||
LUA_API int lua_toboolean (lua_State *L, int index);
|
||||
LUA_API const char *lua_tostring (lua_State *L, int index);
|
||||
LUA_API size_t lua_strlen (lua_State *L, int index);
|
||||
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index);
|
||||
LUA_API void *lua_touserdata (lua_State *L, int index);
|
||||
LUA_API const void *lua_topointer (lua_State *L, int index);
|
||||
LUA_API lua_Number lua_tonumber (lua_State *L, int idx);
|
||||
LUA_API int lua_toboolean (lua_State *L, int idx);
|
||||
LUA_API const char *lua_tostring (lua_State *L, int idx);
|
||||
LUA_API size_t lua_strlen (lua_State *L, int idx);
|
||||
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx);
|
||||
LUA_API void *lua_touserdata (lua_State *L, int idx);
|
||||
LUA_API lua_State *lua_tothread (lua_State *L, int idx);
|
||||
LUA_API const void *lua_topointer (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
@@ -148,7 +150,7 @@ LUA_API const void *lua_topointer (lua_State *L, int index);
|
||||
*/
|
||||
LUA_API void lua_pushnil (lua_State *L);
|
||||
LUA_API void lua_pushnumber (lua_State *L, lua_Number n);
|
||||
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len);
|
||||
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t l);
|
||||
LUA_API void lua_pushstring (lua_State *L, const char *s);
|
||||
LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
|
||||
va_list argp);
|
||||
@@ -161,24 +163,22 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p);
|
||||
/*
|
||||
** get functions (Lua -> stack)
|
||||
*/
|
||||
LUA_API void lua_gettable (lua_State *L, int index);
|
||||
LUA_API void lua_rawget (lua_State *L, int index);
|
||||
LUA_API void lua_rawgeti (lua_State *L, int index, int n);
|
||||
LUA_API void lua_gettable (lua_State *L, int idx);
|
||||
LUA_API void lua_rawget (lua_State *L, int idx);
|
||||
LUA_API void lua_rawgeti (lua_State *L, int idx, int n);
|
||||
LUA_API void lua_newtable (lua_State *L);
|
||||
LUA_API int lua_getmetatable (lua_State *L, int objindex);
|
||||
LUA_API const char *lua_getmode (lua_State *L, int index);
|
||||
LUA_API void lua_getglobals (lua_State *L, int index);
|
||||
LUA_API void lua_getglobals (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** set functions (stack -> Lua)
|
||||
*/
|
||||
LUA_API void lua_settable (lua_State *L, int index);
|
||||
LUA_API void lua_rawset (lua_State *L, int index);
|
||||
LUA_API void lua_rawseti (lua_State *L, int index, int n);
|
||||
LUA_API void lua_setmode (lua_State *L, int index, const char *mode);
|
||||
LUA_API void lua_settable (lua_State *L, int idx);
|
||||
LUA_API void lua_rawset (lua_State *L, int idx);
|
||||
LUA_API void lua_rawseti (lua_State *L, int idx, int n);
|
||||
LUA_API int lua_setmetatable (lua_State *L, int objindex);
|
||||
LUA_API int lua_setglobals (lua_State *L, int index);
|
||||
LUA_API int lua_setglobals (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
@@ -186,19 +186,21 @@ LUA_API int lua_setglobals (lua_State *L, int index);
|
||||
*/
|
||||
LUA_API void lua_call (lua_State *L, int nargs, int nresults);
|
||||
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
|
||||
LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
|
||||
LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);
|
||||
LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *dt,
|
||||
const char *chunkname);
|
||||
|
||||
LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data);
|
||||
|
||||
|
||||
/*
|
||||
** coroutine functions
|
||||
*/
|
||||
LUA_API void lua_cobegin (lua_State *L, int nargs);
|
||||
LUA_API int lua_yield (lua_State *L, int nresults);
|
||||
LUA_API int lua_resume (lua_State *L, lua_State *co);
|
||||
LUA_API int lua_resume (lua_State *L, int narg);
|
||||
|
||||
/*
|
||||
** Garbage-collection functions
|
||||
** garbage-collection functions
|
||||
*/
|
||||
LUA_API int lua_getgcthreshold (lua_State *L);
|
||||
LUA_API int lua_getgccount (lua_State *L);
|
||||
@@ -208,13 +210,15 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold);
|
||||
** miscellaneous functions
|
||||
*/
|
||||
|
||||
LUA_API const char *lua_version (void);
|
||||
|
||||
LUA_API int lua_error (lua_State *L);
|
||||
|
||||
LUA_API int lua_next (lua_State *L, int index);
|
||||
LUA_API int lua_next (lua_State *L, int idx);
|
||||
|
||||
LUA_API void lua_concat (lua_State *L, int n);
|
||||
|
||||
LUA_API void *lua_newuserdata (lua_State *L, size_t size);
|
||||
LUA_API void *lua_newuserdata (lua_State *L, size_t sz);
|
||||
|
||||
|
||||
|
||||
@@ -240,7 +244,6 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size);
|
||||
|
||||
#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION)
|
||||
#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE)
|
||||
#define lua_isuserdata(L,n) (lua_type(L,n) >= LUA_TUSERDATA)
|
||||
#define lua_islightuserdata(L,n) (lua_type(L,n) == LUA_TLIGHTUSERDATA)
|
||||
#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL)
|
||||
#define lua_isboolean(L,n) (lua_type(L,n) == LUA_TBOOLEAN)
|
||||
@@ -266,8 +269,6 @@ LUA_API int lua_pushupvalues (lua_State *L);
|
||||
#define lua_getglobal(L,s) \
|
||||
(lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX))
|
||||
|
||||
#define lua_isnull lua_isnone
|
||||
|
||||
|
||||
/* compatibility with ref system */
|
||||
|
||||
@@ -296,7 +297,7 @@ LUA_API int lua_pushupvalues (lua_State *L);
|
||||
#endif
|
||||
|
||||
#ifndef LUA_NUMBER_FMT
|
||||
#define LUA_NUMBER_FMT "%.16g"
|
||||
#define LUA_NUMBER_FMT "%.14g"
|
||||
#endif
|
||||
|
||||
/* }====================================================================== */
|
||||
@@ -308,18 +309,23 @@ LUA_API int lua_pushupvalues (lua_State *L);
|
||||
** =======================================================================
|
||||
*/
|
||||
|
||||
typedef enum lua_Hookevent {
|
||||
LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKLINE, LUA_HOOKCOUNT
|
||||
} lua_Hookevent;
|
||||
|
||||
/*
|
||||
** Event codes
|
||||
*/
|
||||
#define LUA_HOOKCALL 0
|
||||
#define LUA_HOOKRET 1
|
||||
#define LUA_HOOKLINE 2
|
||||
#define LUA_HOOKCOUNT 3
|
||||
|
||||
|
||||
#define LUA_MASKCALL (2 << LUA_HOOKCALL)
|
||||
#define LUA_MASKRET (2 << LUA_HOOKRET)
|
||||
#define LUA_MASKLINE (2 << LUA_HOOKLINE)
|
||||
#define LUA_MASKCOUNT(count) ((unsigned long)(count) << 8)
|
||||
#define lua_getmaskcount(mask) ((mask) >> 8)
|
||||
|
||||
#define LUA_MAXCOUNT ((1<<24) - 1)
|
||||
/*
|
||||
** Event masks
|
||||
*/
|
||||
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
|
||||
#define LUA_MASKRET (1 << LUA_HOOKRET)
|
||||
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
|
||||
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
|
||||
|
||||
typedef struct lua_Debug lua_Debug; /* activation record */
|
||||
|
||||
@@ -331,15 +337,16 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
|
||||
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
|
||||
|
||||
LUA_API int lua_sethook (lua_State *L, lua_Hook func, unsigned long mask);
|
||||
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
|
||||
LUA_API lua_Hook lua_gethook (lua_State *L);
|
||||
LUA_API unsigned long lua_gethookmask (lua_State *L);
|
||||
LUA_API int lua_gethookmask (lua_State *L);
|
||||
LUA_API int lua_gethookcount (lua_State *L);
|
||||
|
||||
|
||||
#define LUA_IDSIZE 60
|
||||
|
||||
struct lua_Debug {
|
||||
lua_Hookevent event;
|
||||
int event;
|
||||
const char *name; /* (n) */
|
||||
const char *namewhat; /* (n) `global', `local', `field', `method' */
|
||||
const char *what; /* (S) `Lua' function, `C' function, Lua `main' */
|
||||
|
||||
37
lundump.c
37
lundump.c
@@ -1,9 +1,11 @@
|
||||
/*
|
||||
** $Id: lundump.c,v 1.43 2002/08/07 00:36:03 lhf Exp $
|
||||
** $Id: lundump.c,v 1.57 2002/11/14 16:15:53 roberto Exp roberto $
|
||||
** load pre-compiled Lua chunks
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lundump_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
@@ -19,6 +21,7 @@
|
||||
typedef struct {
|
||||
lua_State* L;
|
||||
ZIO* Z;
|
||||
Mbuffer* b;
|
||||
int swap;
|
||||
const char* name;
|
||||
} LoadState;
|
||||
@@ -45,7 +48,7 @@ static void LoadBlock (LoadState* S, void* b, size_t size)
|
||||
{
|
||||
if (S->swap)
|
||||
{
|
||||
char *p=(char*) b+size-1;
|
||||
char* p=(char*) b+size-1;
|
||||
int n=size;
|
||||
while (n--) *p--=(char)ezgetc(S);
|
||||
}
|
||||
@@ -57,10 +60,10 @@ static void LoadVector (LoadState* S, void* b, int m, size_t size)
|
||||
{
|
||||
if (S->swap)
|
||||
{
|
||||
char *q=(char*) b;
|
||||
char* q=(char*) b;
|
||||
while (m--)
|
||||
{
|
||||
char *p=q+size-1;
|
||||
char* p=q+size-1;
|
||||
int n=size;
|
||||
while (n--) *p--=(char)ezgetc(S);
|
||||
q+=size;
|
||||
@@ -99,7 +102,7 @@ static TString* LoadString (LoadState* S)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
char* s=luaO_openspace(S->L,size,char);
|
||||
char* s=luaZ_openspace(S->L,S->b,size);
|
||||
ezread(S,s,size);
|
||||
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
|
||||
}
|
||||
@@ -129,10 +132,10 @@ static void LoadLocals (LoadState* S, Proto* f)
|
||||
|
||||
static void LoadLines (LoadState* S, Proto* f)
|
||||
{
|
||||
int n;
|
||||
n=LoadInt(S);
|
||||
f->lineinfo=luaM_newvector(S->L,n,int);
|
||||
LoadVector(S,f->lineinfo,n,sizeof(*f->lineinfo));
|
||||
int size=LoadInt(S);
|
||||
f->lineinfo=luaM_newvector(S->L,size,int);
|
||||
f->sizelineinfo=size;
|
||||
LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo));
|
||||
}
|
||||
|
||||
static Proto* LoadFunction (LoadState* S, TString* p);
|
||||
@@ -153,7 +156,7 @@ static void LoadConstants (LoadState* S, Proto* f)
|
||||
setnvalue(o,LoadNumber(S));
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
setsvalue(o,LoadString(S));
|
||||
setsvalue2n(o,LoadString(S));
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
setnilvalue(o);
|
||||
@@ -232,8 +235,7 @@ static void LoadHeader (LoadState* S)
|
||||
TESTSIZE(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: read %f; expected %f",
|
||||
S->name,x,tx);
|
||||
luaG_runerror(S->L,"unknown number format in %s",S->name);
|
||||
}
|
||||
|
||||
static Proto* LoadChunk (LoadState* S)
|
||||
@@ -243,12 +245,11 @@ static Proto* LoadChunk (LoadState* S)
|
||||
}
|
||||
|
||||
/*
|
||||
** load one chunk from a file or buffer
|
||||
** load precompiled chunk
|
||||
*/
|
||||
Proto* luaU_undump (lua_State* L, ZIO* Z)
|
||||
Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff)
|
||||
{
|
||||
LoadState S;
|
||||
Proto* f;
|
||||
const char* s=zname(Z);
|
||||
if (*s=='@' || *s=='=')
|
||||
S.name=s+1;
|
||||
@@ -258,10 +259,8 @@ Proto* luaU_undump (lua_State* L, ZIO* Z)
|
||||
S.name=s;
|
||||
S.L=L;
|
||||
S.Z=Z;
|
||||
f=LoadChunk(&S);
|
||||
if (zgetc(Z)!=EOZ)
|
||||
luaG_runerror(L,"%s apparently contains more than one chunk",S.name);
|
||||
return f;
|
||||
S.b=buff;
|
||||
return LoadChunk(&S);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lundump.h,v 1.26 2002/08/07 00:36:03 lhf Exp $
|
||||
** $Id: lundump.h,v 1.28 2002/10/09 13:42:01 roberto Exp roberto $
|
||||
** load pre-compiled Lua chunks
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -10,16 +10,14 @@
|
||||
#include "lobject.h"
|
||||
#include "lzio.h"
|
||||
|
||||
typedef int (*Writer)(const void* p, size_t size, void* u);
|
||||
|
||||
/* load one chunk; from lundump.c */
|
||||
Proto* luaU_undump (lua_State* L, ZIO* Z);
|
||||
Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer *buff);
|
||||
|
||||
/* find byte order; from lundump.c */
|
||||
int luaU_endianness (void);
|
||||
|
||||
/* dump one chunk; from dump.c */
|
||||
void luaU_dump (const Proto* Main, Writer w, void* data);
|
||||
void luaU_dump (lua_State *L, const Proto* Main, lua_Chunkwriter w, void* data);
|
||||
|
||||
/* print one chunk; from print.c */
|
||||
void luaU_print (const Proto* Main);
|
||||
|
||||
223
lvm.c
223
lvm.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.c,v 1.251 2002/08/07 19:22:39 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 1.272 2002/12/06 17:09:00 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define lvm_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
@@ -36,15 +38,6 @@
|
||||
#define MAXTAGLOOP 100
|
||||
|
||||
|
||||
static void luaV_checkGC (lua_State *L, StkId top) {
|
||||
if (G(L)->nblocks >= G(L)->GCthreshold) {
|
||||
L->top = top; /* limit for active registers */
|
||||
luaC_collectgarbage(L);
|
||||
L->top = L->ci->top; /* restore old top position */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
|
||||
lua_Number num;
|
||||
if (ttisnumber(obj)) return obj;
|
||||
@@ -57,24 +50,24 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
|
||||
}
|
||||
|
||||
|
||||
int luaV_tostring (lua_State *L, TObject *obj) {
|
||||
int luaV_tostring (lua_State *L, StkId obj) {
|
||||
if (!ttisnumber(obj))
|
||||
return 0;
|
||||
else {
|
||||
char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */
|
||||
lua_number2str(s, nvalue(obj));
|
||||
setsvalue(obj, luaS_new(L, s));
|
||||
setsvalue2s(obj, luaS_new(L, s));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void traceexec (lua_State *L) {
|
||||
unsigned long mask = L->hookmask;
|
||||
lu_byte mask = L->hookmask;
|
||||
if (mask > LUA_MASKLINE) { /* instruction-hook set? */
|
||||
if (L->hookcount == 0) {
|
||||
luaD_callhook(L, LUA_HOOKCOUNT, -1);
|
||||
resethookcount(L);
|
||||
luaD_callhook(L, LUA_HOOKCOUNT, -1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -82,6 +75,10 @@ static void traceexec (lua_State *L) {
|
||||
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' */
|
||||
@@ -98,9 +95,9 @@ static void traceexec (lua_State *L) {
|
||||
|
||||
static void callTMres (lua_State *L, const TObject *f,
|
||||
const TObject *p1, const TObject *p2) {
|
||||
setobj(L->top, f); /* push function */
|
||||
setobj(L->top+1, p1); /* 1st argument */
|
||||
setobj(L->top+2, p2); /* 2nd argument */
|
||||
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) */
|
||||
L->top += 3;
|
||||
luaD_call(L, L->top - 3, 1);
|
||||
@@ -111,10 +108,10 @@ static void callTMres (lua_State *L, const TObject *f,
|
||||
|
||||
static void callTM (lua_State *L, const TObject *f,
|
||||
const TObject *p1, const TObject *p2, const TObject *p3) {
|
||||
setobj(L->top, f); /* push function */
|
||||
setobj(L->top+1, p1); /* 1st argument */
|
||||
setobj(L->top+2, p2); /* 2nd argument */
|
||||
setobj(L->top+3, p3); /* 3th argument */
|
||||
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) */
|
||||
L->top += 4;
|
||||
luaD_call(L, L->top - 4, 0);
|
||||
@@ -134,7 +131,7 @@ static const TObject *luaV_index (lua_State *L, const TObject *t,
|
||||
|
||||
static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
|
||||
TObject *key, int loop) {
|
||||
const TObject *tm = luaT_gettmbyobj(L, t, TM_GETTABLE);
|
||||
const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX);
|
||||
if (ttisnil(tm))
|
||||
luaG_typeerror(L, t, "index");
|
||||
if (ttisfunction(tm)) {
|
||||
@@ -176,12 +173,12 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
|
||||
TObject *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? */
|
||||
setobj(oldval, val);
|
||||
setobj2t(oldval, val); /* write barrier */
|
||||
return;
|
||||
}
|
||||
/* else will try the tag method */
|
||||
}
|
||||
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_SETTABLE)))
|
||||
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
|
||||
luaG_typeerror(L, t, "index");
|
||||
if (ttisfunction(tm)) {
|
||||
callTM(L, tm, t, key, val);
|
||||
@@ -194,7 +191,7 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
|
||||
|
||||
|
||||
static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
|
||||
TObject *res, TMS event) {
|
||||
StkId res, TMS event) {
|
||||
ptrdiff_t result = savestack(L, res);
|
||||
const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
|
||||
if (ttisnil(tm))
|
||||
@@ -202,7 +199,7 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
|
||||
if (!ttisfunction(tm)) return 0;
|
||||
callTMres(L, tm, p1, p2);
|
||||
res = restorestack(L, result); /* previous call may change stack */
|
||||
setobj(res, L->top);
|
||||
setobjs2s(res, L->top);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -263,22 +260,23 @@ int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
|
||||
switch (ttype(t1)) {
|
||||
case LUA_TNIL: return 1;
|
||||
case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);
|
||||
case LUA_TSTRING: return tsvalue(t1) == tsvalue(t2);
|
||||
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
|
||||
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
|
||||
case LUA_TFUNCTION: return clvalue(t1) == clvalue(t2);
|
||||
case LUA_TUSERDATA:
|
||||
case LUA_TUSERDATA: {
|
||||
if (uvalue(t1) == uvalue(t2)) return 1;
|
||||
else if ((tm = fasttm(L, uvalue(t1)->uv.metatable, TM_EQ)) == NULL &&
|
||||
(tm = fasttm(L, uvalue(t2)->uv.metatable, TM_EQ)) == NULL)
|
||||
return 0; /* no TM */
|
||||
else break; /* will try TM */
|
||||
case LUA_TTABLE:
|
||||
}
|
||||
case LUA_TTABLE: {
|
||||
if (hvalue(t1) == hvalue(t2)) return 1;
|
||||
else if ((tm = fasttm(L, hvalue(t1)->metatable, TM_EQ)) == NULL &&
|
||||
(tm = fasttm(L, hvalue(t2)->metatable, TM_EQ)) == NULL)
|
||||
return 0; /* no TM */
|
||||
else break; /* will try TM */
|
||||
}
|
||||
default: return gcvalue(t1) == gcvalue(t2);
|
||||
}
|
||||
callTMres(L, tm, t1, t2); /* call TM */
|
||||
return !l_isfalse(L->top);
|
||||
@@ -287,7 +285,7 @@ int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
|
||||
|
||||
void luaV_concat (lua_State *L, int total, int last) {
|
||||
do {
|
||||
StkId top = L->ci->base + last + 1;
|
||||
StkId top = L->base + last + 1;
|
||||
int n = 2; /* number of elements handled in this pass (at least 2) */
|
||||
if (!tostring(L, top-2) || !tostring(L, top-1)) {
|
||||
if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
|
||||
@@ -303,14 +301,14 @@ void luaV_concat (lua_State *L, int total, int last) {
|
||||
n++;
|
||||
}
|
||||
if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
|
||||
buffer = luaO_openspace(L, tl, char);
|
||||
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;
|
||||
memcpy(buffer+tl, svalue(top-i), l);
|
||||
tl += l;
|
||||
}
|
||||
setsvalue(top-n, luaS_newlstr(L, buffer, tl));
|
||||
setsvalue2s(top-n, luaS_newlstr(L, buffer, tl));
|
||||
}
|
||||
total -= n-1; /* got `n' strings to create 1 new */
|
||||
last -= n-1;
|
||||
@@ -318,7 +316,8 @@ void luaV_concat (lua_State *L, int total, int last) {
|
||||
}
|
||||
|
||||
|
||||
static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
|
||||
static void Arith (lua_State *L, StkId ra,
|
||||
const TObject *rb, const TObject *rc, TMS op) {
|
||||
TObject tempb, tempc;
|
||||
const TObject *b, *c;
|
||||
if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
|
||||
@@ -336,7 +335,7 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
|
||||
luaG_runerror(L, "`pow' (for `^' operator) is not a function");
|
||||
callTMres(L, f, b, c);
|
||||
ra = restorestack(L, res); /* previous call may change stack */
|
||||
setobj(ra, L->top);
|
||||
setobjs2s(ra, L->top);
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0); break;
|
||||
@@ -355,11 +354,12 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
|
||||
#define runtime_check(L, c) { if (!(c)) return 0; }
|
||||
|
||||
#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) ? \
|
||||
base+GETARG_C(i) : \
|
||||
k+GETARG_C(i)-MAXSTACK)
|
||||
#define RKC(i) ((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)
|
||||
#define KBx(i) (k+GETARG_Bx(i))
|
||||
|
||||
|
||||
@@ -367,42 +367,49 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
|
||||
|
||||
|
||||
StkId luaV_execute (lua_State *L) {
|
||||
StkId base;
|
||||
LClosure *cl;
|
||||
TObject *k;
|
||||
const Instruction *pc;
|
||||
callentry: /* entry point when calling new functions */
|
||||
L->ci->u.l.pb = &base;
|
||||
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 */
|
||||
lua_assert(L->ci->state & CI_SAVEDPC);
|
||||
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;
|
||||
base = L->ci->base;
|
||||
cl = &clvalue(base - 1)->l;
|
||||
cl = &clvalue(L->base - 1)->l;
|
||||
k = cl->p->k;
|
||||
/* main loop of interpreter */
|
||||
for (;;) {
|
||||
const Instruction i = *pc++;
|
||||
StkId ra;
|
||||
if (L->hookmask >= LUA_MASKLINE &&
|
||||
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
|
||||
StkId base, 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? */
|
||||
L->ci->u.l.savedpc = pc - 1;
|
||||
L->ci->state = CI_YIELD | CI_SAVEDPC;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* warning!! several calls may realloc the stack and invalidate `ra' */
|
||||
base = L->base;
|
||||
ra = RA(i);
|
||||
lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
|
||||
lua_assert(L->ci->state & CI_HASFRAME);
|
||||
lua_assert(base == L->ci->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: {
|
||||
setobj(ra, RB(i));
|
||||
setobjs2s(ra, RB(i));
|
||||
break;
|
||||
}
|
||||
case OP_LOADK: {
|
||||
setobj(ra, KBx(i));
|
||||
setobj2s(ra, KBx(i));
|
||||
break;
|
||||
}
|
||||
case OP_LOADBOOL: {
|
||||
@@ -419,17 +426,17 @@ StkId luaV_execute (lua_State *L) {
|
||||
}
|
||||
case OP_GETUPVAL: {
|
||||
int b = GETARG_B(i);
|
||||
setobj(ra, cl->upvals[b]->v);
|
||||
setobj2s(ra, cl->upvals[b]->v);
|
||||
break;
|
||||
}
|
||||
case OP_GETGLOBAL: {
|
||||
StkId rb = KBx(i);
|
||||
TObject *rb = KBx(i);
|
||||
const TObject *v;
|
||||
lua_assert(ttisstring(rb) && ttistable(&cl->g));
|
||||
v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
|
||||
if (!ttisnil(v)) { setobj(ra, v); }
|
||||
if (!ttisnil(v)) { setobj2s(ra, v); }
|
||||
else
|
||||
setobj(RA(i), luaV_index(L, &cl->g, rb, 0));
|
||||
setobj2s(XRA(i), luaV_index(L, &cl->g, rb, 0));
|
||||
break;
|
||||
}
|
||||
case OP_GETTABLE: {
|
||||
@@ -437,12 +444,12 @@ StkId luaV_execute (lua_State *L) {
|
||||
TObject *rc = RKC(i);
|
||||
if (ttistable(rb)) {
|
||||
const TObject *v = luaH_get(hvalue(rb), rc);
|
||||
if (!ttisnil(v)) { setobj(ra, v); }
|
||||
if (!ttisnil(v)) { setobj2s(ra, v); }
|
||||
else
|
||||
setobj(RA(i), luaV_index(L, rb, rc, 0));
|
||||
setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
|
||||
}
|
||||
else
|
||||
setobj(RA(i), luaV_getnotable(L, rb, rc, 0));
|
||||
setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
|
||||
break;
|
||||
}
|
||||
case OP_SETGLOBAL: {
|
||||
@@ -452,38 +459,38 @@ StkId luaV_execute (lua_State *L) {
|
||||
}
|
||||
case OP_SETUPVAL: {
|
||||
int b = GETARG_B(i);
|
||||
setobj(cl->upvals[b]->v, ra);
|
||||
setobj(cl->upvals[b]->v, ra); /* write barrier */
|
||||
break;
|
||||
}
|
||||
case OP_SETTABLE: {
|
||||
luaV_settable(L, RB(i), RKC(i), ra);
|
||||
luaV_settable(L, ra, RKB(i), RKC(i));
|
||||
break;
|
||||
}
|
||||
case OP_NEWTABLE: {
|
||||
int b = GETARG_B(i);
|
||||
if (b > 0) b = twoto(b-1);
|
||||
sethvalue(ra, luaH_new(L, b, GETARG_C(i)));
|
||||
luaV_checkGC(L, ra+1);
|
||||
luaC_checkGC(L);
|
||||
break;
|
||||
}
|
||||
case OP_SELF: {
|
||||
StkId rb = RB(i);
|
||||
TObject *rc = RKC(i);
|
||||
runtime_check(L, ttisstring(rc));
|
||||
setobj(ra+1, rb);
|
||||
setobjs2s(ra+1, rb);
|
||||
if (ttistable(rb)) {
|
||||
const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
|
||||
if (!ttisnil(v)) { setobj(ra, v); }
|
||||
if (!ttisnil(v)) { setobj2s(ra, v); }
|
||||
else
|
||||
setobj(RA(i), luaV_index(L, rb, rc, 0));
|
||||
setobj2s(XRA(i), luaV_index(L, rb, rc, 0));
|
||||
}
|
||||
else
|
||||
setobj(RA(i), luaV_getnotable(L, rb, rc, 0));
|
||||
setobj2s(XRA(i), luaV_getnotable(L, rb, rc, 0));
|
||||
break;
|
||||
}
|
||||
case OP_ADD: {
|
||||
StkId rb = RB(i);
|
||||
StkId rc = RKC(i);
|
||||
TObject *rb = RKB(i);
|
||||
TObject *rc = RKC(i);
|
||||
if (ttisnumber(rb) && ttisnumber(rc)) {
|
||||
setnvalue(ra, nvalue(rb) + nvalue(rc));
|
||||
}
|
||||
@@ -492,8 +499,8 @@ StkId luaV_execute (lua_State *L) {
|
||||
break;
|
||||
}
|
||||
case OP_SUB: {
|
||||
StkId rb = RB(i);
|
||||
StkId rc = RKC(i);
|
||||
TObject *rb = RKB(i);
|
||||
TObject *rc = RKC(i);
|
||||
if (ttisnumber(rb) && ttisnumber(rc)) {
|
||||
setnvalue(ra, nvalue(rb) - nvalue(rc));
|
||||
}
|
||||
@@ -502,8 +509,8 @@ StkId luaV_execute (lua_State *L) {
|
||||
break;
|
||||
}
|
||||
case OP_MUL: {
|
||||
StkId rb = RB(i);
|
||||
StkId rc = RKC(i);
|
||||
TObject *rb = RKB(i);
|
||||
TObject *rc = RKC(i);
|
||||
if (ttisnumber(rb) && ttisnumber(rc)) {
|
||||
setnvalue(ra, nvalue(rb) * nvalue(rc));
|
||||
}
|
||||
@@ -512,8 +519,8 @@ StkId luaV_execute (lua_State *L) {
|
||||
break;
|
||||
}
|
||||
case OP_DIV: {
|
||||
StkId rb = RB(i);
|
||||
StkId rc = RKC(i);
|
||||
TObject *rb = RKB(i);
|
||||
TObject *rc = RKC(i);
|
||||
if (ttisnumber(rb) && ttisnumber(rc)) {
|
||||
setnvalue(ra, nvalue(rb) / nvalue(rc));
|
||||
}
|
||||
@@ -522,7 +529,7 @@ StkId luaV_execute (lua_State *L) {
|
||||
break;
|
||||
}
|
||||
case OP_POW: {
|
||||
Arith(L, ra, RB(i), RKC(i), TM_POW);
|
||||
Arith(L, ra, RKB(i), RKC(i), TM_POW);
|
||||
break;
|
||||
}
|
||||
case OP_UNM: {
|
||||
@@ -547,44 +554,35 @@ StkId luaV_execute (lua_State *L) {
|
||||
int b = GETARG_B(i);
|
||||
int c = GETARG_C(i);
|
||||
luaV_concat(L, c-b+1, c); /* may change `base' (and `ra') */
|
||||
setobj(RA(i), base+b);
|
||||
luaV_checkGC(L, base+c+1);
|
||||
base = L->base;
|
||||
setobjs2s(RA(i), base+b);
|
||||
luaC_checkGC(L);
|
||||
break;
|
||||
}
|
||||
case OP_JMP: {
|
||||
dojump(pc, GETARG_sBx(i));
|
||||
break;
|
||||
}
|
||||
case OP_EQ: { /* skip next instruction if test fails */
|
||||
if (equalobj(L, ra, RKC(i)) != GETARG_B(i)) pc++;
|
||||
case OP_EQ: {
|
||||
if (equalobj(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
|
||||
else dojump(pc, GETARG_sBx(*pc) + 1);
|
||||
break;
|
||||
}
|
||||
case OP_LT: {
|
||||
if (luaV_lessthan(L, ra, RKC(i)) != GETARG_B(i)) pc++;
|
||||
if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
|
||||
else dojump(pc, GETARG_sBx(*pc) + 1);
|
||||
break;
|
||||
}
|
||||
case OP_LE: {
|
||||
if (luaV_lessequal(L, ra, RKC(i)) != GETARG_B(i)) pc++;
|
||||
else dojump(pc, GETARG_sBx(*pc) + 1);
|
||||
break;
|
||||
}
|
||||
case OP_GT: {
|
||||
if (luaV_lessthan(L, RKC(i), ra) != GETARG_B(i)) pc++;
|
||||
else dojump(pc, GETARG_sBx(*pc) + 1);
|
||||
break;
|
||||
}
|
||||
case OP_GE: {
|
||||
if (luaV_lessequal(L, RKC(i), ra) != GETARG_B(i)) pc++;
|
||||
if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) pc++;
|
||||
else dojump(pc, GETARG_sBx(*pc) + 1);
|
||||
break;
|
||||
}
|
||||
case OP_TEST: {
|
||||
StkId rc = RKC(i);
|
||||
if (l_isfalse(rc) == GETARG_B(i)) pc++;
|
||||
TObject *rb = RB(i);
|
||||
if (l_isfalse(rb) == GETARG_C(i)) pc++;
|
||||
else {
|
||||
setobj(ra, rc);
|
||||
setobjs2s(ra, rb);
|
||||
dojump(pc, GETARG_sBx(*pc) + 1);
|
||||
}
|
||||
break;
|
||||
@@ -599,6 +597,7 @@ StkId luaV_execute (lua_State *L) {
|
||||
firstResult = luaD_precall(L, ra);
|
||||
if (firstResult) {
|
||||
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;
|
||||
@@ -614,15 +613,17 @@ StkId luaV_execute (lua_State *L) {
|
||||
}
|
||||
else { /* tail call: put new frame in place of previous one */
|
||||
int aux;
|
||||
StkId ra1 = RA(i); /* `luaD_precall' may change the stack */
|
||||
base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */
|
||||
ra = RA(i);
|
||||
if (L->openupval) luaF_close(L, base);
|
||||
for (aux = 0; ra1+aux < L->top; aux++) /* move frame down */
|
||||
setobj(base+aux-1, ra1+aux);
|
||||
for (aux = 0; ra+aux < L->top; aux++) /* move frame down */
|
||||
setobjs2s(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)->state = CI_SAVEDPC;
|
||||
L->ci--; /* remove previous frame */
|
||||
L->ci--; /* remove new frame */
|
||||
L->base = L->ci->base;
|
||||
}
|
||||
goto callentry;
|
||||
}
|
||||
@@ -670,20 +671,30 @@ StkId luaV_execute (lua_State *L) {
|
||||
break;
|
||||
}
|
||||
case OP_TFORLOOP: {
|
||||
setobj(ra+4, ra+2);
|
||||
setobj(ra+3, ra+1);
|
||||
setobj(ra+2, ra);
|
||||
L->top = ra+5;
|
||||
luaD_call(L, ra+2, GETARG_C(i) + 1);
|
||||
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);
|
||||
L->top = cb+3; /* func. + 2 args (state and index) */
|
||||
luaD_call(L, cb, nvar);
|
||||
L->top = L->ci->top;
|
||||
if (ttisnil(RA(i)+2)) pc++; /* skip jump (break loop) */
|
||||
else dojump(pc, GETARG_sBx(*pc) + 1); /* else jump back */
|
||||
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? */
|
||||
pc++; /* skip jump (break loop) */
|
||||
else
|
||||
dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */
|
||||
break;
|
||||
}
|
||||
case OP_TFORPREP: { /* for compatibility only */
|
||||
if (ttistable(ra)) {
|
||||
setobj(ra+1, ra);
|
||||
setobj(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
|
||||
setobjs2s(ra+1, ra);
|
||||
setobj2s(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
|
||||
}
|
||||
dojump(pc, GETARG_sBx(i));
|
||||
break;
|
||||
@@ -704,7 +715,7 @@ StkId luaV_execute (lua_State *L) {
|
||||
}
|
||||
bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */
|
||||
for (; n > 0; n--)
|
||||
setobj(luaH_setnum(L, h, bc+n), ra+n);
|
||||
setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */
|
||||
break;
|
||||
}
|
||||
case OP_CLOSE: {
|
||||
@@ -728,7 +739,7 @@ StkId luaV_execute (lua_State *L) {
|
||||
}
|
||||
}
|
||||
setclvalue(ra, ncl);
|
||||
luaV_checkGC(L, L->top);
|
||||
luaC_checkGC(L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
4
lvm.h
4
lvm.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.h,v 1.45 2002/08/05 17:36:24 roberto Exp roberto $
|
||||
** $Id: lvm.h,v 1.46 2002/08/07 19:22:39 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
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_tostring (lua_State *L, TObject *obj);
|
||||
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);
|
||||
|
||||
17
lzio.c
17
lzio.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lzio.c,v 1.20 2002/08/05 18:45:02 roberto Exp roberto $
|
||||
** $Id: lzio.c,v 1.22 2002/10/08 18:46:08 roberto Exp roberto $
|
||||
** a generic input stream interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,13 +7,15 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define lzio_c
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "llimits.h"
|
||||
#include "lmem.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
|
||||
int luaZ_fill (ZIO *z) {
|
||||
size_t size;
|
||||
const char *buff = z->reader(NULL, z->data, &size);
|
||||
@@ -66,3 +68,14 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
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;
|
||||
}
|
||||
return buff->buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
lzio.h
27
lzio.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lzio.h,v 1.12 2002/06/06 12:40:22 roberto Exp roberto $
|
||||
** $Id: lzio.h,v 1.13 2002/08/05 18:45:02 roberto Exp roberto $
|
||||
** Buffered streams
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#define EOZ (-1) /* end of stream */
|
||||
|
||||
typedef struct zio ZIO;
|
||||
typedef struct Zio ZIO;
|
||||
|
||||
#define zgetc(z) (((z)->n--)>0 ? \
|
||||
cast(int, cast(unsigned char, *(z)->p++)) : \
|
||||
@@ -26,9 +26,30 @@ size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
|
||||
int luaZ_lookahead (ZIO *z);
|
||||
|
||||
|
||||
|
||||
typedef struct Mbuffer {
|
||||
char *buffer;
|
||||
size_t buffsize;
|
||||
} Mbuffer;
|
||||
|
||||
|
||||
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_resizebuffer(L, buff, size) \
|
||||
(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
|
||||
(buff)->buffsize = size)
|
||||
|
||||
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
|
||||
|
||||
|
||||
/* --------- Private Part ------------------ */
|
||||
|
||||
struct zio {
|
||||
struct Zio {
|
||||
size_t n; /* bytes still unread */
|
||||
const char *p; /* current position in buffer */
|
||||
lua_Chunkreader reader;
|
||||
|
||||
76
makefile
76
makefile
@@ -1,5 +1,5 @@
|
||||
#
|
||||
## $Id: makefile,v 1.35 2002/03/18 18:18:35 roberto Exp roberto $
|
||||
## $Id: makefile,v 1.38 2002/10/25 21:38:17 roberto Exp $
|
||||
## Makefile
|
||||
## See Copyright Notice in lua.h
|
||||
#
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#CONFIGURATION
|
||||
|
||||
# define (undefine) POPEN if your system (does not) support piped I/O
|
||||
# define (undefine) USE_POPEN if your system (does not) support piped I/O
|
||||
#
|
||||
# define (undefine) _POSIX_SOURCE if your system is (not) POSIX compliant
|
||||
#
|
||||
@@ -16,13 +16,13 @@
|
||||
# you may need to adapat the code, too.
|
||||
|
||||
|
||||
# DEBUG = -g -DLUA_USER_H='"ltests.h"'
|
||||
# DEBUG = -g -DLUA_USER_H='"ltests.h"' # -DHARDSTACKTESTS -DEXTERNMEMCHECK
|
||||
OPTIMIZE = -O2 \
|
||||
-D'lua_number2int(i,d)=__asm__("fldl %1\nfistpl %0":"=m"(i):"m"(d))' \
|
||||
-fomit-frame-pointer
|
||||
# -D'lua_number2int(i,d)=__asm__("fldl %1\nfistpl %0":"=m"(i):"m"(d))' \
|
||||
# -fomit-frame-pointer
|
||||
|
||||
CONFIG = -D_POSIX_SOURCE -DPOPEN $(DEBUG) $(OPTIMIZE)
|
||||
|
||||
CONFIG = -D_POSIX_SOURCE $(DEBUG) $(OPTIMIZE) # -DUSE_POPEN
|
||||
|
||||
|
||||
# Compilation parameters
|
||||
@@ -68,6 +68,7 @@ LUAOBJS = \
|
||||
llex.o \
|
||||
lopcodes.o \
|
||||
lundump.o \
|
||||
ldump.o \
|
||||
lzio.o \
|
||||
ldebug.o \
|
||||
ltests.o
|
||||
@@ -109,52 +110,53 @@ clear :
|
||||
co $(CO_OPTIONS) $@
|
||||
|
||||
|
||||
lapi.o: lapi.c lua.h lapi.h lobject.h llimits.h ldebug.h lstate.h \
|
||||
ltm.h ldo.h lzio.h lfunc.h lgc.h lmem.h lstring.h ltable.h lundump.h \
|
||||
lvm.h
|
||||
lapi.o: lapi.c lua.h lapi.h lobject.h llimits.h ldebug.h lstate.h ltm.h \
|
||||
lzio.h ldo.h lfunc.h lgc.h lmem.h lstring.h ltable.h lundump.h lvm.h
|
||||
lauxlib.o: lauxlib.c lua.h lauxlib.h
|
||||
lbaselib.o: lbaselib.c lua.h lauxlib.h lualib.h
|
||||
lcode.o: lcode.c lua.h lcode.h llex.h lobject.h llimits.h lzio.h \
|
||||
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h lmem.h
|
||||
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h lmem.h
|
||||
ldblib.o: ldblib.c lua.h lauxlib.h lualib.h
|
||||
ldebug.o: ldebug.c lua.h lapi.h lobject.h llimits.h lcode.h llex.h \
|
||||
lzio.h lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h \
|
||||
lfunc.h lstring.h lvm.h
|
||||
ldo.o: ldo.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
|
||||
lzio.h lfunc.h lgc.h lmem.h lopcodes.h lparser.h ltable.h lstring.h \
|
||||
lundump.h lvm.h
|
||||
lfunc.o: lfunc.c lua.h lfunc.h lobject.h llimits.h lmem.h lstate.h \
|
||||
ltm.h
|
||||
lgc.o: lgc.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
|
||||
lzio.h lfunc.h lgc.h lmem.h lstring.h ltable.h
|
||||
ldebug.o: ldebug.c lua.h lapi.h lobject.h llimits.h lcode.h llex.h lzio.h \
|
||||
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h lfunc.h \
|
||||
lstring.h lvm.h
|
||||
ldo.o: ldo.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h lzio.h \
|
||||
ldo.h lfunc.h lgc.h lmem.h lopcodes.h lparser.h ltable.h lstring.h \
|
||||
lundump.h lvm.h
|
||||
ldump.o: ldump.c lua.h lobject.h llimits.h lopcodes.h lstate.h ltm.h \
|
||||
lzio.h lundump.h
|
||||
lfunc.o: lfunc.c lua.h lfunc.h lobject.h llimits.h lgc.h lmem.h lstate.h \
|
||||
ltm.h lzio.h
|
||||
lgc.o: lgc.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h lzio.h \
|
||||
ldo.h lfunc.h lgc.h lmem.h lstring.h ltable.h
|
||||
liolib.o: liolib.c lua.h lauxlib.h lualib.h
|
||||
llex.o: llex.c lua.h ldo.h lobject.h llimits.h lstate.h ltm.h lzio.h \
|
||||
llex.h lparser.h ltable.h lstring.h
|
||||
llex.h lparser.h ltable.h lstring.h
|
||||
lmathlib.o: lmathlib.c lua.h lauxlib.h lualib.h
|
||||
lmem.o: lmem.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
|
||||
lzio.h lmem.h
|
||||
lmem.o: lmem.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h lzio.h \
|
||||
ldo.h lmem.h
|
||||
lobject.o: lobject.c lua.h ldo.h lobject.h llimits.h lstate.h ltm.h \
|
||||
lzio.h lmem.h lstring.h lvm.h
|
||||
lzio.h lmem.h lstring.h lvm.h
|
||||
lopcodes.o: lopcodes.c lua.h lobject.h llimits.h lopcodes.h
|
||||
lparser.o: lparser.c lua.h lcode.h llex.h lobject.h llimits.h lzio.h \
|
||||
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h lfunc.h lmem.h \
|
||||
lstring.h
|
||||
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h lfunc.h lmem.h \
|
||||
lstring.h
|
||||
lstate.o: lstate.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
|
||||
ldo.h lzio.h lfunc.h lgc.h llex.h lmem.h lstring.h ltable.h
|
||||
lzio.h ldo.h lfunc.h lgc.h llex.h lmem.h lstring.h ltable.h
|
||||
lstring.o: lstring.c lua.h lmem.h llimits.h lobject.h lstate.h ltm.h \
|
||||
lstring.h
|
||||
lzio.h lstring.h
|
||||
lstrlib.o: lstrlib.c lua.h lauxlib.h lualib.h
|
||||
ltable.o: ltable.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
|
||||
ldo.h lzio.h lmem.h ltable.h
|
||||
lzio.h ldo.h lgc.h lmem.h ltable.h
|
||||
ltablib.o: ltablib.c lua.h lauxlib.h lualib.h
|
||||
ltests.o: ltests.c lua.h lapi.h lobject.h llimits.h lauxlib.h lcode.h \
|
||||
llex.h lzio.h lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h \
|
||||
ldo.h lfunc.h lmem.h lstring.h lualib.h
|
||||
ltm.o: ltm.c lua.h lobject.h llimits.h lstate.h ltm.h lstring.h \
|
||||
ltable.h
|
||||
llex.h lzio.h lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h \
|
||||
ldo.h lfunc.h lmem.h lstring.h lualib.h
|
||||
ltm.o: ltm.c lua.h lobject.h llimits.h lstate.h ltm.h lzio.h lstring.h \
|
||||
ltable.h
|
||||
lua.o: lua.c lua.h lauxlib.h lualib.h
|
||||
lundump.o: lundump.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
|
||||
lfunc.h lmem.h lopcodes.h lstring.h lundump.h lzio.h
|
||||
lvm.o: lvm.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
|
||||
lzio.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h
|
||||
lzio.o: lzio.c lua.h llimits.h lzio.h
|
||||
lzio.h lfunc.h lmem.h lopcodes.h lstring.h lundump.h
|
||||
lvm.o: lvm.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h lzio.h \
|
||||
ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h
|
||||
lzio.o: lzio.c lua.h llimits.h lmem.h lzio.h
|
||||
|
||||
531
manual.tex
531
manual.tex
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user