Compare commits

...

92 Commits

Author SHA1 Message Date
Roberto Ierusalimschy
69ea087dff small change to strip file names when stripping debug information 2006-02-17 13:51:03 -02:00
Roberto Ierusalimschy
c05aaf3bf0 avoid warning in OS X - ansi 2006-02-10 15:44:06 -02:00
Roberto Ierusalimschy
298ae7e230 complete support for hexadecimal constants 2006-02-10 15:43:52 -02:00
Roberto Ierusalimschy
6316a866a3 compiler warning 2006-02-06 16:28:16 -02:00
Roberto Ierusalimschy
ea2cc2bc47 small improvements for allignments 2006-02-06 16:27:59 -02:00
Roberto Ierusalimschy
64205e91a3 empty string may cause out-of-bound access 2006-01-28 10:59:13 -02:00
Roberto Ierusalimschy
8173688542 detail 2006-01-27 11:54:39 -02:00
Roberto Ierusalimschy
3ef5a6797f detail 2006-01-23 18:06:19 -02:00
Roberto Ierusalimschy
9e6e43984d details 2006-01-23 17:51:43 -02:00
Roberto Ierusalimschy
baffc37f5c detail 2006-01-18 09:49:12 -02:00
Roberto Ierusalimschy
440113bbe8 unused macro removed 2006-01-18 09:37:34 -02:00
Roberto Ierusalimschy
73ebc5d8f6 compat code should keep compatibility 2006-01-16 10:42:21 -02:00
Roberto Ierusalimschy
a666752b1d detail 2006-01-13 17:36:28 -02:00
Roberto Ierusalimschy
f8b7a5581e avoid unnecessary exports 2006-01-10 11:13:06 -02:00
Roberto Ierusalimschy
ffb798e1e2 avoids type punning for table keys 2006-01-10 10:51:53 -02:00
Roberto Ierusalimschy
fa936f8fa9 detail 2006-01-10 10:50:13 -02:00
Roberto Ierusalimschy
dd1221582b details 2006-01-10 10:50:00 -02:00
Roberto Ierusalimschy
bfdcbbcd76 small optimizations (lua_newtable -> lua_createtable) 2005-12-29 14:23:32 -02:00
Roberto Ierusalimschy
30eebb2d1c detail (stop collector while openning libraries) 2005-12-29 10:30:16 -02:00
Roberto Ierusalimschy
0fd6466957 lua_assert is an internal matter, not to be configured 2005-12-27 15:12:00 -02:00
Roberto Ierusalimschy
6a516878e9 collectgarbage"count" returns kilobytes (where K = 1024) 2005-12-27 15:10:11 -02:00
Roberto Ierusalimschy
a486090a5c copyright will be 2006 2005-12-27 15:09:50 -02:00
Roberto Ierusalimschy
0160591998 removal of dead code 2005-12-26 11:35:47 -02:00
Roberto Ierusalimschy
c505f341d6 small changes in casts 2005-12-22 14:19:56 -02:00
Roberto Ierusalimschy
428325baec detail 2005-12-21 10:59:43 -02:00
Roberto Ierusalimschy
0561f71f0f (much) better error messages for 'require' 2005-12-19 18:56:39 -02:00
Roberto Ierusalimschy
9fbefdf69c integer formats in 'string.format' may need to operate with larger-than-int
types
2005-12-15 16:53:34 -02:00
Roberto Ierusalimschy
43c61fc113 details 2005-12-15 16:17:49 -02:00
Roberto Ierusalimschy
ea6b1b42c7 more robust way to test for decimal point separator 2005-12-08 13:50:54 -02:00
Roberto Ierusalimschy
87024e257d details 2005-12-07 13:43:05 -02:00
Roberto Ierusalimschy
6cd461633d clearer error message for uninstalled loadlib 2005-12-07 13:42:32 -02:00
Roberto Ierusalimschy
16fd4abaf6 corrects decimal point to follow current locale 2005-12-07 13:33:27 -02:00
Roberto Ierusalimschy
f26b85c5b7 small detail 2005-12-02 16:42:08 -02:00
Roberto Ierusalimschy
3592c08a2c avoid printing two copyright messages with '-v -i' options 2005-11-28 12:44:48 -02:00
Roberto Ierusalimschy
db724e14e0 new macro luai_numisnan 2005-11-25 11:29:32 -02:00
Roberto Ierusalimschy
1702953293 new macro LUA_WIN + new macro luai_numisnan 2005-11-25 11:29:11 -02:00
Roberto Ierusalimschy
33b4dec1cb no more "auto-detection" 2005-11-16 14:25:08 -02:00
Roberto Ierusalimschy
7dd10a1d7e new macro LUA_USE_POSIX to control POSIX-related macros 2005-11-16 09:56:28 -02:00
Roberto Ierusalimschy
521a452f28 'mod' may also raise an error when applied to zero 2005-11-16 09:55:27 -02:00
Roberto Ierusalimschy
2753134a38 new versions by lhf 2005-11-16 09:55:07 -02:00
Roberto Ierusalimschy
cbbde11a8a better position for lua_number2int (it is related to lua_Number) 2005-11-08 17:45:58 -02:00
Roberto Ierusalimschy
7b89cf3aeb unused include's 2005-11-08 17:45:36 -02:00
Roberto Ierusalimschy
d2811e8097 simpler checking for numbers (strtod does the rest) 2005-11-08 17:45:14 -02:00
Roberto Ierusalimschy
e43e95553f more privacy 2005-11-08 17:44:31 -02:00
Roberto Ierusalimschy
930018e273 lua_getlocal/setlocal work also for C locals and temporaries 2005-11-01 14:08:52 -02:00
Roberto Ierusalimschy
a160266c3d details 2005-11-01 14:08:45 -02:00
Roberto Ierusalimschy
d4c99b2673 new function 'getregistry' 2005-11-01 14:08:32 -02:00
Roberto Ierusalimschy
88f9843eee better error message 2005-10-26 11:28:19 -02:00
Roberto Ierusalimschy
9b5ae6faf9 better control of which values macros use 2005-10-25 11:36:28 -02:00
Roberto Ierusalimschy
caf3cfc6ac try to ensure that macros actually use their arguments 2005-10-24 15:39:21 -02:00
Roberto Ierusalimschy
ff7638b0ed VC warnings 2005-10-24 15:38:47 -02:00
Roberto Ierusalimschy
8e48ebb638 no more L in numer-operator macros (some functions that use those macros
have no access to L)
2005-10-24 15:37:52 -02:00
Roberto Ierusalimschy
c2bd68d2c3 detail 2005-10-24 15:37:33 -02:00
Roberto Ierusalimschy
201288b4df small bug 2005-10-23 15:52:42 -02:00
Roberto Ierusalimschy
62367dda44 string.gsub accepts a table as the replacement value 2005-10-23 15:46:30 -02:00
Roberto Ierusalimschy
056b6a8ef4 more robust implementation for table.insert 2005-10-23 15:38:15 -02:00
Roberto Ierusalimschy
502d8f9a06 comments 2005-10-23 15:37:55 -02:00
Roberto Ierusalimschy
7f376e6ea8 do a complete garbage collection in case of errors 2005-10-21 11:48:31 -02:00
Roberto Ierusalimschy
053e873145 new macro luaL_opt to avoid evaluating defaults when no needed 2005-10-21 11:47:42 -02:00
Roberto Ierusalimschy
9f4211310f more precision for gc count 2005-10-20 09:35:50 -02:00
Roberto Ierusalimschy
515d556832 access to metamethods and metafields should be raw 2005-10-20 09:35:25 -02:00
Roberto Ierusalimschy
ed7039024d avoid some warnings 2005-10-19 11:05:11 -02:00
Roberto Ierusalimschy
5511bf6b9d avoid comparisons between (void *) and (int *) 2005-10-17 16:01:51 -02:00
Roberto Ierusalimschy
86704cffe9 detail in usage message 2005-10-14 15:34:23 -03:00
Roberto Ierusalimschy
fa41fafa6e reorganization of argument handling 2005-10-14 15:15:46 -03:00
Roberto Ierusalimschy
ebf646efb5 detail 2005-10-14 13:24:11 -03:00
Roberto Ierusalimschy
b3f81f1d1d small bug when debugging dead threads 2005-10-14 13:23:33 -03:00
Roberto Ierusalimschy
a24eb3ef17 different organization for platform dependencies 2005-10-13 09:22:53 -03:00
Roberto Ierusalimschy
4385e2ada4 "conceptually", OP_TEST may change reg. A 2005-10-13 09:22:05 -03:00
Roberto Ierusalimschy
e9b06c506f small optimization 2005-10-13 09:21:51 -03:00
Roberto Ierusalimschy
cd12ab2597 details (more uniform coding) 2005-10-13 09:21:26 -03:00
Roberto Ierusalimschy
e251e84e0f constant folding optimizations 2005-10-09 17:05:48 -03:00
Roberto Ierusalimschy
e6bfbc38b5 'luaopen_package' was missing in new states 2005-10-06 17:47:32 -03:00
Roberto Ierusalimschy
d31c04c049 missing macros 'luai_userstate*' 2005-10-06 17:46:25 -03:00
Roberto Ierusalimschy
522481a788 avoid some warnings 2005-10-06 17:46:10 -03:00
Roberto Ierusalimschy
37b49aa451 detail 2005-10-06 17:44:22 -03:00
Roberto Ierusalimschy
0fa9b16148 details 2005-10-06 17:43:44 -03:00
Roberto Ierusalimschy
e41fb9a604 registry._LOADED created "on demand" 2005-10-03 11:36:45 -03:00
Roberto Ierusalimschy
5fc92cce12 registry._LOADED created "on demand" and baselib created as module _G 2005-10-03 11:36:45 -03:00
Roberto Ierusalimschy
6dd0c6ccbc numeral expressions keep their values in struct 'expdesc' 2005-10-03 11:02:40 -03:00
Roberto Ierusalimschy
a77413acd0 include of math.h depends on luaconf 2005-10-03 11:01:26 -03:00
Roberto Ierusalimschy
5dbb870815 small optimization for local declarations without initializations 2005-09-30 11:23:33 -03:00
Roberto Ierusalimschy
ede19c9138 2005-09-30 11:21:56 -03:00
Roberto Ierusalimschy
9e88b336b4 unused assignment 2005-09-30 10:50:05 -03:00
Roberto Ierusalimschy
0fae476ed4 new function 'table.maxn' 2005-09-20 14:56:47 -03:00
Roberto Ierusalimschy
361a9adba7 smaller initial tables (for programs that create many states) 2005-09-20 14:55:53 -03:00
Roberto Ierusalimschy
d8f1cca16e new function 'lua_setallocf' 2005-09-20 14:55:10 -03:00
Roberto Ierusalimschy
bf96d3fdd9 'string.find' as it was in 5.0 2005-09-19 10:49:12 -03:00
Roberto Ierusalimschy
c8c2e06899 'select' accepts negative indices 2005-09-16 15:22:48 -03:00
Roberto Ierusalimschy
8dcc6bc532 avoid the use of global lock 2005-09-14 14:48:57 -03:00
Roberto Ierusalimschy
38f585d271 separated macros for thread creation and state creation 2005-09-14 14:44:48 -03:00
Roberto Ierusalimschy
6887f91799 ":" is not a good mark as it is not valid in Windows file names 2005-09-14 14:23:03 -03:00
44 changed files with 1349 additions and 1223 deletions

45
lapi.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lapi.c,v 2.47 2005/08/24 16:15:49 roberto Exp roberto $ ** $Id: lapi.c,v 2.52 2005/12/22 16:19:56 roberto Exp roberto $
** Lua API ** Lua API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -40,7 +40,7 @@ const char lua_ident[] =
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) #define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
#define api_checkvalidindex(L, i) api_check(L, (i) != &luaO_nilobject) #define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject)
#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} #define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
@@ -50,7 +50,7 @@ static TValue *index2adr (lua_State *L, int idx) {
if (idx > 0) { if (idx > 0) {
TValue *o = L->base + (idx - 1); TValue *o = L->base + (idx - 1);
api_check(L, idx <= L->ci->top - L->base); api_check(L, idx <= L->ci->top - L->base);
if (o >= L->top) return cast(TValue *, &luaO_nilobject); if (o >= L->top) return cast(TValue *, luaO_nilobject);
else return o; else return o;
} }
else if (idx > LUA_REGISTRYINDEX) { else if (idx > LUA_REGISTRYINDEX) {
@@ -70,7 +70,7 @@ static TValue *index2adr (lua_State *L, int idx) {
idx = LUA_GLOBALSINDEX - idx; idx = LUA_GLOBALSINDEX - idx;
return (idx <= func->c.nupvalues) return (idx <= func->c.nupvalues)
? &func->c.upvalue[idx-1] ? &func->c.upvalue[idx-1]
: cast(TValue *, &luaO_nilobject); : cast(TValue *, luaO_nilobject);
} }
} }
} }
@@ -141,7 +141,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
setthvalue(L, L->top, L1); setthvalue(L, L->top, L1);
api_incr_top(L); api_incr_top(L);
lua_unlock(L); lua_unlock(L);
luai_userstateopen(L1); luai_userstatethread(L, L1);
return L1; return L1;
} }
@@ -153,7 +153,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
LUA_API int lua_gettop (lua_State *L) { LUA_API int lua_gettop (lua_State *L) {
return cast(int, L->top - L->base); return cast_int(L->top - L->base);
} }
@@ -234,7 +234,7 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) {
LUA_API int lua_type (lua_State *L, int idx) { LUA_API int lua_type (lua_State *L, int idx) {
StkId o = index2adr(L, idx); StkId o = index2adr(L, idx);
return (o == &luaO_nilobject) ? LUA_TNONE : ttype(o); return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
} }
@@ -272,7 +272,7 @@ LUA_API int lua_isuserdata (lua_State *L, int idx) {
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
StkId o1 = index2adr(L, index1); StkId o1 = index2adr(L, index1);
StkId o2 = index2adr(L, index2); StkId o2 = index2adr(L, index2);
return (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0 return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
: luaO_rawequalObj(o1, o2); : luaO_rawequalObj(o1, o2);
} }
@@ -283,8 +283,7 @@ LUA_API int lua_equal (lua_State *L, int index1, int index2) {
lua_lock(L); /* may call tag method */ lua_lock(L); /* may call tag method */
o1 = index2adr(L, index1); o1 = index2adr(L, index1);
o2 = index2adr(L, index2); o2 = index2adr(L, index2);
i = (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0 i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
: equalobj(L, o1, o2);
lua_unlock(L); lua_unlock(L);
return i; return i;
} }
@@ -296,7 +295,7 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
lua_lock(L); /* may call tag method */ lua_lock(L); /* may call tag method */
o1 = index2adr(L, index1); o1 = index2adr(L, index1);
o2 = index2adr(L, index2); o2 = index2adr(L, index2);
i = (o1 == &luaO_nilobject || o2 == &luaO_nilobject) ? 0 i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
: luaV_lessthan(L, o1, o2); : luaV_lessthan(L, o1, o2);
lua_unlock(L); lua_unlock(L);
return i; return i;
@@ -430,7 +429,7 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
lua_lock(L); lua_lock(L);
setnvalue(L->top, cast(lua_Number, n)); setnvalue(L->top, cast_num(n));
api_incr_top(L); api_incr_top(L);
lua_unlock(L); lua_unlock(L);
} }
@@ -910,7 +909,11 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
} }
case LUA_GCCOUNT: { case LUA_GCCOUNT: {
/* GC values are expressed in Kbytes: #bytes/2^10 */ /* GC values are expressed in Kbytes: #bytes/2^10 */
res = cast(int, g->totalbytes >> 10); res = cast_int(g->totalbytes >> 10);
break;
}
case LUA_GCCOUNTB: {
res = cast_int(g->totalbytes & 0x3ff);
break; break;
} }
case LUA_GCSTEP: { case LUA_GCSTEP: {
@@ -979,7 +982,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
api_checknelems(L, n); api_checknelems(L, n);
if (n >= 2) { if (n >= 2) {
luaC_checkGC(L); luaC_checkGC(L);
luaV_concat(L, n, cast(int, L->top - L->base) - 1); luaV_concat(L, n, cast_int(L->top - L->base) - 1);
L->top -= (n-1); L->top -= (n-1);
} }
else if (n == 0) { /* push empty string */ else if (n == 0) { /* push empty string */
@@ -992,8 +995,20 @@ LUA_API void lua_concat (lua_State *L, int n) {
LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
lua_Alloc f;
lua_lock(L);
if (ud) *ud = G(L)->ud; if (ud) *ud = G(L)->ud;
return G(L)->frealloc; f = G(L)->frealloc;
lua_unlock(L);
return f;
}
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
lua_lock(L);
G(L)->ud = ud;
G(L)->frealloc = f;
lua_unlock(L);
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lauxlib.c,v 1.151 2005/08/26 17:36:32 roberto Exp roberto $ ** $Id: lauxlib.c,v 1.157 2005/12/29 15:32:11 roberto Exp roberto $
** Auxiliary functions for building Lua libraries ** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -176,8 +176,7 @@ LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
LUALIB_API lua_Number luaL_optnumber (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; return luaL_opt(L, luaL_checknumber, narg, def);
else return luaL_checknumber(L, narg);
} }
@@ -190,16 +189,16 @@ LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
lua_Integer def) { lua_Integer def) {
if (lua_isnoneornil(L, narg)) return def; return luaL_opt(L, luaL_checkinteger, narg, def);
else return luaL_checkinteger(L, narg);
} }
LUALIB_API int luaL_getmetafield (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? */ if (!lua_getmetatable(L, obj)) /* no metatable? */
return 0; return 0;
lua_getfield(L, -1, event); lua_pushstring(L, event);
lua_rawget(L, -2);
if (lua_isnil(L, -1)) { if (lua_isnil(L, -1)) {
lua_pop(L, 2); /* remove metatable and metafield */ lua_pop(L, 2); /* remove metatable and metafield */
return 0; return 0;
@@ -227,16 +226,24 @@ LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
} }
static int libsize (const luaL_Reg *l) {
int size = 0;
for (; l->name; l++) size++;
return size;
}
LUALIB_API void luaI_openlib (lua_State *L, const char *libname, LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
const luaL_Reg *l, int nup) { const luaL_Reg *l, int nup) {
if (libname) { if (libname) {
int size = libsize(l);
/* check whether lib already exists */ /* check whether lib already exists */
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size);
lua_getfield(L, -1, libname); /* get _LOADED[libname] */ lua_getfield(L, -1, libname); /* get _LOADED[libname] */
if (!lua_istable(L, -1)) { /* not found? */ if (!lua_istable(L, -1)) { /* not found? */
lua_pop(L, 1); /* remove previous result */ lua_pop(L, 1); /* remove previous result */
/* try global variable (and create one if it does not exist) */ /* try global variable (and create one if it does not exist) */
if (luaL_findtable(L, LUA_GLOBALSINDEX, libname) != NULL) if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
luaL_error(L, "name conflict for module " LUA_QS, libname); luaL_error(L, "name conflict for module " LUA_QS, libname);
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
@@ -288,24 +295,34 @@ static void getsizes (lua_State *L) {
LUALIB_API void luaL_setn (lua_State *L, int t, int n) { LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
t = abs_index(L, t); t = abs_index(L, t);
getsizes(L); lua_pushliteral(L, "n");
lua_pushvalue(L, t); lua_rawget(L, t);
lua_pushinteger(L, n); if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
lua_rawset(L, -3); /* sizes[t] = n */ lua_pushliteral(L, "n"); /* use it */
lua_pop(L, 1); /* remove `sizes' */ lua_pushinteger(L, n);
lua_rawset(L, t);
}
else { /* use `sizes' */
getsizes(L);
lua_pushvalue(L, t);
lua_pushinteger(L, n);
lua_rawset(L, -3); /* sizes[t] = n */
lua_pop(L, 1); /* remove `sizes' */
}
} }
LUALIB_API int luaL_getn (lua_State *L, int t) { LUALIB_API int luaL_getn (lua_State *L, int t) {
int n; int n;
t = abs_index(L, t); t = abs_index(L, t);
getsizes(L); /* try sizes[t] */ lua_pushliteral(L, "n"); /* try t.n */
lua_rawget(L, t);
if ((n = checkint(L, 1)) >= 0) return n;
getsizes(L); /* else try sizes[t] */
lua_pushvalue(L, t); lua_pushvalue(L, t);
lua_rawget(L, -2); lua_rawget(L, -2);
if ((n = checkint(L, 2)) >= 0) return n; if ((n = checkint(L, 2)) >= 0) return n;
lua_getfield(L, t, "n"); /* else try t.n */ return (int)lua_objlen(L, t);
if ((n = checkint(L, 1)) >= 0) return n;
return lua_objlen(L, t);
} }
#endif #endif
@@ -332,7 +349,7 @@ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
LUALIB_API const char *luaL_findtable (lua_State *L, int idx, LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
const char *fname) { const char *fname, int szhint) {
const char *e; const char *e;
lua_pushvalue(L, idx); lua_pushvalue(L, idx);
do { do {
@@ -342,7 +359,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
lua_rawget(L, -2); lua_rawget(L, -2);
if (lua_isnil(L, -1)) { /* no such field? */ if (lua_isnil(L, -1)) { /* no such field? */
lua_pop(L, 1); /* remove this nil */ lua_pop(L, 1); /* remove this nil */
lua_newtable(L); /* create a new table for field */ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
lua_pushlstring(L, fname, e - fname); lua_pushlstring(L, fname, e - fname);
lua_pushvalue(L, -2); lua_pushvalue(L, -2);
lua_settable(L, -4); /* set new table into field */ lua_settable(L, -4); /* set new table into field */
@@ -470,7 +487,7 @@ LUALIB_API int luaL_ref (lua_State *L, int t) {
lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
} }
else { /* no free elements */ else { /* no free elements */
ref = lua_objlen(L, t); ref = (int)lua_objlen(L, t);
ref++; /* create new reference */ ref++; /* create new reference */
} }
lua_rawseti(L, t, ref); lua_rawseti(L, t, ref);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lauxlib.h,v 1.84 2005/08/26 17:36:32 roberto Exp roberto $ ** $Id: lauxlib.h,v 1.86 2005/10/21 13:47:42 roberto Exp roberto $
** Auxiliary functions for building Lua libraries ** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -86,7 +86,7 @@ LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r); const char *r);
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
const char *fname); const char *fname, int szhint);
@@ -114,6 +114,7 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
/* /*
** {====================================================== ** {======================================================

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lbaselib.c,v 1.181 2005/08/15 14:12:32 roberto Exp roberto $ ** $Id: lbaselib.c,v 1.188 2005/12/29 15:32:11 roberto Exp roberto $
** Basic library ** Basic library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -196,9 +196,23 @@ static int luaB_collectgarbage (lua_State *L) {
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
int o = luaL_checkoption(L, 1, "collect", opts); int o = luaL_checkoption(L, 1, "collect", opts);
int ex = luaL_optinteger(L, 2, 0); int ex = luaL_optint(L, 2, 0);
lua_pushinteger(L, lua_gc(L, optsnum[o], ex)); int res = lua_gc(L, optsnum[o], ex);
return 1; switch (optsnum[o]) {
case LUA_GCCOUNT: {
int b = lua_gc(L, LUA_GCCOUNTB, 0);
lua_pushnumber(L, res + ((lua_Number)b/1024));
return 1;
}
case LUA_GCSTEP: {
lua_pushboolean(L, res);
return 1;
}
default: {
lua_pushnumber(L, res);
return 1;
}
}
} }
@@ -326,12 +340,10 @@ static int luaB_assert (lua_State *L) {
static int luaB_unpack (lua_State *L) { static int luaB_unpack (lua_State *L) {
int i = luaL_optint(L, 2, 1); int i, e, n;
int e = luaL_optint(L, 3, -1);
int n;
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
if (e == -1) i = luaL_optint(L, 2, 1);
e = luaL_getn(L, 1); e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
n = e - i + 1; /* number of elements */ n = e - i + 1; /* number of elements */
if (n <= 0) return 0; /* empty range */ if (n <= 0) return 0; /* empty range */
luaL_checkstack(L, n, "table too big to unpack"); luaL_checkstack(L, n, "table too big to unpack");
@@ -349,8 +361,9 @@ static int luaB_select (lua_State *L) {
} }
else { else {
int i = luaL_checkint(L, 1); int i = luaL_checkint(L, 1);
if (i <= 0) i = 1; if (i < 0) i = n + i;
else if (i >= n) i = n; else if (i > n) i = n;
luaL_argcheck(L, 1 <= i, 1, "index out of range");
return n - i; return n - i;
} }
} }
@@ -560,7 +573,7 @@ static int luaB_costatus (lua_State *L) {
lua_pushliteral(L, "dead"); lua_pushliteral(L, "dead");
else else
lua_pushliteral(L, "suspended"); /* initial state */ lua_pushliteral(L, "suspended"); /* initial state */
break; break;
} }
default: /* some error occured */ default: /* some error occured */
lua_pushliteral(L, "dead"); lua_pushliteral(L, "dead");
@@ -601,27 +614,24 @@ static void auxopen (lua_State *L, const char *name,
static void base_open (lua_State *L) { static void base_open (lua_State *L) {
/* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_register(L, NULL, base_funcs); /* open lib into global table */ lua_setglobal(L, "_G");
/* open lib into global table */
luaL_register(L, "_G", base_funcs);
lua_pushliteral(L, LUA_VERSION); lua_pushliteral(L, LUA_VERSION);
lua_setglobal(L, "_VERSION"); /* set global _VERSION */ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
/* `ipairs' and `pairs' need auxiliary functions as upvalues */ /* `ipairs' and `pairs' need auxiliary functions as upvalues */
auxopen(L, "ipairs", luaB_ipairs, ipairsaux); auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
auxopen(L, "pairs", luaB_pairs, luaB_next); auxopen(L, "pairs", luaB_pairs, luaB_next);
/* `newproxy' needs a weaktable as upvalue */ /* `newproxy' needs a weaktable as upvalue */
lua_newtable(L); /* new table `w' */ lua_createtable(L, 0, 1); /* new table `w' */
lua_pushvalue(L, -1); /* `w' will be its own metatable */ lua_pushvalue(L, -1); /* `w' will be its own metatable */
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
lua_pushliteral(L, "kv"); lua_pushliteral(L, "kv");
lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
lua_pushcclosure(L, luaB_newproxy, 1); lua_pushcclosure(L, luaB_newproxy, 1);
lua_setglobal(L, "newproxy"); /* set global `newproxy' */ lua_setglobal(L, "newproxy"); /* set global `newproxy' */
/* create register._LOADED to track loaded modules */
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED");
/* set global _G */
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setglobal(L, "_G");
} }

287
lcode.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lcode.c,v 2.15 2005/08/17 18:32:09 roberto Exp $ ** $Id: lcode.c,v 2.23 2005/11/25 13:29:32 roberto Exp roberto $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -27,16 +27,24 @@
#define hasjumps(e) ((e)->t != (e)->f) #define hasjumps(e) ((e)->t != (e)->f)
static int isnumeral(expdesc *e) {
return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
}
void luaK_nil (FuncState *fs, int from, int n) { void luaK_nil (FuncState *fs, int from, int n) {
Instruction *previous; Instruction *previous;
if (fs->pc > fs->lasttarget && /* no jumps to current position? */ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) { if (fs->pc == 0) /* function start? */
int pfrom = GETARG_A(*previous); return; /* positions are already clean */
int pto = GETARG_B(*previous); if (GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) {
if (pfrom <= from && from <= pto+1) { /* can connect both? */ int pfrom = GETARG_A(*previous);
if (from+n-1 > pto) int pto = GETARG_B(*previous);
SETARG_B(*previous, from+n-1); if (pfrom <= from && from <= pto+1) { /* can connect both? */
return; if (from+n-1 > pto)
SETARG_B(*previous, from+n-1);
return;
}
} }
} }
luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */
@@ -115,20 +123,22 @@ static int need_value (FuncState *fs, int list) {
} }
static void patchtestreg (Instruction *i, int reg) { static int patchtestreg (FuncState *fs, int node, int reg) {
if (reg != NO_REG) Instruction *i = getjumpcontrol(fs, node);
if (GET_OPCODE(*i) != OP_TESTSET)
return 0; /* cannot patch other instructions */
if (reg != NO_REG && reg != GETARG_B(*i))
SETARG_A(*i, reg); SETARG_A(*i, reg);
else /* no register to put value; change TESTSET to TEST */ else /* no register to put value or register already has the value */
*i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
return 1;
} }
static void removevalues (FuncState *fs, int list) { static void removevalues (FuncState *fs, int list) {
for (; list != NO_JUMP; list = getjump(fs, list)) { for (; list != NO_JUMP; list = getjump(fs, list))
Instruction *i = getjumpcontrol(fs, list); patchtestreg(fs, list, NO_REG);
if (GET_OPCODE(*i) == OP_TESTSET)
patchtestreg(i, NO_REG);
}
} }
@@ -136,11 +146,8 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
int dtarget) { int dtarget) {
while (list != NO_JUMP) { while (list != NO_JUMP) {
int next = getjump(fs, list); int next = getjump(fs, list);
Instruction *i = getjumpcontrol(fs, list); if (patchtestreg(fs, list, reg))
if (GET_OPCODE(*i) == OP_TESTSET) {
patchtestreg(i, reg);
fixjump(fs, list, vtarget); fixjump(fs, list, vtarget);
}
else else
fixjump(fs, list, dtarget); /* jump to default target */ fixjump(fs, list, dtarget); /* jump to default target */
list = next; list = next;
@@ -189,7 +196,7 @@ void luaK_checkstack (FuncState *fs, int n) {
if (newstack > fs->f->maxstacksize) { if (newstack > fs->f->maxstacksize) {
if (newstack >= MAXSTACK) if (newstack >= MAXSTACK)
luaX_syntaxerror(fs->ls, "function or expression too complex"); luaX_syntaxerror(fs->ls, "function or expression too complex");
fs->f->maxstacksize = cast(lu_byte, newstack); fs->f->maxstacksize = cast_byte(newstack);
} }
} }
@@ -210,7 +217,7 @@ static void freereg (FuncState *fs, int reg) {
static void freeexp (FuncState *fs, expdesc *e) { static void freeexp (FuncState *fs, expdesc *e) {
if (e->k == VNONRELOC) if (e->k == VNONRELOC)
freereg(fs, e->info); freereg(fs, e->u.s.info);
} }
@@ -220,11 +227,11 @@ static int addk (FuncState *fs, TValue *k, TValue *v) {
Proto *f = fs->f; Proto *f = fs->f;
int oldsize = f->sizek; int oldsize = f->sizek;
if (ttisnumber(idx)) { if (ttisnumber(idx)) {
lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v)); lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
return cast(int, nvalue(idx)); return cast_int(nvalue(idx));
} }
else { /* constant not found; create a new entry */ else { /* constant not found; create a new entry */
setnvalue(idx, cast(lua_Number, fs->nk)); setnvalue(idx, cast_num(fs->nk));
luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
MAXARG_Bx, "constant table overflow"); MAXARG_Bx, "constant table overflow");
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
@@ -280,7 +287,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
void luaK_setoneret (FuncState *fs, expdesc *e) { void luaK_setoneret (FuncState *fs, expdesc *e) {
if (e->k == VCALL) { /* expression is an open function call? */ if (e->k == VCALL) { /* expression is an open function call? */
e->k = VNONRELOC; e->k = VNONRELOC;
e->info = GETARG_A(getcode(fs, e)); e->u.s.info = GETARG_A(getcode(fs, e));
} }
else if (e->k == VVARARG) { else if (e->k == VVARARG) {
SETARG_B(getcode(fs, e), 2); SETARG_B(getcode(fs, e), 2);
@@ -296,19 +303,19 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
break; break;
} }
case VUPVAL: { case VUPVAL: {
e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0); e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
e->k = VRELOCABLE; e->k = VRELOCABLE;
break; break;
} }
case VGLOBAL: { case VGLOBAL: {
e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info); e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
e->k = VRELOCABLE; e->k = VRELOCABLE;
break; break;
} }
case VINDEXED: { case VINDEXED: {
freereg(fs, e->aux); freereg(fs, e->u.s.aux);
freereg(fs, e->info); freereg(fs, e->u.s.info);
e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux); e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
e->k = VRELOCABLE; e->k = VRELOCABLE;
break; break;
} }
@@ -340,7 +347,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
break; break;
} }
case VK: { case VK: {
luaK_codeABx(fs, OP_LOADK, reg, e->info); luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
break;
}
case VKNUM: {
luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
break; break;
} }
case VRELOCABLE: { case VRELOCABLE: {
@@ -349,8 +360,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
break; break;
} }
case VNONRELOC: { case VNONRELOC: {
if (reg != e->info) if (reg != e->u.s.info)
luaK_codeABC(fs, OP_MOVE, reg, e->info, 0); luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
break; break;
} }
default: { default: {
@@ -358,7 +369,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
return; /* nothing to do... */ return; /* nothing to do... */
} }
} }
e->info = reg; e->u.s.info = reg;
e->k = VNONRELOC; e->k = VNONRELOC;
} }
@@ -374,15 +385,13 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) {
static void exp2reg (FuncState *fs, expdesc *e, int reg) { static void exp2reg (FuncState *fs, expdesc *e, int reg) {
discharge2reg(fs, e, reg); discharge2reg(fs, e, reg);
if (e->k == VJMP) if (e->k == VJMP)
luaK_concat(fs, &e->t, e->info); /* put this jump in `t' list */ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */
if (hasjumps(e)) { if (hasjumps(e)) {
int final; /* position after whole expression */ int final; /* position after whole expression */
int p_f = NO_JUMP; /* position of an eventual LOAD false */ int p_f = NO_JUMP; /* position of an eventual LOAD false */
int p_t = NO_JUMP; /* position of an eventual LOAD true */ int p_t = NO_JUMP; /* position of an eventual LOAD true */
if (need_value(fs, e->t) || need_value(fs, e->f)) { if (need_value(fs, e->t) || need_value(fs, e->f)) {
int fj = NO_JUMP; /* first jump (over LOAD ops.) */ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
if (e->k != VJMP)
fj = luaK_jump(fs);
p_f = code_label(fs, reg, 0, 1); p_f = code_label(fs, reg, 0, 1);
p_t = code_label(fs, reg, 1, 0); p_t = code_label(fs, reg, 1, 0);
luaK_patchtohere(fs, fj); luaK_patchtohere(fs, fj);
@@ -392,7 +401,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) {
patchlistaux(fs, e->t, final, reg, p_t); patchlistaux(fs, e->t, final, reg, p_t);
} }
e->f = e->t = NO_JUMP; e->f = e->t = NO_JUMP;
e->info = reg; e->u.s.info = reg;
e->k = VNONRELOC; e->k = VNONRELOC;
} }
@@ -408,14 +417,14 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
int luaK_exp2anyreg (FuncState *fs, expdesc *e) { int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
luaK_dischargevars(fs, e); luaK_dischargevars(fs, e);
if (e->k == VNONRELOC) { if (e->k == VNONRELOC) {
if (!hasjumps(e)) return e->info; /* exp is already in a register */ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */
if (e->info >= fs->nactvar) { /* reg. is not a local? */ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
exp2reg(fs, e, e->info); /* put value on it */ exp2reg(fs, e, e->u.s.info); /* put value on it */
return e->info; return e->u.s.info;
} }
} }
luaK_exp2nextreg(fs, e); /* default */ luaK_exp2nextreg(fs, e); /* default */
return e->info; return e->u.s.info;
} }
@@ -430,19 +439,22 @@ void luaK_exp2val (FuncState *fs, expdesc *e) {
int luaK_exp2RK (FuncState *fs, expdesc *e) { int luaK_exp2RK (FuncState *fs, expdesc *e) {
luaK_exp2val(fs, e); luaK_exp2val(fs, e);
switch (e->k) { switch (e->k) {
case VKNUM:
case VTRUE: case VTRUE:
case VFALSE: case VFALSE:
case VNIL: { case VNIL: {
if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
e->info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); e->u.s.info = (e->k == VNIL) ? nilK(fs) :
(e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
boolK(fs, (e->k == VTRUE));
e->k = VK; e->k = VK;
return RKASK(e->info); return RKASK(e->u.s.info);
} }
else break; else break;
} }
case VK: { case VK: {
if (e->info <= MAXINDEXRK) /* constant fit in argC? */ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */
return RKASK(e->info); return RKASK(e->u.s.info);
else break; else break;
} }
default: break; default: break;
@@ -456,22 +468,22 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
switch (var->k) { switch (var->k) {
case VLOCAL: { case VLOCAL: {
freeexp(fs, ex); freeexp(fs, ex);
exp2reg(fs, ex, var->info); exp2reg(fs, ex, var->u.s.info);
return; return;
} }
case VUPVAL: { case VUPVAL: {
int e = luaK_exp2anyreg(fs, ex); int e = luaK_exp2anyreg(fs, ex);
luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0); luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
break; break;
} }
case VGLOBAL: { case VGLOBAL: {
int e = luaK_exp2anyreg(fs, ex); int e = luaK_exp2anyreg(fs, ex);
luaK_codeABx(fs, OP_SETGLOBAL, e, var->info); luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
break; break;
} }
case VINDEXED: { case VINDEXED: {
int e = luaK_exp2RK(fs, ex); int e = luaK_exp2RK(fs, ex);
luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e); luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
break; break;
} }
default: { default: {
@@ -489,15 +501,15 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
freeexp(fs, e); freeexp(fs, e);
func = fs->freereg; func = fs->freereg;
luaK_reserveregs(fs, 2); luaK_reserveregs(fs, 2);
luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key)); luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
freeexp(fs, key); freeexp(fs, key);
e->info = func; e->u.s.info = func;
e->k = VNONRELOC; e->k = VNONRELOC;
} }
static void invertjump (FuncState *fs, expdesc *e) { static void invertjump (FuncState *fs, expdesc *e) {
Instruction *pc = getjumpcontrol(fs, e->info); Instruction *pc = getjumpcontrol(fs, e->u.s.info);
lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
GET_OPCODE(*pc) != OP_TEST); GET_OPCODE(*pc) != OP_TEST);
SETARG_A(*pc, !(GETARG_A(*pc))); SETARG_A(*pc, !(GETARG_A(*pc)));
@@ -515,7 +527,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
} }
discharge2anyreg(fs, e); discharge2anyreg(fs, e);
freeexp(fs, e); freeexp(fs, e);
return condjump(fs, OP_TESTSET, NO_REG, e->info, cond); return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
} }
@@ -523,7 +535,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
int pc; /* pc of last jump */ int pc; /* pc of last jump */
luaK_dischargevars(fs, e); luaK_dischargevars(fs, e);
switch (e->k) { switch (e->k) {
case VK: case VTRUE: { case VK: case VKNUM: case VTRUE: {
pc = NO_JUMP; /* always true; do nothing */ pc = NO_JUMP; /* always true; do nothing */
break; break;
} }
@@ -533,7 +545,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
} }
case VJMP: { case VJMP: {
invertjump(fs, e); invertjump(fs, e);
pc = e->info; pc = e->u.s.info;
break; break;
} }
default: { default: {
@@ -547,7 +559,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
} }
void luaK_goiffalse (FuncState *fs, expdesc *e) { static void luaK_goiffalse (FuncState *fs, expdesc *e) {
int pc; /* pc of last jump */ int pc; /* pc of last jump */
luaK_dischargevars(fs, e); luaK_dischargevars(fs, e);
switch (e->k) { switch (e->k) {
@@ -560,7 +572,7 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
break; break;
} }
case VJMP: { case VJMP: {
pc = e->info; pc = e->u.s.info;
break; break;
} }
default: { default: {
@@ -581,7 +593,7 @@ static void codenot (FuncState *fs, expdesc *e) {
e->k = VTRUE; e->k = VTRUE;
break; break;
} }
case VK: case VTRUE: { case VK: case VKNUM: case VTRUE: {
e->k = VFALSE; e->k = VFALSE;
break; break;
} }
@@ -593,7 +605,7 @@ static void codenot (FuncState *fs, expdesc *e) {
case VNONRELOC: { case VNONRELOC: {
discharge2anyreg(fs, e); discharge2anyreg(fs, e);
freeexp(fs, e); freeexp(fs, e);
e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0); e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
e->k = VRELOCABLE; e->k = VRELOCABLE;
break; break;
} }
@@ -610,34 +622,81 @@ static void codenot (FuncState *fs, expdesc *e) {
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
t->aux = luaK_exp2RK(fs, k); t->u.s.aux = luaK_exp2RK(fs, k);
t->k = VINDEXED; t->k = VINDEXED;
} }
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
lua_Number v1, v2, r;
if (!isnumeral(e1) || !isnumeral(e2)) return 0;
v1 = e1->u.nval;
v2 = e2->u.nval;
switch (op) {
case OP_ADD: r = luai_numadd(v1, v2); break;
case OP_SUB: r = luai_numsub(v1, v2); break;
case OP_MUL: r = luai_nummul(v1, v2); break;
case OP_DIV:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
r = luai_numdiv(v1, v2); break;
case OP_MOD:
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
r = luai_nummod(v1, v2); break;
case OP_POW: r = luai_numpow(v1, v2); break;
case OP_UNM: r = luai_numunm(v1); break;
case OP_LEN: return 0; /* no constant folding for 'len' */
default: lua_assert(0); r = 0; break;
}
if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
e1->u.nval = r;
return 1;
}
static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
if (constfolding(op, e1, e2))
return;
else {
int o1 = luaK_exp2RK(fs, e1);
int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
freeexp(fs, e2);
freeexp(fs, e1);
e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
e1->k = VRELOCABLE;
}
}
static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
expdesc *e2) {
int o1 = luaK_exp2RK(fs, e1);
int o2 = luaK_exp2RK(fs, e2);
freeexp(fs, e2);
freeexp(fs, e1);
if (cond == 0 && op != OP_EQ) {
int temp; /* exchange args to replace by `<' or `<=' */
temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
cond = 1;
}
e1->u.s.info = condjump(fs, op, cond, o1, o2);
e1->k = VJMP;
}
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
expdesc e2;
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
switch (op) { switch (op) {
case OPR_MINUS: { case OPR_MINUS: {
luaK_exp2val(fs, e); if (e->k == VK)
if (e->k == VK && ttisnumber(&fs->f->k[e->info])) luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
e->info = luaK_numberK(fs, luai_numunm(L, nvalue(&fs->f->k[e->info]))); codearith(fs, OP_UNM, e, &e2);
else {
luaK_exp2anyreg(fs, e);
freeexp(fs, e);
e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0);
e->k = VRELOCABLE;
}
break;
}
case OPR_NOT: {
codenot(fs, e);
break; break;
} }
case OPR_NOT: codenot(fs, e); break;
case OPR_LEN: { case OPR_LEN: {
luaK_exp2anyreg(fs, e); luaK_exp2anyreg(fs, e); /* cannot operate on constants */
freeexp(fs, e); codearith(fs, OP_LEN, e, &e2);
e->info = luaK_codeABC(fs, OP_LEN, 0, e->info, 0);
e->k = VRELOCABLE;
break; break;
} }
default: lua_assert(0); default: lua_assert(0);
@@ -660,74 +719,58 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
break; break;
} }
default: { default: {
luaK_exp2RK(fs, v); if (!isnumeral(v)) luaK_exp2RK(fs, v);
break; break;
} }
} }
} }
static void codebinop (FuncState *fs, expdesc *res, BinOpr op,
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 */
}
else if (op == OPR_NE) cond = 0;
res->info = condjump(fs, ops[op - OPR_NE], cond, o1, o2);
res->k = VJMP;
}
}
void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
switch (op) { switch (op) {
case OPR_AND: { case OPR_AND: {
lua_assert(e1->t == NO_JUMP); /* list must be closed */ lua_assert(e1->t == NO_JUMP); /* list must be closed */
luaK_dischargevars(fs, e2); luaK_dischargevars(fs, e2);
luaK_concat(fs, &e1->f, e2->f); luaK_concat(fs, &e1->f, e2->f);
e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t; e1->k = e2->k; e1->u.s.info = e2->u.s.info;
e1->u.s.aux = e2->u.s.aux; e1->t = e2->t;
break; break;
} }
case OPR_OR: { case OPR_OR: {
lua_assert(e1->f == NO_JUMP); /* list must be closed */ lua_assert(e1->f == NO_JUMP); /* list must be closed */
luaK_dischargevars(fs, e2); luaK_dischargevars(fs, e2);
luaK_concat(fs, &e1->t, e2->t); luaK_concat(fs, &e1->t, e2->t);
e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f; e1->k = e2->k; e1->u.s.info = e2->u.s.info;
e1->u.s.aux = e2->u.s.aux; e1->f = e2->f;
break; break;
} }
case OPR_CONCAT: { case OPR_CONCAT: {
luaK_exp2val(fs, e2); luaK_exp2val(fs, e2);
if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1); lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
freeexp(fs, e1); freeexp(fs, e1);
SETARG_B(getcode(fs, e2), e1->info); SETARG_B(getcode(fs, e2), e1->u.s.info);
e1->k = e2->k; e1->info = e2->info; e1->k = e2->k; e1->u.s.info = e2->u.s.info;
} }
else { else {
luaK_exp2nextreg(fs, e2); luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
freeexp(fs, e2); codearith(fs, OP_CONCAT, e1, e2);
freeexp(fs, e1);
e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info);
e1->k = VRELOCABLE;
} }
break; break;
} }
default: { case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
int o1 = luaK_exp2RK(fs, e1); case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
int o2 = luaK_exp2RK(fs, e2); case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
freeexp(fs, e2); case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
freeexp(fs, e1); case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
codebinop(fs, e1, op, o1, o2); case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
} case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
default: lua_assert(0);
} }
} }
@@ -737,7 +780,7 @@ void luaK_fixline (FuncState *fs, int line) {
} }
int luaK_code (FuncState *fs, Instruction i, int line) { static int luaK_code (FuncState *fs, Instruction i, int line) {
Proto *f = fs->f; Proto *f = fs->f;
dischargejpc(fs); /* `pc' will change */ dischargejpc(fs); /* `pc' will change */
/* put new instruction in code array */ /* put new instruction in code array */

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lcode.h,v 1.44 2005/05/20 15:53:42 roberto Exp $ ** $Id: lcode.h,v 1.46 2005/10/03 14:02:40 roberto Exp roberto $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -24,7 +24,7 @@
** grep "ORDER OPR" if you change these enums ** grep "ORDER OPR" if you change these enums
*/ */
typedef enum BinOpr { typedef enum BinOpr {
OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV, OPR_MOD, OPR_POW, OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
OPR_CONCAT, OPR_CONCAT,
OPR_NE, OPR_EQ, OPR_NE, OPR_EQ,
OPR_LT, OPR_LE, OPR_GT, OPR_GE, OPR_LT, OPR_LE, OPR_GT, OPR_GE,
@@ -37,13 +37,12 @@ typedef enum BinOpr {
typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
#define getcode(fs,e) ((fs)->f->code[(e)->info]) #define getcode(fs,e) ((fs)->f->code[(e)->u.s.info])
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i, int line);
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line); LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
@@ -60,7 +59,6 @@ LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ldblib.c,v 1.100 2005/08/15 14:12:32 roberto Exp roberto $ ** $Id: ldblib.c,v 1.103 2005/11/01 16:08:32 roberto Exp roberto $
** Interface from Lua to its debug API ** Interface from Lua to its debug API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -19,6 +19,12 @@
static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
}
static int db_getmetatable (lua_State *L) { static int db_getmetatable (lua_State *L) {
luaL_checkany(L, 1); luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) { if (!lua_getmetatable(L, 1)) {
@@ -110,7 +116,7 @@ static int db_getinfo (lua_State *L) {
return luaL_argerror(L, arg+1, "function or level expected"); return luaL_argerror(L, arg+1, "function or level expected");
if (!lua_getinfo(L1, options, &ar)) if (!lua_getinfo(L1, options, &ar))
return luaL_argerror(L, arg+2, "invalid option"); return luaL_argerror(L, arg+2, "invalid option");
lua_newtable(L); lua_createtable(L, 0, 2);
if (strchr(options, 'S')) { if (strchr(options, 'S')) {
settabss(L, "source", ar.source); settabss(L, "source", ar.source);
settabss(L, "short_src", ar.short_src); settabss(L, "short_src", ar.short_src);
@@ -240,7 +246,7 @@ static void gethooktable (lua_State *L) {
lua_rawget(L, LUA_REGISTRYINDEX); lua_rawget(L, LUA_REGISTRYINDEX);
if (!lua_istable(L, -1)) { if (!lua_istable(L, -1)) {
lua_pop(L, 1); lua_pop(L, 1);
lua_newtable(L); lua_createtable(L, 0, 1);
lua_pushlightuserdata(L, (void *)&KEY_HOOK); lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_pushvalue(L, -2); lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX); lua_rawset(L, LUA_REGISTRYINDEX);
@@ -319,7 +325,7 @@ static int db_errorfb (lua_State *L) {
lua_State *L1 = getthread(L, &arg); lua_State *L1 = getthread(L, &arg);
lua_Debug ar; lua_Debug ar;
if (lua_isnumber(L, arg+2)) { if (lua_isnumber(L, arg+2)) {
level = lua_tointeger(L, arg+2); level = (int)lua_tointeger(L, arg+2);
lua_pop(L, 1); lua_pop(L, 1);
} }
else else
@@ -371,6 +377,7 @@ static const luaL_Reg dblib[] = {
{"gethook", db_gethook}, {"gethook", db_gethook},
{"getinfo", db_getinfo}, {"getinfo", db_getinfo},
{"getlocal", db_getlocal}, {"getlocal", db_getlocal},
{"getregistry", db_getregistry},
{"getmetatable", db_getmetatable}, {"getmetatable", db_getmetatable},
{"getupvalue", db_getupvalue}, {"getupvalue", db_getupvalue},
{"setfenv", db_setfenv}, {"setfenv", db_setfenv},

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 2.25 2005/07/11 13:59:03 roberto Exp roberto $ ** $Id: ldebug.c,v 2.28 2005/11/01 16:08:52 roberto Exp roberto $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -61,7 +61,7 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
L->hook = func; L->hook = func;
L->basehookcount = count; L->basehookcount = count;
resethookcount(L); resethookcount(L);
L->hookmask = cast(lu_byte, mask); L->hookmask = cast_byte(mask);
return 1; return 1;
} }
@@ -92,7 +92,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
} }
if (level == 0 && ci > L->base_ci) { /* level found? */ if (level == 0 && ci > L->base_ci) { /* level found? */
status = 1; status = 1;
ar->i_ci = cast(int, ci - L->base_ci); ar->i_ci = cast_int(ci - L->base_ci);
} }
else if (level < 0) { /* level is of a lost tail call? */ else if (level < 0) { /* level is of a lost tail call? */
status = 1; status = 1;
@@ -109,40 +109,39 @@ static Proto *getluaproto (CallInfo *ci) {
} }
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
const char *name; const char *name;
CallInfo *ci; Proto *fp = getluaproto(ci);
Proto *fp; if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
lua_lock(L); return name; /* is a local variable in a Lua function */
name = NULL; else {
ci = L->base_ci + ar->i_ci; StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
fp = getluaproto(ci); if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */
if (fp) { /* is a Lua function? */ return "(*temporary)";
name = luaF_getlocalname(fp, n, currentpc(L, ci)); else
if (name) return NULL;
luaA_pushobject(L, ci->base+(n-1)); /* push value */
} }
}
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
CallInfo *ci = L->base_ci + ar->i_ci;
const char *name = findlocal(L, ci, n);
lua_lock(L);
if (name)
luaA_pushobject(L, ci->base + (n - 1));
lua_unlock(L); lua_unlock(L);
return name; return name;
} }
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
const char *name; CallInfo *ci = L->base_ci + ar->i_ci;
CallInfo *ci; const char *name = findlocal(L, ci, n);
Proto *fp;
lua_lock(L); lua_lock(L);
name = NULL; if (name)
ci = L->base_ci + ar->i_ci; setobjs2s(L, ci->base + (n - 1), L->top - 1);
fp = getluaproto(ci); L->top--; /* pop value */
L->top--; /* pop new value */
if (fp) { /* is a Lua function? */
name = luaF_getlocalname(fp, n, currentpc(L, ci));
if (!name || name[0] == '(') /* `(' starts private locals */
name = NULL;
else
setobjs2s(L, ci->base+(n-1), L->top);
}
lua_unlock(L); lua_unlock(L);
return name; return name;
} }
@@ -321,7 +320,7 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
check(precheck(pt)); check(precheck(pt));
for (pc = 0; pc < lastpc; pc++) { for (pc = 0; pc < lastpc; pc++) {
const Instruction i = pt->code[pc]; Instruction i = pt->code[pc];
OpCode op = GET_OPCODE(i); OpCode op = GET_OPCODE(i);
int a = GETARG_A(i); int a = GETARG_A(i);
int b = 0; int b = 0;
@@ -348,7 +347,7 @@ static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
check(0 <= dest && dest < pt->sizecode); check(0 <= dest && dest < pt->sizecode);
if (dest > 0) { if (dest > 0) {
/* cannot jump to a setlist count */ /* cannot jump to a setlist count */
const Instruction d = pt->code[dest-1]; Instruction d = pt->code[dest-1];
check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)); check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0));
} }
} }
@@ -551,7 +550,7 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
const char *name = NULL; const char *name = NULL;
const char *t = luaT_typenames[ttype(o)]; const char *t = luaT_typenames[ttype(o)];
const char *kind = (isinstack(L->ci, o)) ? const char *kind = (isinstack(L->ci, o)) ?
getobjname(L, L->ci, cast(int, o - L->base), &name) : getobjname(L, L->ci, cast_int(o - L->base), &name) :
NULL; NULL;
if (kind) if (kind)
luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",

31
ldo.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 2.32 2005/08/24 16:15:49 roberto Exp roberto $ ** $Id: ldo.c,v 2.36 2005/10/23 17:52:42 roberto Exp roberto $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -71,7 +71,7 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
static void restore_stack_limit (lua_State *L) { static void restore_stack_limit (lua_State *L) {
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */
int inuse = cast(int, L->ci - L->base_ci); int inuse = cast_int(L->ci - L->base_ci);
if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
luaD_reallocCI(L, LUAI_MAXCALLS); luaD_reallocCI(L, LUAI_MAXCALLS);
} }
@@ -97,7 +97,7 @@ void luaD_throw (lua_State *L, int errcode) {
LUAI_THROW(L, L->errorJmp); LUAI_THROW(L, L->errorJmp);
} }
else { else {
L->status = cast(lu_byte, errcode); L->status = cast_byte(errcode);
if (G(L)->panic) { if (G(L)->panic) {
resetstack(L, errcode); resetstack(L, errcode);
lua_unlock(L); lua_unlock(L);
@@ -189,7 +189,7 @@ void luaD_callhook (lua_State *L, int event, int line) {
if (event == LUA_HOOKTAILRET) if (event == LUA_HOOKTAILRET)
ar.i_ci = 0; /* tail call; no debug information about it */ ar.i_ci = 0; /* tail call; no debug information about it */
else else
ar.i_ci = cast(int, L->ci - L->base_ci); ar.i_ci = cast_int(L->ci - L->base_ci);
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
L->ci->top = L->top + LUA_MINSTACK; L->ci->top = L->top + LUA_MINSTACK;
lua_assert(L->ci->top <= L->stack_last); lua_assert(L->ci->top <= L->stack_last);
@@ -221,8 +221,7 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
/* store counter in field `n' */ /* store counter in field `n' */
setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
cast(lua_Number, nvar));
} }
#endif #endif
/* move fixed parameters to final position */ /* move fixed parameters to final position */
@@ -276,10 +275,13 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
Proto *p = cl->p; Proto *p = cl->p;
luaD_checkstack(L, p->maxstacksize); luaD_checkstack(L, p->maxstacksize);
func = restorestack(L, funcr); func = restorestack(L, funcr);
if (!p->is_vararg) /* no varargs? */ if (!p->is_vararg) { /* no varargs? */
base = func + 1; base = func + 1;
if (L->top > base + p->numparams)
L->top = base + p->numparams;
}
else { /* vararg function */ else { /* vararg function */
int nargs = cast(int, L->top - func) - 1; int nargs = cast_int(L->top - func) - 1;
base = adjust_varargs(L, p, nargs); base = adjust_varargs(L, p, nargs);
func = restorestack(L, funcr); /* previous call may change the stack */ func = restorestack(L, funcr); /* previous call may change the stack */
} }
@@ -316,14 +318,12 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
lua_unlock(L); lua_unlock(L);
n = (*curr_func(L)->c.f)(L); /* do the actual call */ n = (*curr_func(L)->c.f)(L); /* do the actual call */
lua_lock(L); lua_lock(L);
if (n >= 0) { /* no yielding? */ if (n < 0) /* yielding? */
return PCRYIELD;
else {
luaD_poscall(L, L->top - n); luaD_poscall(L, L->top - n);
return PCRC; return PCRC;
} }
else {
ci->nresults = nresults;
return PCRYIELD;
}
} }
} }
@@ -400,7 +400,7 @@ static void resume (lua_State *L, void *ud) {
L->base = L->ci->base; L->base = L->ci->base;
} }
L->status = 0; L->status = 0;
luaV_execute(L, cast(int, L->ci - L->base_ci)); luaV_execute(L, cast_int(L->ci - L->base_ci));
} }
@@ -426,8 +426,9 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
lua_assert(L->errfunc == 0 && L->nCcalls == 0); lua_assert(L->errfunc == 0 && L->nCcalls == 0);
status = luaD_rawrunprotected(L, resume, L->top - nargs); status = luaD_rawrunprotected(L, resume, L->top - nargs);
if (status != 0) { /* error? */ if (status != 0) { /* error? */
L->status = cast(lu_byte, status); /* mark thread as `dead' */ L->status = cast_byte(status); /* mark thread as `dead' */
luaD_seterrorobj(L, status, L->top); luaD_seterrorobj(L, status, L->top);
L->ci->top = L->top;
} }
else else
status = L->status; status = L->status;

153
ldump.c
View File

@@ -1,6 +1,6 @@
/* /*
** $Id: ldump.c,v 2.5 2005/05/05 20:47:02 roberto Exp roberto $ ** $Id: ldump.c,v 1.15 2006/02/16 15:53:49 lhf Exp $
** save pre-compiled Lua chunks ** save precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -12,13 +12,9 @@
#include "lua.h" #include "lua.h"
#include "lobject.h" #include "lobject.h"
#include "lopcodes.h"
#include "lstate.h" #include "lstate.h"
#include "lundump.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 { typedef struct {
lua_State* L; lua_State* L;
lua_Writer writer; lua_Writer writer;
@@ -27,6 +23,9 @@ typedef struct {
int status; int status;
} DumpState; } DumpState;
#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
static void DumpBlock(const void* b, size_t size, DumpState* D) static void DumpBlock(const void* b, size_t size, DumpState* D)
{ {
if (D->status==0) if (D->status==0)
@@ -37,48 +36,84 @@ static void DumpBlock(const void* b, size_t size, DumpState* D)
} }
} }
static void DumpByte(int y, DumpState* D) static void DumpChar(int y, DumpState* D)
{ {
char x=(char)y; char x=(char)y;
DumpBlock(&x,sizeof(x),D); DumpVar(x,D);
} }
static void DumpInt(int x, DumpState* D) static void DumpInt(int x, DumpState* D)
{ {
DumpBlock(&x,sizeof(x),D); DumpVar(x,D);
}
static void DumpSize(size_t x, DumpState* D)
{
DumpBlock(&x,sizeof(x),D);
} }
static void DumpNumber(lua_Number x, DumpState* D) static void DumpNumber(lua_Number x, DumpState* D)
{ {
DumpBlock(&x,sizeof(x),D); DumpVar(x,D);
}
static void DumpVector(const void* b, int n, size_t size, DumpState* D)
{
DumpInt(n,D);
DumpMem(b,n,size,D);
} }
static void DumpString(const TString* s, DumpState* D) static void DumpString(const TString* s, DumpState* D)
{ {
if (s==NULL || getstr(s)==NULL) if (s==NULL || getstr(s)==NULL)
DumpSize(0,D); {
size_t size=0;
DumpVar(size,D);
}
else else
{ {
size_t size=s->tsv.len+1; /* include trailing '\0' */ size_t size=s->tsv.len+1; /* include trailing '\0' */
DumpSize(size,D); DumpVar(size,D);
DumpBlock(getstr(s),size,D); DumpBlock(getstr(s),size,D);
} }
} }
static void DumpCode(const Proto* f, DumpState* D) #define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
static void DumpConstants(const Proto* f, DumpState* D)
{ {
DumpInt(f->sizecode,D); int i,n=f->sizek;
DumpVector(f->code,f->sizecode,sizeof(*f->code),D); DumpInt(n,D);
for (i=0; i<n; i++)
{
const TValue* o=&f->k[i];
DumpChar(ttype(o),D);
switch (ttype(o))
{
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
DumpChar(bvalue(o),D);
break;
case LUA_TNUMBER:
DumpNumber(nvalue(o),D);
break;
case LUA_TSTRING:
DumpString(rawtsvalue(o),D);
break;
default:
lua_assert(0); /* cannot happen */
break;
}
}
n=f->sizep;
DumpInt(n,D);
for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
} }
static void DumpLocals(const Proto* f, DumpState* D) static void DumpDebug(const Proto* f, DumpState* D)
{ {
int i,n=f->sizelocvars; int i,n;
n= (D->strip) ? 0 : f->sizelineinfo;
DumpVector(f->lineinfo,n,sizeof(int),D);
n= (D->strip) ? 0 : f->sizelocvars;
DumpInt(n,D); DumpInt(n,D);
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
@@ -86,86 +121,36 @@ static void DumpLocals(const Proto* f, DumpState* D)
DumpInt(f->locvars[i].startpc,D); DumpInt(f->locvars[i].startpc,D);
DumpInt(f->locvars[i].endpc,D); DumpInt(f->locvars[i].endpc,D);
} }
} n= (D->strip) ? 0 : f->sizeupvalues;
static void DumpLines(const Proto* f, DumpState* D)
{
DumpInt(f->sizelineinfo,D);
DumpVector(f->lineinfo,f->sizelineinfo,sizeof(*f->lineinfo),D);
}
static void DumpUpvalues(const Proto* f, DumpState* D)
{
int i,n=f->sizeupvalues;
DumpInt(n,D); DumpInt(n,D);
for (i=0; i<n; i++) DumpString(f->upvalues[i],D); for (i=0; i<n; i++) DumpString(f->upvalues[i],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 TValue* o=&f->k[i];
DumpByte(ttype(o),D);
switch (ttype(o))
{
case LUA_TNUMBER:
DumpNumber(nvalue(o),D);
break;
case LUA_TSTRING:
DumpString(rawtsvalue(o),D);
break;
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
DumpByte(bvalue(o),D);
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) static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
{ {
DumpString((f->source==p) ? NULL : f->source,D); DumpString((f->source==p || D->strip) ? NULL : f->source,D);
DumpInt(f->linedefined,D); DumpInt(f->linedefined,D);
DumpInt(f->lastlinedefined,D); DumpInt(f->lastlinedefined,D);
DumpByte(f->nups,D); DumpChar(f->nups,D);
DumpByte(f->numparams,D); DumpChar(f->numparams,D);
DumpByte(f->is_vararg,D); DumpChar(f->is_vararg,D);
DumpByte(f->maxstacksize,D); DumpChar(f->maxstacksize,D);
if (D->strip) DumpInt(0,D); else DumpLines(f,D);
if (D->strip) DumpInt(0,D); else DumpLocals(f,D);
if (D->strip) DumpInt(0,D); else DumpUpvalues(f,D);
DumpConstants(f,D);
DumpCode(f,D); DumpCode(f,D);
DumpConstants(f,D);
DumpDebug(f,D);
} }
static void DumpHeader(DumpState* D) static void DumpHeader(DumpState* D)
{ {
DumpLiteral(LUA_SIGNATURE,D); char h[LUAC_HEADERSIZE];
DumpByte(VERSION,D); luaU_header(h);
DumpByte(luaU_endianness(),D); DumpBlock(h,LUAC_HEADERSIZE,D);
DumpByte(sizeof(int),D);
DumpByte(sizeof(size_t),D);
DumpByte(sizeof(Instruction),D);
DumpByte(sizeof(lua_Number),D);
DumpNumber(TEST_NUMBER,D);
} }
/* /*
** dump Lua function as precompiled chunk ** dump Lua function as precompiled chunk
*/ */
int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
int strip)
{ {
DumpState D; DumpState D;
D.L=L; D.L=L;

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lfunc.c,v 2.10 2005/04/29 13:54:05 roberto Exp roberto $ ** $Id: lfunc.c,v 2.11 2005/05/05 20:47:02 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures ** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -25,7 +25,7 @@ Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
luaC_link(L, obj2gco(c), LUA_TFUNCTION); luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->c.isC = 1; c->c.isC = 1;
c->c.env = e; c->c.env = e;
c->c.nupvalues = cast(lu_byte, nelems); c->c.nupvalues = cast_byte(nelems);
return c; return c;
} }
@@ -35,7 +35,7 @@ Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
luaC_link(L, obj2gco(c), LUA_TFUNCTION); luaC_link(L, obj2gco(c), LUA_TFUNCTION);
c->l.isC = 0; c->l.isC = 0;
c->l.env = e; c->l.env = e;
c->l.nupvalues = cast(lu_byte, nelems); c->l.nupvalues = cast_byte(nelems);
while (nelems--) c->l.upvals[nelems] = NULL; while (nelems--) c->l.upvals[nelems] = NULL;
return c; return c;
} }

17
lgc.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 2.35 2005/08/04 13:37:38 roberto Exp roberto $ ** $Id: lgc.c,v 2.36 2005/08/24 17:06:36 roberto Exp roberto $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -29,11 +29,10 @@
#define GCFINALIZECOST 100 #define GCFINALIZECOST 100
#define maskmarks \ #define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
cast(lu_byte, ~(bitmask(BLACKBIT)|WHITEBITS))
#define makewhite(g,x) \ #define makewhite(g,x) \
((x)->gch.marked = ((x)->gch.marked & maskmarks) | luaC_white(g)) ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))
#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
@@ -169,8 +168,8 @@ static int traversetable (global_State *g, Table *h) {
weakvalue = (strchr(svalue(mode), 'v') != NULL); weakvalue = (strchr(svalue(mode), 'v') != NULL);
if (weakkey || weakvalue) { /* is really weak? */ if (weakkey || weakvalue) { /* is really weak? */
h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) | h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
(weakvalue << VALUEWEAKBIT)); (weakvalue << VALUEWEAKBIT));
h->gclist = g->weak; /* must be cleared after GC, ... */ h->gclist = g->weak; /* must be cleared after GC, ... */
g->weak = obj2gco(h); /* ... so put in the appropriate list */ g->weak = obj2gco(h); /* ... so put in the appropriate list */
} }
@@ -240,8 +239,8 @@ static void traverseclosure (global_State *g, Closure *cl) {
static void checkstacksizes (lua_State *L, StkId max) { static void checkstacksizes (lua_State *L, StkId max) {
int ci_used = cast(int, L->ci - L->base_ci); /* number of `ci' in use */ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */
int s_used = cast(int, max - L->stack); /* part of stack in use */ int s_used = cast_int(max - L->stack); /* part of stack in use */
if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */
return; /* do not touch the stacks */ return; /* do not touch the stacks */
if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
@@ -544,7 +543,7 @@ static void atomic (lua_State *L) {
propagateall(g); /* remark, to propagate `preserveness' */ propagateall(g); /* remark, to propagate `preserveness' */
cleartable(g->weak); /* remove collected objects from weak tables */ cleartable(g->weak); /* remove collected objects from weak tables */
/* flip current white */ /* flip current white */
g->currentwhite = cast(lu_byte, otherwhite(g)); g->currentwhite = cast_byte(otherwhite(g));
g->sweepstrgc = 0; g->sweepstrgc = 0;
g->sweepgc = &g->rootgc; g->sweepgc = &g->rootgc;
g->gcstate = GCSsweepstring; g->gcstate = GCSsweepstring;

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: linit.c,v 1.12 2005/08/10 18:06:58 roberto Exp roberto $ ** $Id: linit.c,v 1.13 2005/08/26 17:36:32 roberto Exp roberto $
** Initialization of libraries for lua.c ** Initialization of libraries for lua.c
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -16,13 +16,13 @@
static const luaL_Reg lualibs[] = { static const luaL_Reg lualibs[] = {
{"", luaopen_base}, {"", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_TABLIBNAME, luaopen_table}, {LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io}, {LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os}, {LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string}, {LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math}, {LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug}, {LUA_DBLIBNAME, luaopen_debug},
{LUA_LOADLIBNAME, luaopen_package},
{NULL, NULL} {NULL, NULL}
}; };

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: liolib.c,v 2.66 2005/08/17 19:05:04 roberto Exp roberto $ ** $Id: liolib.c,v 2.71 2006/01/17 13:54:02 roberto Exp roberto $
** Standard I/O (and system) library ** Standard I/O (and system) library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -28,6 +28,7 @@ static const char *const fnames[] = {"input", "output"};
static int pushresult (lua_State *L, int i, const char *filename) { static int pushresult (lua_State *L, int i, const char *filename) {
int en = errno; /* calls to Lua API may change this value */
if (i) { if (i) {
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
@@ -35,10 +36,10 @@ static int pushresult (lua_State *L, int i, const char *filename) {
else { else {
lua_pushnil(L); lua_pushnil(L);
if (filename) if (filename)
lua_pushfstring(L, "%s: %s", filename, strerror(errno)); lua_pushfstring(L, "%s: %s", filename, strerror(en));
else else
lua_pushfstring(L, "%s", strerror(errno)); lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, errno); lua_pushinteger(L, en);
return 3; return 3;
} }
} }
@@ -282,7 +283,7 @@ static int read_line (lua_State *L, FILE *f) {
return (lua_strlen(L, -1) > 0); /* check whether read something */ return (lua_strlen(L, -1) > 0); /* check whether read something */
} }
l = strlen(p); l = strlen(p);
if (p[l-1] != '\n') if (l == 0 || p[l-1] != '\n')
luaL_addsize(&b, l); luaL_addsize(&b, l);
else { else {
luaL_addsize(&b, l - 1); /* do not include `eol' */ luaL_addsize(&b, l - 1); /* do not include `eol' */
@@ -424,7 +425,7 @@ static int f_seek (lua_State *L) {
static const char *const modenames[] = {"set", "cur", "end", NULL}; static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L); FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames); int op = luaL_checkoption(L, 2, "cur", modenames);
lua_Integer offset = luaL_optinteger(L, 3, 0); long offset = luaL_optlong(L, 3, 0);
op = fseek(f, offset, mode[op]); op = fseek(f, offset, mode[op]);
if (op) if (op)
return pushresult(L, 0, NULL); /* error */ return pushresult(L, 0, NULL); /* error */
@@ -440,7 +441,7 @@ static int f_setvbuf (lua_State *L) {
static const char *const modenames[] = {"no", "full", "line", NULL}; static const char *const modenames[] = {"no", "full", "line", NULL};
FILE *f = tofile(L); FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, NULL, modenames); int op = luaL_checkoption(L, 2, NULL, modenames);
lua_Integer sz = luaL_optinteger(L, 3, BUFSIZ); lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
int res = setvbuf(f, NULL, mode[op], sz); int res = setvbuf(f, NULL, mode[op], sz);
return pushresult(L, res == 0, NULL); return pushresult(L, res == 0, NULL);
} }
@@ -507,8 +508,8 @@ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
LUALIB_API int luaopen_io (lua_State *L) { LUALIB_API int luaopen_io (lua_State *L) {
createmeta(L); createmeta(L);
/* create new (private) environment */ /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
lua_newtable(L); lua_createtable(L, 2, 1);
lua_replace(L, LUA_ENVIRONINDEX); lua_replace(L, LUA_ENVIRONINDEX);
/* open library */ /* open library */
luaL_register(L, LUA_IOLIBNAME, iolib); luaL_register(L, LUA_IOLIBNAME, iolib);
@@ -518,7 +519,7 @@ LUALIB_API int luaopen_io (lua_State *L) {
createstdfile(L, stderr, 0, "stderr"); createstdfile(L, stderr, 0, "stderr");
/* create environment for 'popen' */ /* create environment for 'popen' */
lua_getfield(L, -1, "popen"); lua_getfield(L, -1, "popen");
lua_newtable(L); lua_createtable(L, 0, 1);
lua_pushcfunction(L, io_pclose); lua_pushcfunction(L, io_pclose);
lua_setfield(L, -2, "__close"); lua_setfield(L, -2, "__close");
lua_setfenv(L, -2); lua_setfenv(L, -2);

94
llex.c
View File

@@ -1,11 +1,12 @@
/* /*
** $Id: llex.c,v 2.11 2005/05/16 21:19:00 roberto Exp roberto $ ** $Id: llex.c,v 2.18 2006/01/23 20:06:19 roberto Exp roberto $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
#include <ctype.h> #include <ctype.h>
#include <locale.h>
#include <string.h> #include <string.h>
#define llex_c #define llex_c
@@ -65,7 +66,7 @@ void luaX_init (lua_State *L) {
TString *ts = luaS_new(L, luaX_tokens[i]); TString *ts = luaS_new(L, luaX_tokens[i]);
luaS_fix(ts); /* reserved words are never collected */ luaS_fix(ts); /* reserved words are never collected */
lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN); lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
ts->tsv.reserved = cast(lu_byte, i+1); /* reserved word */ ts->tsv.reserved = cast_byte(i+1); /* reserved word */
} }
} }
@@ -134,6 +135,7 @@ static void inclinenumber (LexState *ls) {
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
ls->decpoint = '.';
ls->L = L; ls->L = L;
ls->lookahead.token = TK_EOS; /* no look-ahead token */ ls->lookahead.token = TK_EOS; /* no look-ahead token */
ls->z = z; ls->z = z;
@@ -155,35 +157,50 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {
static int check_next (LexState *ls, const char *set) {
if (!strchr(set, ls->current))
return 0;
save_and_next(ls);
return 1;
}
static void buffreplace (LexState *ls, char from, char to) {
size_t n = luaZ_bufflen(ls->buff);
char *p = luaZ_buffer(ls->buff);
while (n--)
if (p[n] == from) p[n] = to;
}
static void trydecpoint (LexState *ls, SemInfo *seminfo) {
/* format error: try to update decimal point separator */
struct lconv *cv = localeconv();
char old = ls->decpoint;
ls->decpoint = (cv ? cv->decimal_point[0] : '.');
buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
/* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
luaX_lexerror(ls, "malformed number", TK_NUMBER);
}
}
/* LUA_NUMBER */ /* LUA_NUMBER */
static void read_numeral (LexState *ls, SemInfo *seminfo) { static void read_numeral (LexState *ls, SemInfo *seminfo) {
while (isdigit(ls->current)) { lua_assert(isdigit(ls->current));
do {
save_and_next(ls); save_and_next(ls);
} } while (isdigit(ls->current) || ls->current == '.');
if (ls->current == '.') { if (check_next(ls, "Ee")) /* `E'? */
check_next(ls, "+-"); /* optional exponent sign */
while (isalnum(ls->current) || ls->current == '_')
save_and_next(ls); save_and_next(ls);
if (ls->current == '.') {
save_and_next(ls);
luaX_lexerror(ls,
"ambiguous syntax (decimal point x string concatenation)",
TK_NUMBER);
}
}
while (isdigit(ls->current)) {
save_and_next(ls);
}
if (ls->current == 'e' || ls->current == 'E') {
save_and_next(ls); /* read `E' */
if (ls->current == '+' || ls->current == '-')
save_and_next(ls); /* optional exponent sign */
while (isdigit(ls->current)) {
save_and_next(ls);
}
}
save(ls, '\0'); save(ls, '\0');
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
luaX_lexerror(ls, "malformed number", TK_NUMBER); if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
trydecpoint(ls, seminfo); /* try to update decimal point separator */
} }
@@ -311,7 +328,7 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) {
} }
int luaX_lex (LexState *ls, SemInfo *seminfo) { static int llex (LexState *ls, SemInfo *seminfo) {
luaZ_resetbuffer(ls->buff); luaZ_resetbuffer(ls->buff);
for (;;) { for (;;) {
switch (ls->current) { switch (ls->current) {
@@ -375,12 +392,9 @@ int luaX_lex (LexState *ls, SemInfo *seminfo) {
} }
case '.': { case '.': {
save_and_next(ls); save_and_next(ls);
if (ls->current == '.') { if (check_next(ls, ".")) {
next(ls); if (check_next(ls, "."))
if (ls->current == '.') {
next(ls);
return TK_DOTS; /* ... */ return TK_DOTS; /* ... */
}
else return TK_CONCAT; /* .. */ else return TK_CONCAT; /* .. */
} }
else if (!isdigit(ls->current)) return '.'; else if (!isdigit(ls->current)) return '.';
@@ -427,4 +441,20 @@ int luaX_lex (LexState *ls, SemInfo *seminfo) {
} }
} }
#undef next
void luaX_next (LexState *ls) {
ls->lastline = ls->linenumber;
if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
ls->t = ls->lookahead; /* use this one */
ls->lookahead.token = TK_EOS; /* and discharge it */
}
else
ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
}
void luaX_lookahead (LexState *ls) {
lua_assert(ls->lookahead.token == TK_EOS);
ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
}

6
llex.h
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: llex.h,v 1.54 2005/04/25 19:24:10 roberto Exp roberto $ ** $Id: llex.h,v 1.56 2005/12/07 15:33:27 roberto Exp roberto $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -63,6 +63,7 @@ typedef struct LexState {
ZIO *z; /* input stream */ ZIO *z; /* input stream */
Mbuffer *buff; /* buffer for tokens */ Mbuffer *buff; /* buffer for tokens */
TString *source; /* current source name */ TString *source; /* current source name */
char decpoint; /* locale decimal point */
} LexState; } LexState;
@@ -70,7 +71,8 @@ LUAI_FUNC void luaX_init (lua_State *L);
LUAI_FUNC void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, LUAI_FUNC void luaX_setinput (lua_State *L, LexState *LS, ZIO *z,
TString *source); TString *source);
LUAI_FUNC TString *luaX_newstring (LexState *LS, const char *str, size_t l); LUAI_FUNC TString *luaX_newstring (LexState *LS, const char *str, size_t l);
LUAI_FUNC int luaX_lex (LexState *LS, SemInfo *seminfo); LUAI_FUNC void luaX_next (LexState *ls);
LUAI_FUNC void luaX_lookahead (LexState *ls);
LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token);
LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);
LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: llimits.h,v 1.66 2005/08/04 13:37:10 roberto Exp roberto $ ** $Id: llimits.h,v 1.68 2005/12/22 16:19:56 roberto Exp roberto $
** Limits, basic types, and some other `installation-dependent' definitions ** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -15,9 +15,6 @@
#include "lua.h" #include "lua.h"
#define api_check luai_apicheck
typedef LUAI_UINT32 lu_int32; typedef LUAI_UINT32 lu_int32;
typedef LUAI_UMEM lu_mem; typedef LUAI_UMEM lu_mem;
@@ -54,7 +51,19 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
typedef LUAI_UACNUMBER l_uacNumber; typedef LUAI_UACNUMBER l_uacNumber;
#define check_exp(c,e) (lua_assert(c), (e)) /* internal assertions for in-house debugging */
#ifdef lua_assert
#define check_exp(c,e) (lua_assert(c), (e))
#define api_check(l,e) lua_assert(e)
#else
#define lua_assert(c) ((void)0)
#define check_exp(c,e) (e)
#define api_check luai_apicheck
#endif
#ifndef UNUSED #ifndef UNUSED
@@ -66,6 +75,10 @@ typedef LUAI_UACNUMBER l_uacNumber;
#define cast(t, exp) ((t)(exp)) #define cast(t, exp) ((t)(exp))
#endif #endif
#define cast_byte(i) cast(lu_byte, (i))
#define cast_num(i) cast(lua_Number, (i))
#define cast_int(i) cast(int, (i))
/* /*

18
lmem.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lmem.c,v 1.68 2005/01/14 14:21:16 roberto Exp roberto $ ** $Id: lmem.c,v 1.69 2005/02/23 17:30:22 roberto Exp roberto $
** Interface to Memory Manager ** Interface to Memory Manager
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -81,22 +81,6 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
luaD_throw(L, LUA_ERRMEM); luaD_throw(L, LUA_ERRMEM);
lua_assert((nsize == 0) == (block == NULL)); lua_assert((nsize == 0) == (block == NULL));
g->totalbytes = (g->totalbytes - osize) + nsize; g->totalbytes = (g->totalbytes - osize) + nsize;
#if 0
{ /* auxiliar patch to monitor garbage collection */
static unsigned long total = 0; /* our "time" */
static lu_mem last = 0; /* last totalmem that generated an output */
static FILE *f = NULL; /* output file */
if (nsize <= osize) total += 1; /* "time" always grow */
else total += (nsize - osize);
if ((int)g->totalbytes - (int)last > 1000 ||
(int)g->totalbytes - (int)last < -1000) {
last = g->totalbytes;
if (f == NULL) f = fopen("trace", "w");
fprintf(f, "%lu %u %u %u %d\n", total, g->totalbytes, g->GCthreshold,
g->estimate, g->gcstate);
}
}
#endif
return block; return block;
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: loadlib.c,v 1.43 2005/08/31 23:17:29 roberto Exp roberto $ ** $Id: loadlib.c,v 1.50 2005/12/19 20:56:39 roberto Exp roberto $
** Dynamic library loader for Lua ** Dynamic library loader for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
** **
@@ -16,8 +16,9 @@
#define loadlib_c #define loadlib_c
#define LUA_LIB #define LUA_LIB
#include "lua.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "lobject.h"
#include "lua.h"
#include "lualib.h" #include "lualib.h"
@@ -97,16 +98,18 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
#undef setprogdir #undef setprogdir
void setprogdir (lua_State *L) { static void setprogdir (lua_State *L) {
char buff[MAX_PATH + 1]; char buff[MAX_PATH + 1];
char *lb; char *lb;
DWORD nsize = sizeof(buff)/sizeof(char); DWORD nsize = sizeof(buff)/sizeof(char);
DWORD n = GetModuleFileName(NULL, buff, nsize); DWORD n = GetModuleFileName(NULL, buff, nsize);
if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
luaL_error(L, "unable to get ModuleFileName"); luaL_error(L, "unable to get ModuleFileName");
*lb = '\0'; else {
luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); *lb = '\0';
lua_remove(L, -2); /* remove original string */ luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff);
lua_remove(L, -2); /* remove original string */
}
} }
@@ -234,11 +237,8 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
#define LIB_FAIL "absent" #define LIB_FAIL "absent"
#if defined(__ELF__) || defined(__sun) || defined(sgi) || defined(__hpux) #define DLMSG "dynamic libraries not enabled; check your Lua installation"
#define DLMSG LUA_QL("loadlib") " not enabled; check your Lua installation"
#else
#define DLMSG LUA_QL("loadlib") " not supported"
#endif
static void ll_unloadlib (void *lib) { static void ll_unloadlib (void *lib) {
(void)lib; /* to avoid warnings */ (void)lib; /* to avoid warnings */
@@ -360,20 +360,23 @@ static const char *findfile (lua_State *L, const char *name,
path = lua_tostring(L, -1); path = lua_tostring(L, -1);
if (path == NULL) if (path == NULL)
luaL_error(L, LUA_QL("package.%s") " must be a string", pname); luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
lua_pushstring(L, ""); /* error accumulator */
while ((path = pushnexttemplate(L, path)) != NULL) { while ((path = pushnexttemplate(L, path)) != NULL) {
const char *filename; const char *filename;
filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);
if (readable(filename)) /* does file exist and is readable? */ if (readable(filename)) /* does file exist and is readable? */
return filename; /* return that file name */ return filename; /* return that file name */
lua_pop(L, 2); /* remove path template and file name */ lua_pop(L, 2); /* remove path template and file name */
luaO_pushfstring(L, "\n\tno file " LUA_QS, filename);
lua_concat(L, 2);
} }
return NULL; /* not found */ return NULL; /* not found */
} }
static void loaderror (lua_State *L) { static void loaderror (lua_State *L, const char *filename) {
luaL_error(L, "error loading module " LUA_QS " (%s)", luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s",
lua_tostring(L, 1), lua_tostring(L, -1)); lua_tostring(L, 1), filename, lua_tostring(L, -1));
} }
@@ -381,9 +384,9 @@ static int loader_Lua (lua_State *L) {
const char *filename; const char *filename;
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
filename = findfile(L, name, "path"); filename = findfile(L, name, "path");
if (filename == NULL) return 0; /* library not found in this path */ if (filename == NULL) return 1; /* library not found in this path */
if (luaL_loadfile(L, filename) != 0) if (luaL_loadfile(L, filename) != 0)
loaderror(L); loaderror(L, filename);
return 1; /* library loaded successfully */ return 1; /* library loaded successfully */
} }
@@ -403,10 +406,10 @@ static int loader_C (lua_State *L) {
const char *funcname; const char *funcname;
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
const char *filename = findfile(L, name, "cpath"); const char *filename = findfile(L, name, "cpath");
if (filename == NULL) return 0; /* library not found in this path */ if (filename == NULL) return 1; /* library not found in this path */
funcname = mkfuncname(L, name); funcname = mkfuncname(L, name);
if (ll_loadfunc(L, filename, funcname) != 0) if (ll_loadfunc(L, filename, funcname) != 0)
loaderror(L); loaderror(L, filename);
return 1; /* library loaded successfully */ return 1; /* library loaded successfully */
} }
@@ -420,27 +423,32 @@ static int loader_Croot (lua_State *L) {
if (p == NULL) return 0; /* is root */ if (p == NULL) return 0; /* is root */
lua_pushlstring(L, name, p - name); lua_pushlstring(L, name, p - name);
filename = findfile(L, lua_tostring(L, -1), "cpath"); filename = findfile(L, lua_tostring(L, -1), "cpath");
if (filename == NULL) return 0; /* root not found */ if (filename == NULL) return 1; /* root not found */
funcname = mkfuncname(L, name); funcname = mkfuncname(L, name);
if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {
if (stat == ERRFUNC) return 0; /* function not found */ if (stat != ERRFUNC) loaderror(L, filename); /* real error */
else luaO_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
loaderror(L); /* real error */ name, filename);
return 1; /* function not found */
} }
return 1; return 1;
} }
static int loader_preload (lua_State *L) { static int loader_preload (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
lua_getfield(L, LUA_ENVIRONINDEX, "preload"); lua_getfield(L, LUA_ENVIRONINDEX, "preload");
if (!lua_istable(L, -1)) if (!lua_istable(L, -1))
luaL_error(L, LUA_QL("package.preload") " must be a table"); luaL_error(L, LUA_QL("package.preload") " must be a table");
lua_getfield(L, -1, luaL_checkstring(L, 1)); lua_getfield(L, -1, name);
if (lua_isnil(L, -1)) /* not found? */
luaO_pushfstring(L, "\n\tno field package.preload['%s']", name);
return 1; return 1;
} }
static const int sentinel = 0; static const int sentinel_ = 0;
#define sentinel ((void *)&sentinel_)
static int ll_require (lua_State *L) { static int ll_require (lua_State *L) {
@@ -450,7 +458,7 @@ static int ll_require (lua_State *L) {
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
lua_getfield(L, 2, name); lua_getfield(L, 2, name);
if (lua_toboolean(L, -1)) { /* is it there? */ if (lua_toboolean(L, -1)) { /* is it there? */
if (lua_touserdata(L, -1) == &sentinel) /* check loops */ if (lua_touserdata(L, -1) == sentinel) /* check loops */
luaL_error(L, "loop or previous error loading module " LUA_QS, name); luaL_error(L, "loop or previous error loading module " LUA_QS, name);
return 1; /* package is already loaded */ return 1; /* package is already loaded */
} }
@@ -458,23 +466,29 @@ static int ll_require (lua_State *L) {
lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
if (!lua_istable(L, -1)) if (!lua_istable(L, -1))
luaL_error(L, LUA_QL("package.loaders") " must be a table"); luaL_error(L, LUA_QL("package.loaders") " must be a table");
lua_pushstring(L, ""); /* error message accumulator */
for (i=1; ; i++) { for (i=1; ; i++) {
lua_rawgeti(L, -1, i); /* get a loader */ lua_rawgeti(L, -2, i); /* get a loader */
if (lua_isnil(L, -1)) if (lua_isnil(L, -1))
luaL_error(L, "module " LUA_QS " not found", name); luaL_error(L, "module " LUA_QS " not found:%s",
name, lua_tostring(L, -2));
lua_pushstring(L, name); lua_pushstring(L, name);
lua_call(L, 1, 1); /* call it */ lua_call(L, 1, 1); /* call it */
if (lua_isnil(L, -1)) lua_pop(L, 1); /* did not found module */ if (lua_isfunction(L, -1)) /* did it find module? */
else break; /* module loaded successfully */ break; /* module loaded successfully */
else if (lua_isstring(L, -1)) /* loader returned error message? */
lua_concat(L, 2); /* accumulate it */
else
lua_pop(L, 1);
} }
lua_pushlightuserdata(L, (void *)&sentinel); lua_pushlightuserdata(L, sentinel);
lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
lua_pushstring(L, name); /* pass name as argument to module */ lua_pushstring(L, name); /* pass name as argument to module */
lua_call(L, 1, 1); /* run loaded module */ lua_call(L, 1, 1); /* run loaded module */
if (!lua_isnil(L, -1)) /* non-nil return? */ if (!lua_isnil(L, -1)) /* non-nil return? */
lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
lua_getfield(L, 2, name); lua_getfield(L, 2, name);
if (lua_touserdata(L, -1) == &sentinel) { /* module did not set a value? */ if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */
lua_pushboolean(L, 1); /* use true as result */ lua_pushboolean(L, 1); /* use true as result */
lua_pushvalue(L, -1); /* extra copy to be returned */ lua_pushvalue(L, -1); /* extra copy to be returned */
lua_setfield(L, 2, name); /* _LOADED[name] = true */ lua_setfield(L, 2, name); /* _LOADED[name] = true */
@@ -536,7 +550,7 @@ static int ll_module (lua_State *L) {
if (!lua_istable(L, -1)) { /* not found? */ if (!lua_istable(L, -1)) { /* not found? */
lua_pop(L, 1); /* remove previous result */ lua_pop(L, 1); /* remove previous result */
/* try global variable (and create one if it does not exist) */ /* try global variable (and create one if it does not exist) */
if (luaL_findtable(L, LUA_GLOBALSINDEX, modname) != NULL) if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
return luaL_error(L, "name conflict for module " LUA_QS, modname); return luaL_error(L, "name conflict for module " LUA_QS, modname);
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
@@ -559,7 +573,7 @@ static int ll_module (lua_State *L) {
static int ll_seeall (lua_State *L) { static int ll_seeall (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
if (!lua_getmetatable(L, 1)) { if (!lua_getmetatable(L, 1)) {
lua_newtable(L); /* create new metatable */ lua_createtable(L, 0, 1); /* create new metatable */
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
lua_setmetatable(L, 1); lua_setmetatable(L, 1);
} }
@@ -623,12 +637,10 @@ LUALIB_API int luaopen_package (lua_State *L) {
lua_getfield(L, -1, "loadlib"); lua_getfield(L, -1, "loadlib");
lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); lua_setfield(L, LUA_GLOBALSINDEX, "loadlib");
#endif #endif
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, "_PACKAGE");
lua_pushvalue(L, -1); lua_pushvalue(L, -1);
lua_replace(L, LUA_ENVIRONINDEX); lua_replace(L, LUA_ENVIRONINDEX);
/* create `loaders' table */ /* create `loaders' table */
lua_newtable(L); lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1);
/* fill it with pre-defined loaders */ /* fill it with pre-defined loaders */
for (i=0; loaders[i] != NULL; i++) { for (i=0; loaders[i] != NULL; i++) {
lua_pushcfunction(L, loaders[i]); lua_pushcfunction(L, loaders[i]);
@@ -642,7 +654,7 @@ LUALIB_API int luaopen_package (lua_State *L) {
LUA_EXECDIR "\n" LUA_IGMARK); LUA_EXECDIR "\n" LUA_IGMARK);
lua_setfield(L, -2, "config"); lua_setfield(L, -2, "config");
/* set field `loaded' */ /* set field `loaded' */
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2);
lua_setfield(L, -2, "loaded"); lua_setfield(L, -2, "loaded");
/* set field `preload' */ /* set field `preload' */
lua_newtable(L); lua_newtable(L);

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lobject.c,v 2.17 2005/07/31 17:11:50 roberto Exp roberto $ ** $Id: lobject.c,v 2.21 2006/01/10 12:50:00 roberto Exp roberto $
** Some generic functions over Lua objects ** Some generic functions over Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -24,7 +24,7 @@
const TValue luaO_nilobject = {{NULL}, LUA_TNIL}; const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
/* /*
@@ -39,7 +39,7 @@ int luaO_int2fb (unsigned int x) {
e++; e++;
} }
if (x < 8) return x; if (x < 8) return x;
else return ((e+1) << 3) | (cast(int, x) - 8); else return ((e+1) << 3) | (cast_int(x) - 8);
} }
@@ -75,7 +75,7 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
case LUA_TNIL: case LUA_TNIL:
return 1; return 1;
case LUA_TNUMBER: case LUA_TNUMBER:
return luai_numeq(L, nvalue(t1), nvalue(t2)); return luai_numeq(nvalue(t1), nvalue(t2));
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA:
@@ -91,6 +91,8 @@ int luaO_str2d (const char *s, lua_Number *result) {
char *endptr; char *endptr;
*result = lua_str2number(s, &endptr); *result = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* conversion failed */ if (endptr == s) return 0; /* conversion failed */
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
*result = cast_num(strtoul(s, &endptr, 16));
if (*endptr == '\0') return 1; /* most common case */ if (*endptr == '\0') return 1; /* most common case */
while (isspace(cast(unsigned char, *endptr))) endptr++; while (isspace(cast(unsigned char, *endptr))) endptr++;
if (*endptr != '\0') return 0; /* invalid trailing characters? */ if (*endptr != '\0') return 0; /* invalid trailing characters? */
@@ -129,12 +131,12 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
break; break;
} }
case 'd': { case 'd': {
setnvalue(L->top, cast(lua_Number, va_arg(argp, int))); setnvalue(L->top, cast_num(va_arg(argp, int)));
incr_top(L); incr_top(L);
break; break;
} }
case 'f': { case 'f': {
setnvalue(L->top, cast(lua_Number, va_arg(argp, l_uacNumber))); setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
incr_top(L); incr_top(L);
break; break;
} }
@@ -161,7 +163,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
fmt = e+2; fmt = e+2;
} }
pushstr(L, fmt); pushstr(L, fmt);
luaV_concat(L, n+1, cast(int, L->top - L->base) - 1); luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);
L->top -= n; L->top -= n;
return svalue(L->top - 1); return svalue(L->top - 1);
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lobject.h,v 2.16 2005/06/13 14:15:54 roberto Exp roberto $ ** $Id: lobject.h,v 2.19 2006/01/10 12:51:53 roberto Exp roberto $
** Type definitions for Lua objects ** Type definitions for Lua objects
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -119,9 +119,6 @@ typedef struct lua_TValue {
#define setnvalue(obj,x) \ #define setnvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
#define chgnvalue(obj,x) \
check_exp(ttype(obj)==LUA_TNUMBER, (obj)->value.n=(x))
#define setpvalue(obj,x) \ #define setpvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
@@ -323,9 +320,12 @@ typedef union Closure {
** Tables ** Tables
*/ */
typedef struct TKey { typedef union TKey {
TValuefields; struct {
struct Node *next; /* for chaining */ TValuefields;
struct Node *next; /* for chaining */
} nk;
TValue tvk;
} TKey; } TKey;
@@ -353,15 +353,16 @@ typedef struct Table {
** `module' operation for hashing (size is always a power of 2) ** `module' operation for hashing (size is always a power of 2)
*/ */
#define lmod(s,size) \ #define lmod(s,size) \
check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))) (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
#define twoto(x) (1<<(x)) #define twoto(x) (1<<(x))
#define sizenode(t) (twoto((t)->lsizenode)) #define sizenode(t) (twoto((t)->lsizenode))
#define luaO_nilobject (&luaO_nilobject_)
LUAI_DATA const TValue luaO_nilobject; LUAI_DATA const TValue luaO_nilobject_;
#define ceillog2(x) (luaO_log2((x)-1) + 1) #define ceillog2(x) (luaO_log2((x)-1) + 1)

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lopcodes.c,v 1.34 2005/05/20 15:53:42 roberto Exp $ ** $Id: lopcodes.c,v 1.36 2005/10/13 12:22:05 roberto Exp roberto $
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -7,9 +7,7 @@
#define lopcodes_c #define lopcodes_c
#define LUA_CORE #define LUA_CORE
#include "lua.h"
#include "lobject.h"
#include "lopcodes.h" #include "lopcodes.h"
@@ -88,7 +86,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
,opmode(1, 0, OpArgR, OpArgU, iABC) /* OP_TEST */ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lopcodes.h,v 1.121 2005/06/06 13:30:25 roberto Exp $ ** $Id: lopcodes.h,v 1.123 2005/10/23 17:37:55 roberto Exp roberto $
** Opcodes for Lua virtual machine ** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -193,12 +193,12 @@ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then pc+=sBx */ OP_FORLOOP,/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
OP_TFORLOOP,/* A C R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); OP_TFORLOOP,/* A C R(A+3), ... ,R(A+3+C) := R(A)(R(A+1), R(A+2));
if R(A+2) ~= nil then pc++ */ if R(A+3) ~= nil then { pc++; R(A+2)=R(A+3); } */
OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
@@ -208,7 +208,7 @@ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
} OpCode; } OpCode;
#define NUM_OPCODES (cast(int, OP_VARARG+1)) #define NUM_OPCODES (cast(int, OP_VARARG) + 1)

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: loslib.c,v 1.12 2005/08/26 17:36:32 roberto Exp roberto $ ** $Id: loslib.c,v 1.16 2005/12/22 16:19:56 roberto Exp roberto $
** Standard Operating System library ** Standard Operating System library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -21,6 +21,7 @@
static int os_pushresult (lua_State *L, int i, const char *filename) { static int os_pushresult (lua_State *L, int i, const char *filename) {
int en = errno; /* calls to Lua API may change this value */
if (i) { if (i) {
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
@@ -28,35 +29,35 @@ static int os_pushresult (lua_State *L, int i, const char *filename) {
else { else {
lua_pushnil(L); lua_pushnil(L);
if (filename) if (filename)
lua_pushfstring(L, "%s: %s", filename, strerror(errno)); lua_pushfstring(L, "%s: %s", filename, strerror(en));
else else
lua_pushfstring(L, "%s", strerror(errno)); lua_pushfstring(L, "%s", strerror(en));
lua_pushinteger(L, errno); lua_pushinteger(L, en);
return 3; return 3;
} }
} }
static int io_execute (lua_State *L) { static int os_execute (lua_State *L) {
lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
return 1; return 1;
} }
static int io_remove (lua_State *L) { static int os_remove (lua_State *L) {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
return os_pushresult(L, remove(filename) == 0, filename); return os_pushresult(L, remove(filename) == 0, filename);
} }
static int io_rename (lua_State *L) { static int os_rename (lua_State *L) {
const char *fromname = luaL_checkstring(L, 1); const char *fromname = luaL_checkstring(L, 1);
const char *toname = luaL_checkstring(L, 2); const char *toname = luaL_checkstring(L, 2);
return os_pushresult(L, rename(fromname, toname) == 0, fromname); return os_pushresult(L, rename(fromname, toname) == 0, fromname);
} }
static int io_tmpname (lua_State *L) { static int os_tmpname (lua_State *L) {
char buff[LUA_TMPNAMBUFSIZE]; char buff[LUA_TMPNAMBUFSIZE];
int err; int err;
lua_tmpnam(buff, err); lua_tmpnam(buff, err);
@@ -67,13 +68,13 @@ static int io_tmpname (lua_State *L) {
} }
static int io_getenv (lua_State *L) { static int os_getenv (lua_State *L) {
lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
return 1; return 1;
} }
static int io_clock (lua_State *L) { static int os_clock (lua_State *L) {
lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
return 1; return 1;
} }
@@ -123,10 +124,10 @@ static int getfield (lua_State *L, const char *key, int d) {
} }
static int io_date (lua_State *L) { static int os_date (lua_State *L) {
const char *s = luaL_optstring(L, 1, "%c"); const char *s = luaL_optstring(L, 1, "%c");
lua_Number n = luaL_optnumber(L, 2, -1); time_t t = lua_isnoneornil(L, 2) ? time(NULL) :
time_t t = (n == -1) ? time(NULL) : (time_t)n; (time_t)luaL_checknumber(L, 2);
struct tm *stm; struct tm *stm;
if (*s == '!') { /* UTC? */ if (*s == '!') { /* UTC? */
stm = gmtime(&t); stm = gmtime(&t);
@@ -159,7 +160,7 @@ static int io_date (lua_State *L) {
} }
static int io_time (lua_State *L) { static int os_time (lua_State *L) {
time_t t; time_t t;
if (lua_isnoneornil(L, 1)) /* called without args? */ if (lua_isnoneornil(L, 1)) /* called without args? */
t = time(NULL); /* get current time */ t = time(NULL); /* get current time */
@@ -179,12 +180,12 @@ static int io_time (lua_State *L) {
if (t == (time_t)(-1)) if (t == (time_t)(-1))
lua_pushnil(L); lua_pushnil(L);
else else
lua_pushnumber(L, t); lua_pushnumber(L, (lua_Number)t);
return 1; return 1;
} }
static int io_difftime (lua_State *L) { static int os_difftime (lua_State *L) {
lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
(time_t)(luaL_optnumber(L, 2, 0)))); (time_t)(luaL_optnumber(L, 2, 0))));
return 1; return 1;
@@ -193,7 +194,7 @@ static int io_difftime (lua_State *L) {
/* }====================================================== */ /* }====================================================== */
static int io_setloc (lua_State *L) { static int os_setlocale (lua_State *L) {
static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
LC_NUMERIC, LC_TIME}; LC_NUMERIC, LC_TIME};
static const char *const catnames[] = {"all", "collate", "ctype", "monetary", static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
@@ -206,23 +207,23 @@ static int io_setloc (lua_State *L) {
} }
static int io_exit (lua_State *L) { static int os_exit (lua_State *L) {
exit(luaL_optint(L, 1, EXIT_SUCCESS)); exit(luaL_optint(L, 1, EXIT_SUCCESS));
return 0; /* to avoid warnings */ return 0; /* to avoid warnings */
} }
static const luaL_Reg syslib[] = { static const luaL_Reg syslib[] = {
{"clock", io_clock}, {"clock", os_clock},
{"date", io_date}, {"date", os_date},
{"difftime", io_difftime}, {"difftime", os_difftime},
{"execute", io_execute}, {"execute", os_execute},
{"exit", io_exit}, {"exit", os_exit},
{"getenv", io_getenv}, {"getenv", os_getenv},
{"remove", io_remove}, {"remove", os_remove},
{"rename", io_rename}, {"rename", os_rename},
{"setlocale", io_setloc}, {"setlocale", os_setlocale},
{"time", io_time}, {"time", os_time},
{"tmpname", io_tmpname}, {"tmpname", os_tmpname},
{NULL, NULL} {NULL, NULL}
}; };

117
lparser.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lparser.c,v 2.34 2005/08/24 17:41:10 roberto Exp $ ** $Id: lparser.c,v 2.39 2005/12/07 15:43:05 roberto Exp roberto $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -54,24 +54,6 @@ static void chunk (LexState *ls);
static void expr (LexState *ls, expdesc *v); static void expr (LexState *ls, expdesc *v);
static void next (LexState *ls) {
ls->lastline = ls->linenumber;
if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
ls->t = ls->lookahead; /* use this one */
ls->lookahead.token = TK_EOS; /* and discharge it */
}
else
ls->t.token = luaX_lex(ls, &ls->t.seminfo); /* read next token */
}
static void lookahead (LexState *ls) {
lua_assert(ls->lookahead.token == TK_EOS);
ls->lookahead.token = luaX_lex(ls, &ls->lookahead.seminfo);
}
static void anchor_token (LexState *ls) { static void anchor_token (LexState *ls) {
if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
TString *ts = ls->t.seminfo.ts; TString *ts = ls->t.seminfo.ts;
@@ -97,7 +79,7 @@ static void errorlimit (FuncState *fs, int limit, const char *what) {
static int testnext (LexState *ls, int c) { static int testnext (LexState *ls, int c) {
if (ls->t.token == c) { if (ls->t.token == c) {
next(ls); luaX_next(ls);
return 1; return 1;
} }
else return 0; else return 0;
@@ -111,7 +93,7 @@ static void check (LexState *ls, int c) {
static void checknext (LexState *ls, int c) { static void checknext (LexState *ls, int c) {
check(ls, c); check(ls, c);
next(ls); luaX_next(ls);
} }
@@ -136,7 +118,7 @@ static TString *str_checkname (LexState *ls) {
TString *ts; TString *ts;
check(ls, TK_NAME); check(ls, TK_NAME);
ts = ls->t.seminfo.ts; ts = ls->t.seminfo.ts;
next(ls); luaX_next(ls);
return ts; return ts;
} }
@@ -144,7 +126,7 @@ static TString *str_checkname (LexState *ls) {
static void init_exp (expdesc *e, expkind k, int i) { static void init_exp (expdesc *e, expkind k, int i) {
e->f = e->t = NO_JUMP; e->f = e->t = NO_JUMP;
e->k = k; e->k = k;
e->info = i; e->u.s.info = i;
} }
@@ -184,7 +166,7 @@ static void new_localvar (LexState *ls, TString *name, int n) {
static void adjustlocalvars (LexState *ls, int nvars) { static void adjustlocalvars (LexState *ls, int nvars) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
fs->nactvar += nvars; fs->nactvar = cast_byte(fs->nactvar + nvars);
for (; nvars; nvars--) { for (; nvars; nvars--) {
getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
} }
@@ -203,7 +185,7 @@ static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
Proto *f = fs->f; Proto *f = fs->f;
int oldsize = f->sizeupvalues; int oldsize = f->sizeupvalues;
for (i=0; i<f->nups; i++) { for (i=0; i<f->nups; i++) {
if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) { if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {
lua_assert(f->upvalues[i] == name); lua_assert(f->upvalues[i] == name);
return i; return i;
} }
@@ -216,8 +198,8 @@ static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
f->upvalues[f->nups] = name; f->upvalues[f->nups] = name;
luaC_objbarrier(fs->L, f, name); luaC_objbarrier(fs->L, f, name);
lua_assert(v->k == VLOCAL || v->k == VUPVAL); lua_assert(v->k == VLOCAL || v->k == VUPVAL);
fs->upvalues[f->nups].k = cast(lu_byte, v->k); fs->upvalues[f->nups].k = cast_byte(v->k);
fs->upvalues[f->nups].info = cast(lu_byte, v->info); fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
return f->nups++; return f->nups++;
} }
@@ -255,7 +237,7 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
else { /* not found at current level; try upper one */ else { /* not found at current level; try upper one */
if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)
return VGLOBAL; return VGLOBAL;
var->info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */
var->k = VUPVAL; /* upvalue in this level */ var->k = VUPVAL; /* upvalue in this level */
return VUPVAL; return VUPVAL;
} }
@@ -267,7 +249,7 @@ static void singlevar (LexState *ls, expdesc *var) {
TString *varname = str_checkname(ls); TString *varname = str_checkname(ls);
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
if (singlevaraux(fs, varname, var, 1) == VGLOBAL) if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
var->info = luaK_stringK(fs, varname); /* info points to global name */ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
} }
@@ -351,7 +333,7 @@ static void open_func (LexState *ls, FuncState *fs) {
fs->L = L; fs->L = L;
ls->fs = fs; ls->fs = fs;
fs->pc = 0; fs->pc = 0;
fs->lasttarget = 0; fs->lasttarget = -1;
fs->jpc = NO_JUMP; fs->jpc = NO_JUMP;
fs->freereg = 0; fs->freereg = 0;
fs->nk = 0; fs->nk = 0;
@@ -404,7 +386,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
luaX_setinput(L, &lexstate, z, luaS_new(L, name)); luaX_setinput(L, &lexstate, z, luaS_new(L, name));
open_func(&lexstate, &funcstate); open_func(&lexstate, &funcstate);
funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
next(&lexstate); /* read first token */ luaX_next(&lexstate); /* read first token */
chunk(&lexstate); chunk(&lexstate);
check(&lexstate, TK_EOS); check(&lexstate, TK_EOS);
close_func(&lexstate); close_func(&lexstate);
@@ -426,7 +408,7 @@ static void field (LexState *ls, expdesc *v) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
expdesc key; expdesc key;
luaK_exp2anyreg(fs, v); luaK_exp2anyreg(fs, v);
next(ls); /* skip the dot or colon */ luaX_next(ls); /* skip the dot or colon */
checkname(ls, &key); checkname(ls, &key);
luaK_indexed(fs, v, &key); luaK_indexed(fs, v, &key);
} }
@@ -434,7 +416,7 @@ static void field (LexState *ls, expdesc *v) {
static void yindex (LexState *ls, expdesc *v) { static void yindex (LexState *ls, expdesc *v) {
/* index -> '[' expr ']' */ /* index -> '[' expr ']' */
next(ls); /* skip the '[' */ luaX_next(ls); /* skip the '[' */
expr(ls, v); expr(ls, v);
luaK_exp2val(ls->fs, v); luaK_exp2val(ls->fs, v);
checknext(ls, ']'); checknext(ls, ']');
@@ -472,8 +454,8 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
checknext(ls, '='); checknext(ls, '=');
luaK_exp2RK(fs, &key); luaK_exp2RK(fs, &key);
expr(ls, &val); expr(ls, &val);
luaK_codeABC(fs, OP_SETTABLE, cc->t->info, luaK_exp2RK(fs, &key), luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, luaK_exp2RK(fs, &key),
luaK_exp2RK(fs, &val)); luaK_exp2RK(fs, &val));
fs->freereg = reg; /* free registers */ fs->freereg = reg; /* free registers */
} }
@@ -483,7 +465,7 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) {
luaK_exp2nextreg(fs, &cc->v); luaK_exp2nextreg(fs, &cc->v);
cc->v.k = VVOID; cc->v.k = VVOID;
if (cc->tostore == LFIELDS_PER_FLUSH) { if (cc->tostore == LFIELDS_PER_FLUSH) {
luaK_setlist(fs, cc->t->info, cc->na, cc->tostore); /* flush */ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */
cc->tostore = 0; /* no more items pending */ cc->tostore = 0; /* no more items pending */
} }
} }
@@ -493,13 +475,13 @@ static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
if (cc->tostore == 0) return; if (cc->tostore == 0) return;
if (hasmultret(cc->v.k)) { if (hasmultret(cc->v.k)) {
luaK_setmultret(fs, &cc->v); luaK_setmultret(fs, &cc->v);
luaK_setlist(fs, cc->t->info, cc->na, LUA_MULTRET); luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);
cc->na--; /* do not count last expression (unknown number of elements) */ cc->na--; /* do not count last expression (unknown number of elements) */
} }
else { else {
if (cc->v.k != VVOID) if (cc->v.k != VVOID)
luaK_exp2nextreg(fs, &cc->v); luaK_exp2nextreg(fs, &cc->v);
luaK_setlist(fs, cc->t->info, cc->na, cc->tostore); luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
} }
} }
@@ -530,7 +512,7 @@ static void constructor (LexState *ls, expdesc *t) {
closelistfield(fs, &cc); closelistfield(fs, &cc);
switch(ls->t.token) { switch(ls->t.token) {
case TK_NAME: { /* may be listfields or recfields */ case TK_NAME: { /* may be listfields or recfields */
lookahead(ls); luaX_lookahead(ls);
if (ls->lookahead.token != '=') /* expression? */ if (ls->lookahead.token != '=') /* expression? */
listfield(ls, &cc); listfield(ls, &cc);
else else
@@ -571,7 +553,7 @@ static void parlist (LexState *ls) {
break; break;
} }
case TK_DOTS: { /* param -> `...' */ case TK_DOTS: { /* param -> `...' */
next(ls); luaX_next(ls);
#if defined(LUA_COMPAT_VARARG) #if defined(LUA_COMPAT_VARARG)
/* use `arg' as default name */ /* use `arg' as default name */
new_localvarliteral(ls, "arg", nparams++); new_localvarliteral(ls, "arg", nparams++);
@@ -585,7 +567,7 @@ static void parlist (LexState *ls) {
} while (!f->is_vararg && testnext(ls, ',')); } while (!f->is_vararg && testnext(ls, ','));
} }
adjustlocalvars(ls, nparams); adjustlocalvars(ls, nparams);
f->numparams = fs->nactvar - (f->is_vararg & VARARG_HASARG); f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
} }
@@ -632,7 +614,7 @@ static void funcargs (LexState *ls, expdesc *f) {
case '(': { /* funcargs -> `(' [ explist1 ] `)' */ case '(': { /* funcargs -> `(' [ explist1 ] `)' */
if (line != ls->lastline) if (line != ls->lastline)
luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
next(ls); luaX_next(ls);
if (ls->t.token == ')') /* arg list is empty? */ if (ls->t.token == ')') /* arg list is empty? */
args.k = VVOID; args.k = VVOID;
else { else {
@@ -648,7 +630,7 @@ static void funcargs (LexState *ls, expdesc *f) {
} }
case TK_STRING: { /* funcargs -> STRING */ case TK_STRING: { /* funcargs -> STRING */
codestring(ls, &args, ls->t.seminfo.ts); codestring(ls, &args, ls->t.seminfo.ts);
next(ls); /* must use `seminfo' before `next' */ luaX_next(ls); /* must use `seminfo' before `next' */
break; break;
} }
default: { default: {
@@ -657,7 +639,7 @@ static void funcargs (LexState *ls, expdesc *f) {
} }
} }
lua_assert(f->k == VNONRELOC); lua_assert(f->k == VNONRELOC);
base = f->info; /* base register for call */ base = f->u.s.info; /* base register for call */
if (hasmultret(args.k)) if (hasmultret(args.k))
nparams = LUA_MULTRET; /* open call */ nparams = LUA_MULTRET; /* open call */
else { else {
@@ -686,7 +668,7 @@ static void prefixexp (LexState *ls, expdesc *v) {
switch (ls->t.token) { switch (ls->t.token) {
case '(': { case '(': {
int line = ls->linenumber; int line = ls->linenumber;
next(ls); luaX_next(ls);
expr(ls, v); expr(ls, v);
check_match(ls, ')', '(', line); check_match(ls, ')', '(', line);
luaK_dischargevars(ls->fs, v); luaK_dischargevars(ls->fs, v);
@@ -724,7 +706,7 @@ static void primaryexp (LexState *ls, expdesc *v) {
} }
case ':': { /* `:' NAME funcargs */ case ':': { /* `:' NAME funcargs */
expdesc key; expdesc key;
next(ls); luaX_next(ls);
checkname(ls, &key); checkname(ls, &key);
luaK_self(fs, v, &key); luaK_self(fs, v, &key);
funcargs(ls, v); funcargs(ls, v);
@@ -746,7 +728,8 @@ static void simpleexp (LexState *ls, expdesc *v) {
constructor | FUNCTION body | primaryexp */ constructor | FUNCTION body | primaryexp */
switch (ls->t.token) { switch (ls->t.token) {
case TK_NUMBER: { case TK_NUMBER: {
init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r)); init_exp(v, VKNUM, 0);
v->u.nval = ls->t.seminfo.r;
break; break;
} }
case TK_STRING: { case TK_STRING: {
@@ -778,7 +761,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
return; return;
} }
case TK_FUNCTION: { case TK_FUNCTION: {
next(ls); luaX_next(ls);
body(ls, v, 0, ls->linenumber); body(ls, v, 0, ls->linenumber);
return; return;
} }
@@ -787,7 +770,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
return; return;
} }
} }
next(ls); luaX_next(ls);
} }
@@ -805,7 +788,7 @@ static BinOpr getbinopr (int op) {
switch (op) { switch (op) {
case '+': return OPR_ADD; case '+': return OPR_ADD;
case '-': return OPR_SUB; case '-': return OPR_SUB;
case '*': return OPR_MULT; case '*': return OPR_MUL;
case '/': return OPR_DIV; case '/': return OPR_DIV;
case '%': return OPR_MOD; case '%': return OPR_MOD;
case '^': return OPR_POW; case '^': return OPR_POW;
@@ -847,7 +830,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
enterlevel(ls); enterlevel(ls);
uop = getunopr(ls->t.token); uop = getunopr(ls->t.token);
if (uop != OPR_NOUNOPR) { if (uop != OPR_NOUNOPR) {
next(ls); luaX_next(ls);
subexpr(ls, v, UNARY_PRIORITY); subexpr(ls, v, UNARY_PRIORITY);
luaK_prefix(ls->fs, uop, v); luaK_prefix(ls->fs, uop, v);
} }
@@ -857,7 +840,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
while (op != OPR_NOBINOPR && priority[op].left > limit) { while (op != OPR_NOBINOPR && priority[op].left > limit) {
expdesc v2; expdesc v2;
BinOpr nextop; BinOpr nextop;
next(ls); luaX_next(ls);
luaK_infix(ls->fs, op, v); luaK_infix(ls->fs, op, v);
/* read sub-expression with higher priority */ /* read sub-expression with higher priority */
nextop = subexpr(ls, &v2, priority[op].right); nextop = subexpr(ls, &v2, priority[op].right);
@@ -927,18 +910,18 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
int conflict = 0; int conflict = 0;
for (; lh; lh = lh->prev) { for (; lh; lh = lh->prev) {
if (lh->v.k == VINDEXED) { if (lh->v.k == VINDEXED) {
if (lh->v.info == v->info) { /* conflict? */ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */
conflict = 1; conflict = 1;
lh->v.info = extra; /* previous assignment will use safe copy */ lh->v.u.s.info = extra; /* previous assignment will use safe copy */
} }
if (lh->v.aux == v->info) { /* conflict? */ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */
conflict = 1; conflict = 1;
lh->v.aux = extra; /* previous assignment will use safe copy */ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */
} }
} }
} }
if (conflict) { if (conflict) {
luaK_codeABC(fs, OP_MOVE, fs->freereg, v->info, 0); /* make copy */ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */
luaK_reserveregs(fs, 1); luaK_reserveregs(fs, 1);
} }
} }
@@ -1008,7 +991,7 @@ static void whilestat (LexState *ls, int line) {
int whileinit; int whileinit;
int condexit; int condexit;
BlockCnt bl; BlockCnt bl;
next(ls); /* skip WHILE */ luaX_next(ls); /* skip WHILE */
whileinit = luaK_getlabel(fs); whileinit = luaK_getlabel(fs);
condexit = cond(ls); condexit = cond(ls);
enterblock(fs, &bl, 1); enterblock(fs, &bl, 1);
@@ -1029,7 +1012,7 @@ static void repeatstat (LexState *ls, int line) {
BlockCnt bl1, bl2; BlockCnt bl1, bl2;
enterblock(fs, &bl1, 1); /* loop block */ enterblock(fs, &bl1, 1); /* loop block */
enterblock(fs, &bl2, 0); /* scope block */ enterblock(fs, &bl2, 0); /* scope block */
next(ls); /* skip REPEAT */ luaX_next(ls); /* skip REPEAT */
chunk(ls); chunk(ls);
check_match(ls, TK_UNTIL, TK_REPEAT, line); check_match(ls, TK_UNTIL, TK_REPEAT, line);
condexit = cond(ls); /* read condition (inside scope block) */ condexit = cond(ls); /* read condition (inside scope block) */
@@ -1129,7 +1112,7 @@ static void forstat (LexState *ls, int line) {
TString *varname; TString *varname;
BlockCnt bl; BlockCnt bl;
enterblock(fs, &bl, 1); /* scope for loop and control variables */ enterblock(fs, &bl, 1); /* scope for loop and control variables */
next(ls); /* skip `for' */ luaX_next(ls); /* skip `for' */
varname = str_checkname(ls); /* first variable name */ varname = str_checkname(ls); /* first variable name */
switch (ls->t.token) { switch (ls->t.token) {
case '=': fornum(ls, varname, line); break; case '=': fornum(ls, varname, line); break;
@@ -1144,7 +1127,7 @@ static void forstat (LexState *ls, int line) {
static int test_then_block (LexState *ls) { static int test_then_block (LexState *ls) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */ /* test_then_block -> [IF | ELSEIF] cond THEN block */
int condexit; int condexit;
next(ls); /* skip IF or ELSEIF */ luaX_next(ls); /* skip IF or ELSEIF */
condexit = cond(ls); condexit = cond(ls);
checknext(ls, TK_THEN); checknext(ls, TK_THEN);
block(ls); /* `then' part */ block(ls); /* `then' part */
@@ -1166,7 +1149,7 @@ static void ifstat (LexState *ls, int line) {
if (ls->t.token == TK_ELSE) { if (ls->t.token == TK_ELSE) {
luaK_concat(fs, &escapelist, luaK_jump(fs)); luaK_concat(fs, &escapelist, luaK_jump(fs));
luaK_patchtohere(fs, flist); luaK_patchtohere(fs, flist);
next(ls); /* skip ELSE (after patch, for correct line info) */ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */
block(ls); /* `else' part */ block(ls); /* `else' part */
} }
else else
@@ -1227,7 +1210,7 @@ static void funcstat (LexState *ls, int line) {
/* funcstat -> FUNCTION funcname body */ /* funcstat -> FUNCTION funcname body */
int needself; int needself;
expdesc v, b; expdesc v, b;
next(ls); /* skip FUNCTION */ luaX_next(ls); /* skip FUNCTION */
needself = funcname(ls, &v); needself = funcname(ls, &v);
body(ls, &b, needself, line); body(ls, &b, needself, line);
luaK_storevar(ls->fs, &v, &b); luaK_storevar(ls->fs, &v, &b);
@@ -1254,7 +1237,7 @@ static void retstat (LexState *ls) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
expdesc e; expdesc e;
int first, nret; /* registers with returned values */ int first, nret; /* registers with returned values */
next(ls); /* skip RETURN */ luaX_next(ls); /* skip RETURN */
if (block_follow(ls->t.token) || ls->t.token == ';') if (block_follow(ls->t.token) || ls->t.token == ';')
first = nret = 0; /* return no values */ first = nret = 0; /* return no values */
else { else {
@@ -1294,7 +1277,7 @@ static int statement (LexState *ls) {
return 0; return 0;
} }
case TK_DO: { /* stat -> DO block END */ case TK_DO: { /* stat -> DO block END */
next(ls); /* skip DO */ luaX_next(ls); /* skip DO */
block(ls); block(ls);
check_match(ls, TK_END, TK_DO, line); check_match(ls, TK_END, TK_DO, line);
return 0; return 0;
@@ -1312,7 +1295,7 @@ static int statement (LexState *ls) {
return 0; return 0;
} }
case TK_LOCAL: { /* stat -> localstat */ case TK_LOCAL: { /* stat -> localstat */
next(ls); /* skip LOCAL */ luaX_next(ls); /* skip LOCAL */
if (testnext(ls, TK_FUNCTION)) /* local function? */ if (testnext(ls, TK_FUNCTION)) /* local function? */
localfunc(ls); localfunc(ls);
else else
@@ -1324,7 +1307,7 @@ static int statement (LexState *ls) {
return 1; /* must be last statement */ return 1; /* must be last statement */
} }
case TK_BREAK: { /* stat -> breakstat */ case TK_BREAK: { /* stat -> breakstat */
next(ls); /* skip BREAK */ luaX_next(ls); /* skip BREAK */
breakstat(ls); breakstat(ls);
return 1; /* must be last statement */ return 1; /* must be last statement */
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lparser.h,v 1.54 2005/03/09 16:28:07 roberto Exp roberto $ ** $Id: lparser.h,v 1.55 2005/04/25 19:24:10 roberto Exp roberto $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -23,6 +23,7 @@ typedef enum {
VTRUE, VTRUE,
VFALSE, VFALSE,
VK, /* info = index of constant in `k' */ VK, /* info = index of constant in `k' */
VKNUM, /* nval = numerical value */
VLOCAL, /* info = local register */ VLOCAL, /* info = local register */
VUPVAL, /* info = index of upvalue in `upvalues' */ VUPVAL, /* info = index of upvalue in `upvalues' */
VGLOBAL, /* info = index of table; aux = index of global name in `k' */ VGLOBAL, /* info = index of table; aux = index of global name in `k' */
@@ -36,7 +37,10 @@ typedef enum {
typedef struct expdesc { typedef struct expdesc {
expkind k; expkind k;
int info, aux; union {
struct { int info, aux; } s;
lua_Number nval;
} u;
int t; /* patch list of `exit when true' */ int t; /* patch list of `exit when true' */
int f; /* patch list of `exit when false' */ int f; /* patch list of `exit when false' */
} expdesc; } expdesc;

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lstate.c,v 2.32 2005/06/03 20:15:58 roberto Exp roberto $ ** $Id: lstate.c,v 2.34 2005/09/20 17:55:53 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -71,8 +71,8 @@ static void f_luaopen (lua_State *L, void *ud) {
global_State *g = G(L); global_State *g = G(L);
UNUSED(ud); UNUSED(ud);
stack_init(L, L); /* init stack */ stack_init(L, L); /* init stack */
sethvalue(L, gt(L), luaH_new(L, 0, 20)); /* table of globals */ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */
sethvalue(L, registry(L), luaH_new(L, 6, 20)); /* registry */ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
luaT_init(L); luaT_init(L);
luaX_init(L); luaX_init(L);
@@ -134,6 +134,7 @@ lua_State *luaE_newthread (lua_State *L) {
void luaE_freethread (lua_State *L, lua_State *L1) { void luaE_freethread (lua_State *L, lua_State *L1) {
luaF_close(L1, L1->stack); /* close all upvalues for this thread */ luaF_close(L1, L1->stack); /* close all upvalues for this thread */
lua_assert(L1->openupval == NULL); lua_assert(L1->openupval == NULL);
luai_userstatefree(L1);
freestack(L, L1); freestack(L, L1);
luaM_freemem(L, fromstate(L1), state_size(lua_State)); luaM_freemem(L, fromstate(L1), state_size(lua_State));
} }
@@ -196,8 +197,9 @@ static void callallgcTM (lua_State *L, void *ud) {
LUA_API void lua_close (lua_State *L) { LUA_API void lua_close (lua_State *L) {
lua_lock(L);
L = G(L)->mainthread; /* only the main thread can be closed */ L = G(L)->mainthread; /* only the main thread can be closed */
luai_userstateclose(L);
lua_lock(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */ luaF_close(L, L->stack); /* close all upvalues for this thread */
luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
L->errfunc = 0; /* no error function during GC metamethods */ L->errfunc = 0; /* no error function during GC metamethods */

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lstate.h,v 2.22 2005/06/03 20:15:58 roberto Exp roberto $ ** $Id: lstate.h,v 2.23 2005/07/09 13:22:34 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -49,8 +49,8 @@ typedef struct CallInfo {
StkId base; /* base for this function */ StkId base; /* base for this function */
StkId func; /* function index in the stack */ StkId func; /* function index in the stack */
StkId top; /* top for this function */ StkId top; /* top for this function */
int nresults; /* expected number of results from this function */
const Instruction *savedpc; const Instruction *savedpc;
int nresults; /* expected number of results from this function */
int tailcalls; /* number of tail calls lost under this entry */ int tailcalls; /* number of tail calls lost under this entry */
} CallInfo; } CallInfo;
@@ -71,9 +71,9 @@ typedef struct global_State {
void *ud; /* auxiliary data to `frealloc' */ void *ud; /* auxiliary data to `frealloc' */
lu_byte currentwhite; lu_byte currentwhite;
lu_byte gcstate; /* state of garbage collector */ lu_byte gcstate; /* state of garbage collector */
int sweepstrgc; /* position of sweep in `strt' */
GCObject *rootgc; /* list of all collectable objects */ GCObject *rootgc; /* list of all collectable objects */
GCObject **sweepgc; /* position of sweep in `rootgc' */ GCObject **sweepgc; /* position of sweep in `rootgc' */
int sweepstrgc; /* position of sweep in `strt' */
GCObject *gray; /* list of gray objects */ GCObject *gray; /* list of gray objects */
GCObject *grayagain; /* list of objects to be traversed atomically */ GCObject *grayagain; /* list of objects to be traversed atomically */
GCObject *weak; /* list of weak tables (to be cleared) */ GCObject *weak; /* list of weak tables (to be cleared) */
@@ -99,6 +99,7 @@ typedef struct global_State {
*/ */
struct lua_State { struct lua_State {
CommonHeader; CommonHeader;
lu_byte status;
StkId top; /* first free slot in the stack */ StkId top; /* first free slot in the stack */
StkId base; /* base of current function */ StkId base; /* base of current function */
global_State *l_G; global_State *l_G;
@@ -106,14 +107,13 @@ struct lua_State {
const Instruction *savedpc; /* `savedpc' of current function */ const Instruction *savedpc; /* `savedpc' of current function */
StkId stack_last; /* last free slot in the stack */ StkId stack_last; /* last free slot in the stack */
StkId stack; /* stack base */ StkId stack; /* stack base */
int stacksize;
CallInfo *end_ci; /* points after end of ci array*/ CallInfo *end_ci; /* points after end of ci array*/
CallInfo *base_ci; /* array of CallInfo's */ CallInfo *base_ci; /* array of CallInfo's */
int stacksize;
int size_ci; /* size of array `base_ci' */ int size_ci; /* size of array `base_ci' */
unsigned short nCcalls; /* number of nested C calls */ unsigned short nCcalls; /* number of nested C calls */
lu_byte hookmask; lu_byte hookmask;
lu_byte allowhook; lu_byte allowhook;
lu_byte status;
int basehookcount; int basehookcount;
int hookcount; int hookcount;
lua_Hook hook; lua_Hook hook;

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lstring.c,v 2.6 2005/01/18 17:18:09 roberto Exp roberto $ ** $Id: lstring.c,v 2.7 2005/02/18 12:40:02 roberto Exp roberto $
** String table (keeps all strings handled by Lua) ** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -35,7 +35,7 @@ void luaS_resize (lua_State *L, int newsize) {
GCObject *next = p->gch.next; /* save next */ GCObject *next = p->gch.next; /* save next */
unsigned int h = gco2ts(p)->hash; unsigned int h = gco2ts(p)->hash;
int h1 = lmod(h, newsize); /* new position */ int h1 = lmod(h, newsize); /* new position */
lua_assert(cast(int, h%newsize) == lmod(h, newsize)); lua_assert(cast_int(h%newsize) == lmod(h, newsize));
p->gch.next = newhash[h1]; /* chain it */ p->gch.next = newhash[h1]; /* chain it */
newhash[h1] = p; newhash[h1] = p;
p = next; p = next;

190
lstrlib.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lstrlib.c,v 1.122 2005/08/15 14:12:32 roberto Exp roberto $ ** $Id: lstrlib.c,v 1.129 2005/12/21 12:59:43 roberto Exp roberto $
** Standard library for string operations and pattern-matching ** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -111,7 +111,9 @@ static int str_byte (lua_State *L) {
if (posi <= 0) posi = 1; if (posi <= 0) posi = 1;
if ((size_t)pose > l) pose = l; if ((size_t)pose > l) pose = l;
if (posi > pose) return 0; /* empty interval; return no values */ if (posi > pose) return 0; /* empty interval; return no values */
n = pose - posi + 1; n = (int)(pose - posi + 1);
if (posi + n <= pose) /* overflow? */
luaL_error(L, "string slice too long");
luaL_checkstack(L, n, "string slice too long"); luaL_checkstack(L, n, "string slice too long");
for (i=0; i<n; i++) for (i=0; i<n; i++)
lua_pushinteger(L, uchar(s[posi+i-1])); lua_pushinteger(L, uchar(s[posi+i-1]));
@@ -460,28 +462,32 @@ static const char *lmemfind (const char *s1, size_t l1,
} }
static void push_onecapture (MatchState *ms, int i) { static void push_onecapture (MatchState *ms, int i, const char *s,
ptrdiff_t l = ms->capture[i].len; const char *e) {
if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); if (i >= ms->level) {
if (l == CAP_POSITION) if (i == 0) /* ms->level == 0, too */
lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); lua_pushlstring(ms->L, s, e - s); /* add whole match */
else else
lua_pushlstring(ms->L, ms->capture[i].init, l); luaL_error(ms->L, "invalid capture index");
}
else {
ptrdiff_t l = ms->capture[i].len;
if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
if (l == CAP_POSITION)
lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
else
lua_pushlstring(ms->L, ms->capture[i].init, l);
}
} }
static int push_captures (MatchState *ms, const char *s, const char *e) { static int push_captures (MatchState *ms, const char *s, const char *e) {
int i; int i;
luaL_checkstack(ms->L, ms->level, "too many captures"); int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
if (ms->level == 0 && s) { /* no explicit captures? */ luaL_checkstack(ms->L, nlevels, "too many captures");
lua_pushlstring(ms->L, s, e-s); /* return whole match */ for (i = 0; i < nlevels; i++)
return 1; push_onecapture(ms, i, s, e);
} return nlevels; /* number of strings pushed */
else { /* return all captures */
for (i=0; i<ms->level; i++)
push_onecapture(ms, i);
return ms->level; /* number of strings pushed */
}
} }
@@ -516,12 +522,7 @@ static int str_find_aux (lua_State *L, int find) {
if (find) { if (find) {
lua_pushinteger(L, s1-s+1); /* start */ lua_pushinteger(L, s1-s+1); /* start */
lua_pushinteger(L, res-s); /* end */ lua_pushinteger(L, res-s); /* end */
#if defined(LUA_COMPAT_FIND)
return push_captures(&ms, NULL, 0) + 2; return push_captures(&ms, NULL, 0) + 2;
#else
return 2;
#endif
} }
else else
return push_captures(&ms, s1, res); return push_captures(&ms, s1, res);
@@ -585,42 +586,61 @@ static int gfind_nodef (lua_State *L) {
} }
static void add_s (MatchState *ms, luaL_Buffer *b, static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
const char *s, const char *e) { const char *e) {
lua_State *L = ms->L; size_t l, i;
if (lua_isstring(L, 3)) { const char *news = lua_tolstring(ms->L, 3, &l);
size_t l; for (i = 0; i < l; i++) {
const char *news = lua_tolstring(L, 3, &l); if (news[i] != L_ESC)
size_t i; luaL_addchar(b, news[i]);
for (i=0; i<l; i++) { else {
if (news[i] != L_ESC) i++; /* skip ESC */
if (!isdigit(uchar(news[i])))
luaL_addchar(b, news[i]); luaL_addchar(b, news[i]);
else if (news[i] == '0')
luaL_addlstring(b, s, e - s);
else { else {
i++; /* skip ESC */ push_onecapture(ms, news[i] - '1', s, e);
if (!isdigit(uchar(news[i]))) luaL_addvalue(b); /* add capture to accumulated result */
luaL_addchar(b, news[i]);
else {
if (news[i] == '0')
lua_pushlstring(L, s, e - s); /* add whole match */
else {
int level = check_capture(ms, news[i]);
push_onecapture(ms, level);
}
luaL_addvalue(b); /* add capture to accumulated result */
}
} }
} }
} }
else { /* is a function */ }
int n;
lua_pushvalue(L, 3);
n = push_captures(ms, s, e); static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
lua_call(L, n, 1); const char *e) {
if (lua_isstring(L, -1)) lua_State *L = ms->L;
luaL_addvalue(b); /* add return to accumulated result */ switch (lua_type(L, 3)) {
else case LUA_TNUMBER:
lua_pop(L, 1); /* function result is not a string: pop it */ case LUA_TSTRING: {
add_s(ms, b, s, e);
return;
}
case LUA_TFUNCTION: {
int n;
lua_pushvalue(L, 3);
n = push_captures(ms, s, e);
lua_call(L, n, 1);
break;
}
case LUA_TTABLE: {
push_onecapture(ms, 0, s, e);
lua_gettable(L, 3);
break;
}
default: {
luaL_argerror(L, 3, "string/function/table expected");
return;
}
} }
if (!lua_toboolean(L, -1)) { /* nil or false? */
lua_pop(L, 1);
lua_pushlstring(L, s, e - s); /* keep original text */
}
else if (!lua_isstring(L, -1))
luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
luaL_addvalue(b); /* add result to accumulator */
} }
@@ -633,9 +653,6 @@ static int str_gsub (lua_State *L) {
int n = 0; int n = 0;
MatchState ms; MatchState ms;
luaL_Buffer b; luaL_Buffer b;
luaL_argcheck(L,
lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)),
3, "string or function expected");
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
ms.L = L; ms.L = L;
ms.src_init = src; ms.src_init = src;
@@ -646,7 +663,7 @@ static int str_gsub (lua_State *L) {
e = match(&ms, src, p); e = match(&ms, src, p);
if (e) { if (e) {
n++; n++;
add_s(&ms, &b, src, e); add_value(&ms, &b, src, e);
} }
if (e && e>src) /* non empty match? */ if (e && e>src) /* non empty match? */
src = e; /* skip it */ src = e; /* skip it */
@@ -666,8 +683,13 @@ static int str_gsub (lua_State *L) {
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
#define MAX_ITEM 512 #define MAX_ITEM 512
/* maximum size of each format specification (such as '%-099.99d') */ /* valid flags in a format specification */
#define MAX_FORMAT 20 #define FLAGS "-+ #0"
/*
** maximum size of each format specification (such as '%-099.99d')
** (+10 accounts for %99.99x plus margin of error)
*/
#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
@@ -695,30 +717,37 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
luaL_addchar(b, '"'); luaL_addchar(b, '"');
} }
static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
static const char *scanformat (lua_State *L, const char *strfrmt,
char *form, int *hasprecision) {
const char *p = strfrmt; const char *p = strfrmt;
while (strchr("-+ #0", *p)) p++; /* skip flags */ while (strchr(FLAGS, *p)) p++; /* skip flags */
if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
luaL_error(L, "invalid format (repeated flags)");
if (isdigit(uchar(*p))) p++; /* skip width */ if (isdigit(uchar(*p))) p++; /* skip width */
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
if (*p == '.') { if (*p == '.') {
p++; p++;
*hasprecision = 1;
if (isdigit(uchar(*p))) p++; /* skip precision */ if (isdigit(uchar(*p))) p++; /* skip precision */
if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
} }
if (isdigit(uchar(*p))) if (isdigit(uchar(*p)))
luaL_error(L, "invalid format (width or precision too long)"); luaL_error(L, "invalid format (width or precision too long)");
if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */ *(form++) = '%';
luaL_error(L, "invalid format (too long)"); strncpy(form, strfrmt, p - strfrmt + 1);
form[0] = L_ESC; form += p - strfrmt + 1;
strncpy(form+1, strfrmt, p-strfrmt+1); *form = '\0';
form[p-strfrmt+2] = 0;
return p; return p;
} }
static void addintlen (char *form) {
size_t l = strlen(form);
char spec = form[l - 1];
strcpy(form + l - 1, LUA_INTFRMLEN);
form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
}
static int str_format (lua_State *L) { static int str_format (lua_State *L) {
int arg = 1; int arg = 1;
size_t sfl; size_t sfl;
@@ -734,21 +763,26 @@ static int str_format (lua_State *L) {
else { /* format item */ else { /* format item */
char form[MAX_FORMAT]; /* to store the format (`%...') */ char form[MAX_FORMAT]; /* to store the format (`%...') */
char buff[MAX_ITEM]; /* to store the formatted item */ char buff[MAX_ITEM]; /* to store the formatted item */
int hasprecision = 0;
arg++; arg++;
strfrmt = scanformat(L, strfrmt, form, &hasprecision); strfrmt = scanformat(L, strfrmt, form);
switch (*strfrmt++) { switch (*strfrmt++) {
case 'c': case 'd': case 'i': { case 'c': {
sprintf(buff, form, luaL_checkint(L, arg)); sprintf(buff, form, (int)luaL_checknumber(L, arg));
break;
}
case 'd': case 'i': {
addintlen(form);
sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
break; break;
} }
case 'o': case 'u': case 'x': case 'X': { case 'o': case 'u': case 'x': case 'X': {
sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg))); addintlen(form);
sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
break; break;
} }
case 'e': case 'E': case 'f': case 'e': case 'E': case 'f':
case 'g': case 'G': { case 'g': case 'G': {
sprintf(buff, form, luaL_checknumber(L, arg)); sprintf(buff, form, (double)luaL_checknumber(L, arg));
break; break;
} }
case 'q': { case 'q': {
@@ -758,7 +792,7 @@ static int str_format (lua_State *L) {
case 's': { case 's': {
size_t l; size_t l;
const char *s = luaL_checklstring(L, arg, &l); const char *s = luaL_checklstring(L, arg, &l);
if (!hasprecision && l >= 100) { if (!strchr(form, '.') && l >= 100) {
/* no precision and string is too long to be formatted; /* no precision and string is too long to be formatted;
keep original string */ keep original string */
lua_pushvalue(L, arg); lua_pushvalue(L, arg);
@@ -803,7 +837,7 @@ static const luaL_Reg strlib[] = {
static void createmetatable (lua_State *L) { static void createmetatable (lua_State *L) {
lua_newtable(L); /* create metatable for strings */ lua_createtable(L, 0, 1); /* create metatable for strings */
lua_pushliteral(L, ""); /* dummy string */ lua_pushliteral(L, ""); /* dummy string */
lua_pushvalue(L, -2); lua_pushvalue(L, -2);
lua_setmetatable(L, -2); /* set string metatable */ lua_setmetatable(L, -2); /* set string metatable */

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltable.c,v 2.25 2005/05/31 14:25:18 roberto Exp roberto $ ** $Id: ltable.c,v 2.31 2006/01/10 13:13:06 roberto Exp roberto $
** Lua tables (hash) ** Lua tables (hash)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -66,13 +66,15 @@
/* /*
** number of ints inside a lua_Number ** number of ints inside a lua_Number
*/ */
#define numints cast(int, sizeof(lua_Number)/sizeof(int)) #define numints cast_int(sizeof(lua_Number)/sizeof(int))
const Node luaH_dummynode = { #define dummynode (&dummynode_)
static const Node dummynode_ = {
{{NULL}, LUA_TNIL}, /* value */ {{NULL}, LUA_TNIL}, /* value */
{{NULL}, LUA_TNIL, NULL} /* key */ {{{NULL}, LUA_TNIL, NULL}} /* key */
}; };
@@ -95,7 +97,7 @@ static Node *hashnum (const Table *t, lua_Number n) {
** returns the `main' position of an element in a table (that is, the index ** returns the `main' position of an element in a table (that is, the index
** of its hash value) ** of its hash value)
*/ */
Node *luaH_mainposition (const Table *t, const TValue *key) { static Node *mainposition (const Table *t, const TValue *key) {
switch (ttype(key)) { switch (ttype(key)) {
case LUA_TNUMBER: case LUA_TNUMBER:
return hashnum(t, nvalue(key)); return hashnum(t, nvalue(key));
@@ -120,7 +122,7 @@ static int arrayindex (const TValue *key) {
lua_Number n = nvalue(key); lua_Number n = nvalue(key);
int k; int k;
lua_number2int(k, n); lua_number2int(k, n);
if (luai_numeq(L, cast(lua_Number, k), nvalue(key))) if (luai_numeq(cast_num(k), n))
return k; return k;
} }
return -1; /* `key' did not match some condition */ return -1; /* `key' did not match some condition */
@@ -139,13 +141,13 @@ static int findindex (lua_State *L, Table *t, StkId key) {
if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
return i-1; /* yes; that's the index (corrected to C) */ return i-1; /* yes; that's the index (corrected to C) */
else { else {
Node *n = luaH_mainposition(t, key); Node *n = mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */ do { /* check whether `key' is somewhere in the chain */
/* key may be dead already, but it is ok to use it in `next' */ /* key may be dead already, but it is ok to use it in `next' */
if (luaO_rawequalObj(key2tval(n), key) || if (luaO_rawequalObj(key2tval(n), key) ||
(ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
gcvalue(gkey(n)) == gcvalue(key))) { gcvalue(gkey(n)) == gcvalue(key))) {
i = cast(int, n - gnode(t, 0)); /* key index in hash table */ i = cast_int(n - gnode(t, 0)); /* key index in hash table */
/* hash elements are numbered after array ones */ /* hash elements are numbered after array ones */
return i + t->sizearray; return i + t->sizearray;
} }
@@ -161,7 +163,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
int i = findindex(L, t, key); /* find original element */ int i = findindex(L, t, key); /* find original element */
for (i++; i < t->sizearray; i++) { /* try first array part */ for (i++; i < t->sizearray; i++) { /* try first array part */
if (!ttisnil(&t->array[i])) { /* a non-nil value? */ if (!ttisnil(&t->array[i])) { /* a non-nil value? */
setnvalue(key, cast(lua_Number, i+1)); setnvalue(key, cast_num(i+1));
setobj2s(L, key+1, &t->array[i]); setobj2s(L, key+1, &t->array[i]);
return 1; return 1;
} }
@@ -270,7 +272,7 @@ static void setarrayvector (lua_State *L, Table *t, int size) {
static void setnodevector (lua_State *L, Table *t, int size) { static void setnodevector (lua_State *L, Table *t, int size) {
int lsize; int lsize;
if (size == 0) { /* no elements to hash part? */ if (size == 0) { /* no elements to hash part? */
t->node = cast(Node *, &luaH_dummynode); /* use common `dummynode' */ t->node = cast(Node *, dummynode); /* use common `dummynode' */
lsize = 0; lsize = 0;
} }
else { else {
@@ -281,12 +283,13 @@ static void setnodevector (lua_State *L, Table *t, int size) {
size = twoto(lsize); size = twoto(lsize);
t->node = luaM_newvector(L, size, Node); t->node = luaM_newvector(L, size, Node);
for (i=0; i<size; i++) { for (i=0; i<size; i++) {
gnext(&t->node[i]) = NULL; Node *n = gnode(t, i);
setnilvalue(gkey(gnode(t, i))); gnext(n) = NULL;
setnilvalue(gval(gnode(t, i))); setnilvalue(gkey(n));
setnilvalue(gval(n));
} }
} }
t->lsizenode = cast(lu_byte, lsize); t->lsizenode = cast_byte(lsize);
t->lastfree = gnode(t, size); /* all positions are free */ t->lastfree = gnode(t, size); /* all positions are free */
} }
@@ -316,13 +319,13 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
if (!ttisnil(gval(old))) if (!ttisnil(gval(old)))
setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
} }
if (nold != &luaH_dummynode) if (nold != dummynode)
luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
} }
void luaH_resizearray (lua_State *L, Table *t, int nasize) { void luaH_resizearray (lua_State *L, Table *t, int nasize) {
int nsize = (t->node == &luaH_dummynode) ? 0 : sizenode(t); int nsize = (t->node == dummynode) ? 0 : sizenode(t);
resize(L, t, nasize, nsize); resize(L, t, nasize, nsize);
} }
@@ -356,12 +359,12 @@ Table *luaH_new (lua_State *L, int narray, int nhash) {
Table *t = luaM_new(L, Table); Table *t = luaM_new(L, Table);
luaC_link(L, obj2gco(t), LUA_TTABLE); luaC_link(L, obj2gco(t), LUA_TTABLE);
t->metatable = NULL; t->metatable = NULL;
t->flags = cast(lu_byte, ~0); t->flags = cast_byte(~0);
/* temporary values (kept only if some malloc fails) */ /* temporary values (kept only if some malloc fails) */
t->array = NULL; t->array = NULL;
t->sizearray = 0; t->sizearray = 0;
t->lsizenode = 0; t->lsizenode = 0;
t->node = cast(Node *, &luaH_dummynode); t->node = cast(Node *, dummynode);
setarrayvector(L, t, narray); setarrayvector(L, t, narray);
setnodevector(L, t, nhash); setnodevector(L, t, nhash);
return t; return t;
@@ -369,7 +372,7 @@ Table *luaH_new (lua_State *L, int narray, int nhash) {
void luaH_free (lua_State *L, Table *t) { void luaH_free (lua_State *L, Table *t) {
if (t->node != &luaH_dummynode) if (t->node != dummynode)
luaM_freearray(L, t->node, sizenode(t), Node); luaM_freearray(L, t->node, sizenode(t), Node);
luaM_freearray(L, t->array, t->sizearray, TValue); luaM_freearray(L, t->array, t->sizearray, TValue);
luaM_free(L, t); luaM_free(L, t);
@@ -394,16 +397,16 @@ static Node *getfreepos (Table *t) {
** position), new key goes to an empty position. ** position), new key goes to an empty position.
*/ */
static TValue *newkey (lua_State *L, Table *t, const TValue *key) { static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp = luaH_mainposition(t, key); Node *mp = mainposition(t, key);
if (!ttisnil(gval(mp)) || mp == &luaH_dummynode) { if (!ttisnil(gval(mp)) || mp == dummynode) {
Node *othern; Node *othern;
Node *n = getfreepos(t); /* get a free place */ Node *n = getfreepos(t); /* get a free place */
if (n == NULL) { /* cannot find a free place? */ if (n == NULL) { /* cannot find a free place? */
rehash(L, t, key); /* grow table */ rehash(L, t, key); /* grow table */
return luaH_set(L, t, key); /* re-insert key into grown table */ return luaH_set(L, t, key); /* re-insert key into grown table */
} }
lua_assert(n != &luaH_dummynode); lua_assert(n != dummynode);
othern = luaH_mainposition(t, key2tval(mp)); othern = mainposition(t, key2tval(mp));
if (othern != mp) { /* is colliding node out of its main position? */ if (othern != mp) { /* is colliding node out of its main position? */
/* yes; move colliding node into free position */ /* yes; move colliding node into free position */
while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
@@ -434,14 +437,14 @@ const TValue *luaH_getnum (Table *t, int key) {
if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
return &t->array[key-1]; return &t->array[key-1];
else { else {
lua_Number nk = cast(lua_Number, key); lua_Number nk = cast_num(key);
Node *n = hashnum(t, nk); Node *n = hashnum(t, nk);
do { /* check whether `key' is somewhere in the chain */ do { /* check whether `key' is somewhere in the chain */
if (ttisnumber(gkey(n)) && luai_numeq(L, nvalue(gkey(n)), nk)) if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
return gval(n); /* that's it */ return gval(n); /* that's it */
else n = gnext(n); else n = gnext(n);
} while (n); } while (n);
return &luaO_nilobject; return luaO_nilobject;
} }
} }
@@ -456,7 +459,7 @@ const TValue *luaH_getstr (Table *t, TString *key) {
return gval(n); /* that's it */ return gval(n); /* that's it */
else n = gnext(n); else n = gnext(n);
} while (n); } while (n);
return &luaO_nilobject; return luaO_nilobject;
} }
@@ -465,24 +468,24 @@ const TValue *luaH_getstr (Table *t, TString *key) {
*/ */
const TValue *luaH_get (Table *t, const TValue *key) { const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) { switch (ttype(key)) {
case LUA_TNIL: return &luaO_nilobject; case LUA_TNIL: return luaO_nilobject;
case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
case LUA_TNUMBER: { case LUA_TNUMBER: {
int k; int k;
lua_Number n = nvalue(key); lua_Number n = nvalue(key);
lua_number2int(k, n); lua_number2int(k, n);
if (luai_numeq(L, cast(lua_Number, k), nvalue(key))) /* index is int? */ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
return luaH_getnum(t, k); /* use specialized version */ return luaH_getnum(t, k); /* use specialized version */
/* else go through */ /* else go through */
} }
default: { default: {
Node *n = luaH_mainposition(t, key); Node *n = mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */ do { /* check whether `key' is somewhere in the chain */
if (luaO_rawequalObj(key2tval(n), key)) if (luaO_rawequalObj(key2tval(n), key))
return gval(n); /* that's it */ return gval(n); /* that's it */
else n = gnext(n); else n = gnext(n);
} while (n); } while (n);
return &luaO_nilobject; return luaO_nilobject;
} }
} }
} }
@@ -491,11 +494,11 @@ const TValue *luaH_get (Table *t, const TValue *key) {
TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
const TValue *p = luaH_get(t, key); const TValue *p = luaH_get(t, key);
t->flags = 0; t->flags = 0;
if (p != &luaO_nilobject) if (p != luaO_nilobject)
return cast(TValue *, p); return cast(TValue *, p);
else { else {
if (ttisnil(key)) luaG_runerror(L, "table index is nil"); if (ttisnil(key)) luaG_runerror(L, "table index is nil");
else if (ttisnumber(key) && !luai_numeq(L, nvalue(key), nvalue(key))) else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
luaG_runerror(L, "table index is NaN"); luaG_runerror(L, "table index is NaN");
return newkey(L, t, key); return newkey(L, t, key);
} }
@@ -504,11 +507,11 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
TValue *luaH_setnum (lua_State *L, Table *t, int key) { TValue *luaH_setnum (lua_State *L, Table *t, int key) {
const TValue *p = luaH_getnum(t, key); const TValue *p = luaH_getnum(t, key);
if (p != &luaO_nilobject) if (p != luaO_nilobject)
return cast(TValue *, p); return cast(TValue *, p);
else { else {
TValue k; TValue k;
setnvalue(&k, cast(lua_Number, key)); setnvalue(&k, cast_num(key));
return newkey(L, t, &k); return newkey(L, t, &k);
} }
} }
@@ -516,7 +519,7 @@ TValue *luaH_setnum (lua_State *L, Table *t, int key) {
TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
const TValue *p = luaH_getstr(t, key); const TValue *p = luaH_getstr(t, key);
if (p != &luaO_nilobject) if (p != luaO_nilobject)
return cast(TValue *, p); return cast(TValue *, p);
else { else {
TValue k; TValue k;
@@ -528,11 +531,11 @@ TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
static int unbound_search (Table *t, unsigned int j) { static int unbound_search (Table *t, unsigned int j) {
unsigned int i = j; /* i is zero or a present index */ unsigned int i = j; /* i is zero or a present index */
j = j+1; j++;
/* find `i' and `j' such that i is present and j is not */ /* find `i' and `j' such that i is present and j is not */
while (!ttisnil(luaH_getnum(t, j))) { while (!ttisnil(luaH_getnum(t, j))) {
i = j; i = j;
j = i*2; j *= 2;
if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
/* table was built with bad purposes: resort to linear search */ /* table was built with bad purposes: resort to linear search */
i = 1; i = 1;
@@ -541,7 +544,7 @@ static int unbound_search (Table *t, unsigned int j) {
} }
} }
/* now do a binary search between them */ /* now do a binary search between them */
while (i < j-1) { while (j - i > 1) {
unsigned int m = (i+j)/2; unsigned int m = (i+j)/2;
if (ttisnil(luaH_getnum(t, m))) j = m; if (ttisnil(luaH_getnum(t, m))) j = m;
else i = m; else i = m;
@@ -567,8 +570,19 @@ int luaH_getn (Table *t) {
return i; return i;
} }
/* else must find a boundary in hash part */ /* else must find a boundary in hash part */
else if (t->node == &luaH_dummynode) /* hash part is empty? */ else if (t->node == dummynode) /* hash part is empty? */
return j; /* that is easy... */ return j; /* that is easy... */
else return unbound_search(t, j); else return unbound_search(t, j);
} }
#if defined(LUA_DEBUG)
Node *luaH_mainposition (const Table *t, const TValue *key) {
return mainposition(t, key);
}
int luaH_isdummy (Node *n) { return n == dummynode; }
#endif

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltable.h,v 2.7 2005/04/25 19:24:10 roberto Exp roberto $ ** $Id: ltable.h,v 2.9 2006/01/10 12:51:53 roberto Exp roberto $
** Lua tables (hash) ** Lua tables (hash)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -11,15 +11,13 @@
#define gnode(t,i) (&(t)->node[i]) #define gnode(t,i) (&(t)->node[i])
#define gkey(n) (&(n)->i_key) #define gkey(n) (&(n)->i_key.nk)
#define gval(n) (&(n)->i_val) #define gval(n) (&(n)->i_val)
#define gnext(n) ((n)->i_key.next) #define gnext(n) ((n)->i_key.nk.next)
#define key2tval(n) (cast(const TValue *, gkey(n))) #define key2tval(n) (&(n)->i_key.tvk)
LUAI_DATA const Node luaH_dummynode;
LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
@@ -32,8 +30,11 @@ LUAI_FUNC void luaH_free (lua_State *L, Table *t);
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
LUAI_FUNC int luaH_getn (Table *t); LUAI_FUNC int luaH_getn (Table *t);
/* exported only for debugging */
#if defined(LUA_DEBUG)
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
LUAI_FUNC int luaH_isdummy (Node *n);
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltablib.c,v 1.34 2005/08/15 14:12:32 roberto Exp roberto $ ** $Id: ltablib.c,v 1.37 2005/10/21 13:47:42 roberto Exp roberto $
** Library for Table Manipulation ** Library for Table Manipulation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -40,9 +40,7 @@ static int foreach (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TFUNCTION); luaL_checktype(L, 2, LUA_TFUNCTION);
lua_pushnil(L); /* first key */ lua_pushnil(L); /* first key */
for (;;) { while (lua_next(L, 1)) {
if (lua_next(L, 1) == 0)
return 0;
lua_pushvalue(L, 2); /* function */ lua_pushvalue(L, 2); /* function */
lua_pushvalue(L, -3); /* key */ lua_pushvalue(L, -3); /* key */
lua_pushvalue(L, -3); /* value */ lua_pushvalue(L, -3); /* value */
@@ -51,6 +49,23 @@ static int foreach (lua_State *L) {
return 1; return 1;
lua_pop(L, 2); /* remove value and result */ lua_pop(L, 2); /* remove value and result */
} }
return 0;
}
static int maxn (lua_State *L) {
lua_Number max = 0;
luaL_checktype(L, 1, LUA_TTABLE);
lua_pushnil(L); /* first key */
while (lua_next(L, 1)) {
lua_pop(L, 1); /* remove value */
if (lua_type(L, -1) == LUA_TNUMBER) {
lua_Number v = lua_tonumber(L, -1);
if (v > max) max = v;
}
}
lua_pushnumber(L, max);
return 1;
} }
@@ -75,16 +90,23 @@ static int setn (lua_State *L) {
static int tinsert (lua_State *L) { static int tinsert (lua_State *L) {
int e = aux_getn(L, 1) + 1; /* first empty element */ int e = aux_getn(L, 1) + 1; /* first empty element */
int pos; /* where to insert new element */ int pos; /* where to insert new element */
if (lua_isnone(L, 3)) /* called with only 2 arguments */ switch (lua_gettop(L)) {
pos = e; /* insert new element at the end */ case 2: { /* called with only 2 arguments */
else { pos = e; /* insert new element at the end */
int i; break;
pos = luaL_checkint(L, 2); /* 2nd argument is the position */ }
if (pos > e) e = pos; /* `grow' array if necessary */ case 3: {
lua_settop(L, 3); /* function may be called with more than 3 args */ int i;
for (i = e; i > pos; i--) { /* move up elements */ pos = luaL_checkint(L, 2); /* 2nd argument is the position */
lua_rawgeti(L, 1, i-1); if (pos > e) e = pos; /* `grow' array if necessary */
lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ for (i = e; i > pos; i--) { /* move up elements */
lua_rawgeti(L, 1, i-1);
lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
}
break;
}
default: {
return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
} }
} }
luaL_setn(L, 1, e); /* new size */ luaL_setn(L, 1, e); /* new size */
@@ -112,12 +134,11 @@ static int tremove (lua_State *L) {
static int tconcat (lua_State *L) { static int tconcat (lua_State *L) {
luaL_Buffer b; luaL_Buffer b;
size_t lsep; size_t lsep;
int i, last;
const char *sep = luaL_optlstring(L, 2, "", &lsep); const char *sep = luaL_optlstring(L, 2, "", &lsep);
int i = luaL_optint(L, 3, 1);
int last = luaL_optint(L, 4, -2);
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
if (last == -2) i = luaL_optint(L, 3, 1);
last = luaL_getn(L, 1); last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
for (; i <= last; i++) { for (; i <= last; i++) {
lua_rawgeti(L, 1, i); lua_rawgeti(L, 1, i);
@@ -241,6 +262,7 @@ static const luaL_Reg tab_funcs[] = {
{"foreach", foreach}, {"foreach", foreach},
{"foreachi", foreachi}, {"foreachi", foreachi},
{"getn", getn}, {"getn", getn},
{"maxn", maxn},
{"insert", tinsert}, {"insert", tinsert},
{"remove", tremove}, {"remove", tremove},
{"setn", setn}, {"setn", setn},

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltests.c,v 2.29 2005/08/26 17:32:05 roberto Exp roberto $ ** $Id: ltests.c,v 2.35 2006/01/10 12:50:00 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation ** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -564,7 +564,7 @@ static int table_query (lua_State *L) {
t = hvalue(obj_at(L, 1)); t = hvalue(obj_at(L, 1));
if (i == -1) { if (i == -1) {
lua_pushinteger(L, t->sizearray); lua_pushinteger(L, t->sizearray);
lua_pushinteger(L, t->node == &luaH_dummynode ? 0 : sizenode(t)); lua_pushinteger(L, luaH_isdummy(t->node) ? 0 : sizenode(t));
lua_pushinteger(L, t->lastfree - t->node); lua_pushinteger(L, t->lastfree - t->node);
} }
else if (i < t->sizearray) { else if (i < t->sizearray) {
@@ -725,6 +725,7 @@ static int loadlib (lua_State *L) {
{"mathlibopen", luaopen_math}, {"mathlibopen", luaopen_math},
{"strlibopen", luaopen_string}, {"strlibopen", luaopen_string},
{"tablibopen", luaopen_table}, {"tablibopen", luaopen_table},
{"packageopen", luaopen_package},
{NULL, NULL} {NULL, NULL}
}; };
lua_State *L1 = cast(lua_State *, lua_State *L1 = cast(lua_State *,
@@ -737,7 +738,6 @@ static int loadlib (lua_State *L) {
static int closestate (lua_State *L) { static int closestate (lua_State *L) {
lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1))); lua_State *L1 = cast(lua_State *, cast(unsigned long, luaL_checknumber(L, 1)));
lua_close(L1); lua_close(L1);
lua_unlock(L); /* close cannot unlock that */
return 0; return 0;
} }
@@ -798,7 +798,7 @@ static int getnum_aux (lua_State *L, const char **pc) {
int sig = 1; int sig = 1;
skip(pc); skip(pc);
if (**pc == '.') { if (**pc == '.') {
res = cast(int, lua_tonumber(L, -1)); res = cast_int(lua_tonumber(L, -1));
lua_pop(L, 1); lua_pop(L, 1);
(*pc)++; (*pc)++;
return res; return res;
@@ -807,7 +807,7 @@ static int getnum_aux (lua_State *L, const char **pc) {
sig = -1; sig = -1;
(*pc)++; (*pc)++;
} }
while (isdigit(cast(int, **pc))) res = res*10 + (*(*pc)++) - '0'; while (isdigit(cast_int(**pc))) res = res*10 + (*(*pc)++) - '0';
return sig*res; return sig*res;
} }
@@ -994,7 +994,7 @@ static int testC (lua_State *L) {
#ifndef luaL_setn #ifndef luaL_setn
else if EQ("setn") { else if EQ("setn") {
int i = getindex; int i = getindex;
int n = cast(int, lua_tonumber(L1, -1)); int n = cast_int(lua_tonumber(L1, -1));
luaL_setn(L1, i, n); luaL_setn(L1, i, n);
lua_pop(L1, 1); lua_pop(L1, 1);
} }
@@ -1121,39 +1121,27 @@ static const struct luaL_Reg tests_funcs[] = {
}; };
static void fim (void) {
if (!islocked)
lua_close(lua_state);
lua_assert(memcontrol.numblocks == 0);
lua_assert(memcontrol.total == 0);
}
static int l_panic (lua_State *L) {
UNUSED(L);
fprintf(stderr, "unable to recover; exiting\n");
return 0;
}
int luaB_opentests (lua_State *L) { int luaB_opentests (lua_State *L) {
void *ud; void *ud;
lua_assert(lua_getallocf(L, &ud) == debug_realloc); lua_assert(lua_getallocf(L, &ud) == debug_realloc);
lua_assert(ud == cast(void *, &memcontrol)); lua_assert(ud == cast(void *, &memcontrol));
lua_atpanic(L, l_panic); lua_setallocf(L, lua_getallocf(L, NULL), ud);
lua_state = L; /* keep first state to be opened */ lua_state = L; /* keep first state to be opened */
luaL_register(L, "T", tests_funcs); luaL_register(L, "T", tests_funcs);
atexit(fim);
return 0; return 0;
} }
#undef main #undef main
int main (int argc, char *argv[]) { int main (int argc, char *argv[]) {
int ret;
char *limit = getenv("MEMLIMIT"); char *limit = getenv("MEMLIMIT");
if (limit) if (limit)
memcontrol.memlimit = strtoul(limit, NULL, 10); memcontrol.memlimit = strtoul(limit, NULL, 10);
return l_main(argc, argv); ret = l_main(argc, argv);
lua_assert(memcontrol.numblocks == 0);
lua_assert(memcontrol.total == 0);
return ret;
} }
#endif #endif

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltests.h,v 2.14 2005/05/03 19:01:17 roberto Exp roberto $ ** $Id: ltests.h,v 2.16 2005/09/14 17:48:57 roberto Exp roberto $
** Internal Header for Debugging of the Lua Implementation ** Internal Header for Debugging of the Lua Implementation
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -15,7 +15,6 @@
#undef NDEBUG #undef NDEBUG
#include <assert.h> #include <assert.h>
#undef lua_assert
#define lua_assert(c) assert(c) #define lua_assert(c) assert(c)
@@ -55,16 +54,19 @@ int lua_checkpc (lua_State *L, pCallInfo ci);
/* test for lock/unlock */ /* test for lock/unlock */
#undef luai_userstateopen #undef luai_userstateopen
#undef luai_userstatethread
#undef lua_lock #undef lua_lock
#undef lua_unlock #undef lua_unlock
#undef LUAI_EXTRASPACE #undef LUAI_EXTRASPACE
LUAI_DATA int islocked; struct L_EXTRA { int lock; int *plock; };
#define LUAI_EXTRASPACE sizeof(double) #define LUAI_EXTRASPACE sizeof(struct L_EXTRA)
#define getlock(l) (*(cast(int **, l) - 1)) #define getlock(l) (cast(struct L_EXTRA *, l) - 1)
#define luai_userstateopen(l) getlock(l) = &islocked; #define luai_userstateopen(l) \
#define lua_lock(l) lua_assert((*getlock(l))++ == 0) (getlock(l)->lock = 0, getlock(l)->plock = &(getlock(l)->lock))
#define lua_unlock(l) lua_assert(--(*getlock(l)) == 0) #define luai_userstatethread(l,l1) (getlock(l1)->plock = getlock(l)->plock)
#define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0)
#define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0)
int luaB_opentests (lua_State *L); int luaB_opentests (lua_State *L);

6
ltm.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ltm.c,v 2.5 2005/05/05 15:34:03 roberto Exp roberto $ ** $Id: ltm.c,v 2.7 2005/12/22 16:19:56 roberto Exp roberto $
** Tag methods ** Tag methods
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -51,7 +51,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *tm = luaH_getstr(events, ename); const TValue *tm = luaH_getstr(events, ename);
lua_assert(event <= TM_EQ); lua_assert(event <= TM_EQ);
if (ttisnil(tm)) { /* no tag method? */ if (ttisnil(tm)) { /* no tag method? */
events->flags |= cast(lu_byte, 1u<<event); /* cache this fact */ events->flags |= cast_byte(1u<<event); /* cache this fact */
return NULL; return NULL;
} }
else return tm; else return tm;
@@ -70,6 +70,6 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
default: default:
mt = G(L)->mt[ttype(o)]; mt = G(L)->mt[ttype(o)];
} }
return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : &luaO_nilobject); return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
} }

194
lua.c
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lua.c,v 1.149 2005/08/26 17:32:05 roberto Exp roberto $ ** $Id: lua.c,v 1.156 2005/12/29 12:30:16 roberto Exp roberto $
** Lua stand-alone interpreter ** Lua stand-alone interpreter
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -43,12 +43,13 @@ static void print_usage (void) {
fprintf(stderr, fprintf(stderr,
"usage: %s [options] [script [args]].\n" "usage: %s [options] [script [args]].\n"
"Available options are:\n" "Available options are:\n"
" - execute stdin as a file\n"
" -e stat execute string " LUA_QL("stat") "\n" " -e stat execute string " LUA_QL("stat") "\n"
" -i enter interactive mode after executing " LUA_QL("script") "\n"
" -l name require library " LUA_QL("name") "\n" " -l name require library " LUA_QL("name") "\n"
" -i enter interactive mode after executing " LUA_QL("script") "\n"
" -v show version information\n" " -v show version information\n"
" -- stop handling options\n" , " -- stop handling options\n"
" - execute stdin and stop handling options\n"
,
progname); progname);
fflush(stderr); fflush(stderr);
} }
@@ -99,6 +100,8 @@ static int docall (lua_State *L, int narg, int clear) {
status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
lua_remove(L, base); /* remove traceback function */ lua_remove(L, base); /* remove traceback function */
/* force a complete garbage collection in case of errors */
if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
return status; return status;
} }
@@ -108,13 +111,16 @@ static void print_version (void) {
} }
static int getargs (lua_State *L, int argc, char **argv, int n) { static int getargs (lua_State *L, char **argv, int n) {
int narg = argc - (n + 1); /* number of arguments to the script */ int narg;
int i; int i;
int argc = 0;
while (argv[argc]) argc++; /* count total number of arguments */
narg = argc - (n + 1); /* number of arguments to the script */
luaL_checkstack(L, narg + 3, "too many arguments to script"); luaL_checkstack(L, narg + 3, "too many arguments to script");
for (i=n+1; i < argc; i++) for (i=n+1; i < argc; i++)
lua_pushstring(L, argv[i]); lua_pushstring(L, argv[i]);
lua_newtable(L); lua_createtable(L, narg, n + 1);
for (i=0; i < argc; i++) { for (i=0; i < argc; i++) {
lua_pushstring(L, argv[i]); lua_pushstring(L, argv[i]);
lua_rawseti(L, -2, i - n); lua_rawseti(L, -2, i - n);
@@ -209,7 +215,6 @@ static void dotty (lua_State *L) {
int status; int status;
const char *oldprogname = progname; const char *oldprogname = progname;
progname = NULL; progname = NULL;
print_version();
while ((status = loadline(L)) != -1) { while ((status = loadline(L)) != -1) {
if (status == 0) status = docall(L, 0, 0); if (status == 0) status = docall(L, 0, 0);
report(L, status); report(L, status);
@@ -229,86 +234,71 @@ static void dotty (lua_State *L) {
} }
#define clearinteractive(i) (*i &= 2) static int handle_script (lua_State *L, char **argv, int n) {
int status;
const char *fname;
int narg = getargs(L, argv, n); /* collect arguments */
lua_setglobal(L, "arg");
fname = argv[n];
if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
fname = NULL; /* stdin */
status = luaL_loadfile(L, fname);
lua_insert(L, -(narg+1));
if (status == 0)
status = docall(L, narg, 0);
else
lua_pop(L, narg);
return report(L, status);
}
static int handle_argv (lua_State *L, int argc, char **argv, int *interactive) {
if (argv[1] == NULL) { /* no arguments? */ static int collectargs (char **argv, int *pi, int *pv, int *pe) {
*interactive = 0; int i;
if (lua_stdin_is_tty()) for (i = 1; argv[i] != NULL; i++) {
dotty(L); if (argv[i][0] != '-') /* not an option? */
else return i;
dofile(L, NULL); /* executes stdin as a file */ switch (argv[i][1]) { /* option */
case '-': return (argv[i+1] != NULL ? i+1 : 0);
case '\0': return i;
case 'i': *pi = 1; /* go through */
case 'v': *pv = 1; break;
case 'e': *pe = 1; /* go through */
case 'l':
if (argv[i][2] == '\0') {
i++;
if (argv[i] == NULL) return -1;
}
break;
default: return -1; /* invalid option */
}
} }
else { /* other arguments; loop over them */ return 0;
int i; }
for (i = 1; argv[i] != NULL; i++) {
if (argv[i][0] != '-') break; /* not an option? */
switch (argv[i][1]) { /* option */ static int runargs (lua_State *L, char **argv, int n) {
case '-': { /* `--' */ int i;
if (argv[i][2] != '\0') { for (i = 1; i < n; i++) {
print_usage(); if (argv[i] == NULL) continue;
return 1; lua_assert(argv[i][0] == '-');
} switch (argv[i][1]) { /* option */
i++; /* skip this argument */ case 'e': {
goto endloop; /* stop handling arguments */ const char *chunk = argv[i] + 2;
} if (*chunk == '\0') chunk = argv[++i];
case '\0': { lua_assert(chunk != NULL);
clearinteractive(interactive); if (dostring(L, chunk, "=(command line)") != 0)
dofile(L, NULL); /* executes stdin as a file */
break;
}
case 'i': {
*interactive = 2; /* force interactive mode after arguments */
break;
}
case 'v': {
clearinteractive(interactive);
print_version();
break;
}
case 'e': {
const char *chunk = argv[i] + 2;
clearinteractive(interactive);
if (*chunk == '\0') chunk = argv[++i];
if (chunk == NULL) {
print_usage();
return 1;
}
if (dostring(L, chunk, "=(command line)") != 0)
return 1;
break;
}
case 'l': {
const char *filename = argv[i] + 2;
if (*filename == '\0') filename = argv[++i];
if (filename == NULL) {
print_usage();
return 1;
}
if (dolibrary(L, filename))
return 1; /* stop if file fails */
break;
}
default: {
clearinteractive(interactive);
print_usage();
return 1; return 1;
} break;
} }
} endloop: case 'l': {
if (argv[i] != NULL) { const char *filename = argv[i] + 2;
int status; if (*filename == '\0') filename = argv[++i];
const char *filename = argv[i]; lua_assert(filename != NULL);
int narg = getargs(L, argc, argv, i); /* collect arguments */ if (dolibrary(L, filename))
lua_setglobal(L, "arg"); return 1; /* stop if file fails */
clearinteractive(interactive); break;
status = luaL_loadfile(L, filename); }
lua_insert(L, -(narg+1)); default: break;
if (status == 0)
status = docall(L, narg, 0);
else
lua_pop(L, narg);
return report(L, status);
} }
} }
return 0; return 0;
@@ -334,17 +324,37 @@ struct Smain {
static int pmain (lua_State *L) { static int pmain (lua_State *L) {
struct Smain *s = (struct Smain *)lua_touserdata(L, 1); struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
int status; char **argv = s->argv;
int interactive = 1; int script;
if (s->argv[0] && s->argv[0][0]) progname = s->argv[0]; int has_i = 0, has_v = 0, has_e = 0;
globalL = L; globalL = L;
if (argv[0] && argv[0][0]) progname = argv[0];
lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
luaL_openlibs(L); /* open libraries */ luaL_openlibs(L); /* open libraries */
status = handle_luainit(L); lua_gc(L, LUA_GCRESTART, 0);
if (status == 0) { s->status = handle_luainit(L);
status = handle_argv(L, s->argc, s->argv, &interactive); if (s->status != 0) return 0;
if (status == 0 && interactive) dotty(L); script = collectargs(argv, &has_i, &has_v, &has_e);
if (script < 0) { /* invalid args? */
print_usage();
s->status = 1;
return 0;
}
if (has_v) print_version();
s->status = runargs(L, argv, (script > 0) ? script : s->argc);
if (s->status != 0) return 0;
if (script)
s->status = handle_script(L, argv, script);
if (s->status != 0) return 0;
if (has_i)
dotty(L);
else if (script == 0 && !has_e && !has_v) {
if (lua_stdin_is_tty()) {
print_version();
dotty(L);
}
else dofile(L, NULL); /* executes stdin as a file */
} }
s->status = status;
return 0; return 0;
} }

14
lua.h
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lua.h,v 1.211 2005/08/12 13:34:15 roberto Exp roberto $ ** $Id: lua.h,v 1.215 2005/12/27 17:09:50 roberto Exp roberto $
** Lua - An Extensible Extension Language ** Lua - An Extensible Extension Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file ** See Copyright Notice at the end of this file
@@ -18,7 +18,7 @@
#define LUA_VERSION "Lua 5.1" #define LUA_VERSION "Lua 5.1"
#define LUA_VERSION_NUM 501 #define LUA_VERSION_NUM 501
#define LUA_COPYRIGHT "Copyright (C) 1994-2005 Lua.org, PUC-Rio" #define LUA_COPYRIGHT "Copyright (C) 1994-2006 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
@@ -221,9 +221,10 @@ LUA_API int (lua_status) (lua_State *L);
#define LUA_GCRESTART 1 #define LUA_GCRESTART 1
#define LUA_GCCOLLECT 2 #define LUA_GCCOLLECT 2
#define LUA_GCCOUNT 3 #define LUA_GCCOUNT 3
#define LUA_GCSTEP 4 #define LUA_GCCOUNTB 4
#define LUA_GCSETPAUSE 5 #define LUA_GCSTEP 5
#define LUA_GCSETSTEPMUL 6 #define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7
LUA_API int (lua_gc) (lua_State *L, int what, int data); LUA_API int (lua_gc) (lua_State *L, int what, int data);
@@ -239,6 +240,7 @@ LUA_API int (lua_next) (lua_State *L, int idx);
LUA_API void (lua_concat) (lua_State *L, int n); LUA_API void (lua_concat) (lua_State *L, int n);
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
@@ -356,7 +358,7 @@ struct lua_Debug {
/****************************************************************************** /******************************************************************************
* Copyright (C) 1994-2005 Lua.org, PUC-Rio. All rights reserved. * Copyright (C) 1994-2006 Lua.org, PUC-Rio. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the

211
luaconf.h
View File

@@ -1,5 +1,5 @@
/* /*
** $Id: luaconf.h,v 1.64 2005/09/06 17:21:03 roberto Exp roberto $ ** $Id: luaconf.h,v 1.80 2006/01/27 13:54:39 roberto Exp roberto $
** Configuration file for Lua ** Configuration file for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -19,8 +19,6 @@
*/ */
/* /*
@@ LUA_ANSI controls the use of non-ansi features. @@ LUA_ANSI controls the use of non-ansi features.
** CHANGE it (define it) if you want Lua to avoid the use of any ** CHANGE it (define it) if you want Lua to avoid the use of any
@@ -31,6 +29,36 @@
#endif #endif
#if !defined(LUA_ANSI) && defined(_WIN32)
#define LUA_WIN
#endif
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#define LUA_USE_READLINE /* needs some extra libraries */
#endif
#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_DL_DYLD /* does not need extra library */
#endif
/*
@@ LUA_USE_POSIX includes all functionallity listed as X/Open System
@* Interfaces Extension (XSI).
** CHANGE it (define it) if your system is XSI compatible.
*/
#if defined(LUA_USE_POSIX)
#define LUA_USE_MKSTEMP
#define LUA_USE_ISATTY
#define LUA_USE_POPEN
#define LUA_USE_ULONGJMP
#endif
/* /*
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
@* Lua libraries. @* Lua libraries.
@@ -92,7 +120,7 @@
#define LUA_PATHSEP ";" #define LUA_PATHSEP ";"
#define LUA_PATH_MARK "?" #define LUA_PATH_MARK "?"
#define LUA_EXECDIR "!" #define LUA_EXECDIR "!"
#define LUA_IGMARK ":" #define LUA_IGMARK "-"
/* /*
@@ -141,10 +169,12 @@
#if defined(luaall_c) #if defined(luaall_c)
#define LUAI_FUNC static #define LUAI_FUNC static
#define LUAI_DATA /* empty */ #define LUAI_DATA /* empty */
#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ #elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) defined(__ELF__)
#define LUAI_FUNC __attribute__((visibility("hidden"))) extern #define LUAI_FUNC __attribute__((visibility("hidden"))) extern
#define LUAI_DATA LUAI_FUNC #define LUAI_DATA LUAI_FUNC
#else #else
#define LUAI_FUNC extern #define LUAI_FUNC extern
#define LUAI_DATA extern #define LUAI_DATA extern
@@ -152,13 +182,6 @@
/*
@@ lua_assert describes the internal assertions in Lua.
** CHANGE that only if you need to debug Lua.
*/
#define lua_assert(c) ((void)0)
/* /*
@@ LUA_QL describes how error messages quote program elements. @@ LUA_QL describes how error messages quote program elements.
** CHANGE it if you want a different appearance. ** CHANGE it if you want a different appearance.
@@ -189,10 +212,10 @@
** CHANGE it if you have a better definition for non-POSIX/non-Windows ** CHANGE it if you have a better definition for non-POSIX/non-Windows
** systems. ** systems.
*/ */
#if !defined(LUA_ANSI) && defined(_POSIX_C_SOURCE) #if defined(LUA_USE_ISATTY)
#include <unistd.h> #include <unistd.h>
#define lua_stdin_is_tty() isatty(0) #define lua_stdin_is_tty() isatty(0)
#elif !defined(LUA_ANSI) && defined(_WIN32) #elif defined(LUA_WIN)
#include <io.h> #include <io.h>
#include <stdio.h> #include <stdio.h>
#define lua_stdin_is_tty() _isatty(_fileno(stdin)) #define lua_stdin_is_tty() _isatty(_fileno(stdin))
@@ -239,17 +262,17 @@
#include <stdio.h> #include <stdio.h>
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#define lua_readline(L,b,p) (((b)=readline(p)) != NULL) #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,idx) \ #define lua_saveline(L,idx) \
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
add_history(lua_tostring(L, idx)); /* add it to history */ add_history(lua_tostring(L, idx)); /* add it to history */
#define lua_freeline(L,b) free(b) #define lua_freeline(L,b) ((void)L, free(b))
#else #else
#define lua_readline(L,b,p) \ #define lua_readline(L,b,p) \
(fputs(p, stdout), fflush(stdout), /* show prompt */ \ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
#define lua_saveline(L,idx) ((void)0) #define lua_saveline(L,idx) { (void)L; (void)idx; }
#define lua_freeline(L,b) ((void)0) #define lua_freeline(L,b) { (void)L; (void)b; }
#endif #endif
#endif #endif
@@ -315,13 +338,6 @@
*/ */
#define LUA_COMPAT_LSTR 1 #define LUA_COMPAT_LSTR 1
/*
@@ LUA_COMPAT_FIND controls compatibility with old 'string.find' behavior.
** CHANGE it to undefined as soon as your programs use 'string.find' only
** to find patterns.
*/
#define LUA_COMPAT_FIND
/* /*
@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. @@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.
** CHANGE it to undefined as soon as you rename 'string.gfind' to ** CHANGE it to undefined as soon as you rename 'string.gfind' to
@@ -329,7 +345,6 @@
*/ */
#define LUA_COMPAT_GFIND #define LUA_COMPAT_GFIND
/* /*
@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' @@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'
@* behavior. @* behavior.
@@ -349,10 +364,9 @@
*/ */
#if defined(LUA_USE_APICHECK) #if defined(LUA_USE_APICHECK)
#include <assert.h> #include <assert.h>
#define luai_apicheck(L,o) assert(o) #define luai_apicheck(L,o) { (void)L; assert(o); }
#else #else
/* (By default lua_assert is empty, so luai_apicheck is also empty.) */ #define luai_apicheck(L,o) { (void)L; }
#define luai_apicheck(L,o) lua_assert(o)
#endif #endif
@@ -464,31 +478,6 @@
/*
@@ lua_number2int is a macro to convert lua_Number to int.
@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
** CHANGE them if you know a faster way to convert a lua_Number to
** int (with any rounding method and without throwing errors) in your
** system. In Pentium machines, a naive typecast from double to int
** in C is extremely slow, so any alternative is worth trying.
*/
/* On a Pentium, resort to a trick */
#if !defined(LUA_ANSI) && !defined(__SSE2__) && \
(defined(__i386) || defined (_M_IX86))
union luai_Cast { double l_d; long l_l; };
#define lua_number2int(i,d) \
{ volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
#define lua_number2integer(i,n) lua_number2int(i, n)
/* this option always works, but may be slow */
#else
#define lua_number2int(i,d) ((i)=(int)(d))
#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
#endif
/* /*
** {================================================================== ** {==================================================================
@@ -499,6 +488,7 @@ union luai_Cast { double l_d; long l_l; };
** =================================================================== ** ===================================================================
*/ */
#define LUA_NUMBER_DOUBLE
#define LUA_NUMBER double #define LUA_NUMBER double
/* /*
@@ -525,16 +515,45 @@ union luai_Cast { double l_d; long l_l; };
/* /*
@@ The luai_num* macros define the primitive operations over numbers. @@ The luai_num* macros define the primitive operations over numbers.
*/ */
#define luai_numadd(L,a,b) ((a)+(b)) #if defined(LUA_CORE)
#define luai_numsub(L,a,b) ((a)-(b)) #include <math.h>
#define luai_nummul(L,a,b) ((a)*(b)) #define luai_numadd(a,b) ((a)+(b))
#define luai_numdiv(L,a,b) ((a)/(b)) #define luai_numsub(a,b) ((a)-(b))
#define luai_nummod(L,a,b) ((a) - floor((a)/(b))*(b)) #define luai_nummul(a,b) ((a)*(b))
#define luai_numpow(L,a,b) pow(a,b) #define luai_numdiv(a,b) ((a)/(b))
#define luai_numunm(L,a) (-(a)) #define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
#define luai_numeq(L,a,b) ((a)==(b)) #define luai_numpow(a,b) (pow(a,b))
#define luai_numlt(L,a,b) ((a)<(b)) #define luai_numunm(a) (-(a))
#define luai_numle(L,a,b) ((a)<=(b)) #define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(a,b) ((a)<(b))
#define luai_numle(a,b) ((a)<=(b))
#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif
/*
@@ lua_number2int is a macro to convert lua_Number to int.
@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
** CHANGE them if you know a faster way to convert a lua_Number to
** int (with any rounding method and without throwing errors) in your
** system. In Pentium machines, a naive typecast from double to int
** in C is extremely slow, so any alternative is worth trying.
*/
/* On a Pentium, resort to a trick */
#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
(defined(__i386) || defined (_M_IX86) || defined(__i386__))
union luai_Cast { double l_d; long l_l; };
#define lua_number2int(i,d) \
{ volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
#define lua_number2integer(i,n) lua_number2int(i, n)
/* this option always works, but may be slow */
#else
#define lua_number2int(i,d) ((i)=(int)(d))
#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
#endif
/* }================================================================== */ /* }================================================================== */
@@ -597,7 +616,7 @@ union luai_Cast { double l_d; long l_l; };
*/ */
#if defined(loslib_c) || defined(luaall_c) #if defined(loslib_c) || defined(luaall_c)
#if !defined(LUA_ANSI) && defined(_POSIX_C_SOURCE) #if defined(LUA_USE_MKSTEMP)
#include <unistd.h> #include <unistd.h>
#define LUA_TMPNAMBUFSIZE 32 #define LUA_TMPNAMBUFSIZE 32
#define lua_tmpnam(b,e) { \ #define lua_tmpnam(b,e) { \
@@ -605,6 +624,7 @@ union luai_Cast { double l_d; long l_l; };
e = mkstemp(b); \ e = mkstemp(b); \
if (e != -1) close(e); \ if (e != -1) close(e); \
e = (e == -1); } e = (e == -1); }
#else #else
#define LUA_TMPNAMBUFSIZE L_tmpnam #define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
@@ -618,21 +638,21 @@ union luai_Cast { double l_d; long l_l; };
@* the file streams. @* the file streams.
** CHANGE it if you have a way to implement it in your system. ** CHANGE it if you have a way to implement it in your system.
*/ */
#if !defined(LUA_ANSI) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 2 #if defined(LUA_USE_POPEN)
#define lua_popen(L,c,m) popen(c,m) #define lua_popen(L,c,m) ((void)L, popen(c,m))
#define lua_pclose(L,file) (pclose(file) != -1) #define lua_pclose(L,file) ((void)L, (pclose(file) != -1))
#elif !defined(LUA_ANSI) && defined(_WIN32) #elif defined(LUA_WIN)
#define lua_popen(L,c,m) _popen(c,m) #define lua_popen(L,c,m) ((void)L, _popen(c,m))
#define lua_pclose(L,file) (_pclose(file) != -1) #define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
#else #else
#define lua_popen(L,c,m) \ #define lua_popen(L,c,m) ((void)((void)c, m), \
((void)c, (void)m, luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
#define lua_pclose(L,file) ((void)file, 0) #define lua_pclose(L,file) ((void)((void)L, file), 0)
#endif #endif
@@ -647,16 +667,15 @@ union luai_Cast { double l_d; long l_l; };
** automatically. (When you change the makefile to add -ldl, you must ** automatically. (When you change the makefile to add -ldl, you must
** also add -DLUA_USE_DLOPEN.) ** also add -DLUA_USE_DLOPEN.)
** If you do not want any kind of dynamic library, undefine all these ** If you do not want any kind of dynamic library, undefine all these
** options (or just remove these definitions). ** options.
** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.
*/ */
#if !defined(LUA_ANSI) #if defined(LUA_USE_DLOPEN)
#if defined(_WIN32)
#define LUA_DL_DLL
#elif defined(__APPLE__) && defined(__MACH__)
#define LUA_DL_DYLD
#elif defined(LUA_USE_DLOPEN)
#define LUA_DL_DLOPEN #define LUA_DL_DLOPEN
#endif #endif
#if defined(LUA_WIN)
#define LUA_DL_DLL
#endif #endif
@@ -674,12 +693,34 @@ union luai_Cast { double l_d; long l_l; };
** CHANGE them if you defined LUAI_EXTRASPACE and need to do something ** CHANGE them if you defined LUAI_EXTRASPACE and need to do something
** extra when a thread is created/deleted/resumed/yielded. ** extra when a thread is created/deleted/resumed/yielded.
*/ */
#define luai_userstateopen(L) ((void)0) #define luai_userstateopen(L) ((void)L)
#define luai_userstatefree(L) ((void)0) #define luai_userstateclose(L) ((void)L)
#define luai_userstateresume(L,n) ((void)0) #define luai_userstatethread(L,L1) ((void)L)
#define luai_userstateyield(L,n) ((void)0) #define luai_userstatefree(L) ((void)L)
#define luai_userstateresume(L,n) ((void)L)
#define luai_userstateyield(L,n) ((void)L)
/*
@@ LUA_INTFRMLEN is the length modifier for integer conversions
@* in 'string.format'.
@@ LUA_INTFRM_T is the integer type correspoding to the previous length
@* modifier.
** CHANGE them if your system supports long long or does not support long.
*/
#if defined(LUA_USELONGLONG)
#define LUA_INTFRMLEN "ll"
#define LUA_INTFRM_T long long
#else
#define LUA_INTFRMLEN "l"
#define LUA_INTFRM_T long
#endif
/* =================================================================== */ /* =================================================================== */

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: lualib.h,v 1.34 2005/04/13 17:24:20 roberto Exp roberto $ ** $Id: lualib.h,v 1.35 2005/08/10 18:06:58 roberto Exp roberto $
** Lua standard libraries ** Lua standard libraries
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -44,4 +44,10 @@ LUALIB_API int (luaopen_package) (lua_State *L);
LUALIB_API void (luaL_openlibs) (lua_State *L); LUALIB_API void (luaL_openlibs) (lua_State *L);
#ifndef lua_assert
#define lua_assert(x) ((void)0)
#endif
#endif #endif

311
lundump.c
View File

@@ -1,9 +1,11 @@
/* /*
** $Id: lundump.c,v 2.4 2005/05/05 20:47:02 roberto Exp roberto $ ** $Id: lundump.c,v 1.60 2006/02/16 15:53:49 lhf Exp $
** load pre-compiled Lua chunks ** load precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
#include <string.h>
#define lundump_c #define lundump_c
#define LUA_CORE #define LUA_CORE
@@ -13,115 +15,132 @@
#include "ldo.h" #include "ldo.h"
#include "lfunc.h" #include "lfunc.h"
#include "lmem.h" #include "lmem.h"
#include "lopcodes.h" #include "lobject.h"
#include "lstring.h" #include "lstring.h"
#include "lundump.h" #include "lundump.h"
#include "lzio.h" #include "lzio.h"
#define LoadByte (lu_byte) ezgetc
typedef struct { typedef struct {
lua_State* L; lua_State* L;
ZIO* Z; ZIO* Z;
Mbuffer* b; Mbuffer* b;
int swap;
const char* name; const char* name;
} LoadState; } LoadState;
static void unexpectedEOZ (LoadState* S) #ifdef LUAC_TRUST_BINARIES
#define IF(c,s)
#else
#define IF(c,s) if (c) error(S,s)
static void error(LoadState* S, const char* why)
{ {
luaG_runerror(S->L,"unexpected end of file in %s",S->name); luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
luaD_throw(S->L,LUA_ERRSYNTAX);
}
#endif
#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
#define LoadByte(S) (lu_byte)LoadChar(S)
#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
static void LoadBlock(LoadState* S, void* b, size_t size)
{
size_t r=luaZ_read(S->Z,b,size);
IF (r!=0, "unexpected end");
} }
static int ezgetc (LoadState* S) static int LoadChar(LoadState* S)
{ {
int c=zgetc(S->Z); char x;
if (c==EOZ) unexpectedEOZ(S); LoadVar(S,x);
return c; return x;
} }
static void ezread (LoadState* S, void* b, size_t n) static int LoadInt(LoadState* S)
{
size_t r=luaZ_read(S->Z,b,n);
if (r!=0) unexpectedEOZ(S);
}
static void LoadBlock (LoadState* S, void* b, size_t size)
{
if (S->swap)
{
char* p=(char*) b+size-1;
size_t n=size;
while (n--) *p--=(char)ezgetc(S);
}
else
ezread(S,b,size);
}
static void LoadVector (LoadState* S, void* b, int m, size_t size)
{
if (S->swap)
{
char* q=(char*) b;
while (m--)
{
char* p=q+size-1;
size_t n=size;
while (n--) *p--=(char)ezgetc(S);
q+=size;
}
}
else
ezread(S,b,m*size);
}
static int LoadInt (LoadState* S)
{ {
int x; int x;
LoadBlock(S,&x,sizeof(x)); LoadVar(S,x);
if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name); IF (x<0, "bad integer");
return x; return x;
} }
static size_t LoadSize (LoadState* S) static lua_Number LoadNumber(LoadState* S)
{
size_t x;
LoadBlock(S,&x,sizeof(x));
return x;
}
static lua_Number LoadNumber (LoadState* S)
{ {
lua_Number x; lua_Number x;
LoadBlock(S,&x,sizeof(x)); LoadVar(S,x);
return x; return x;
} }
static TString* LoadString (LoadState* S) static TString* LoadString(LoadState* S)
{ {
size_t size=LoadSize(S); size_t size;
LoadVar(S,size);
if (size==0) if (size==0)
return NULL; return NULL;
else else
{ {
char* s=luaZ_openspace(S->L,S->b,size); char* s=luaZ_openspace(S->L,S->b,size);
ezread(S,s,size); LoadBlock(S,s,size);
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
} }
} }
static void LoadCode (LoadState* S, Proto* f) static void LoadCode(LoadState* S, Proto* f)
{ {
int size=LoadInt(S); int n=LoadInt(S);
f->code=luaM_newvector(S->L,size,Instruction); f->code=luaM_newvector(S->L,n,Instruction);
f->sizecode=size; f->sizecode=n;
LoadVector(S,f->code,size,sizeof(*f->code)); LoadVector(S,f->code,n,sizeof(Instruction));
} }
static void LoadLocals (LoadState* S, Proto* f) static Proto* LoadFunction(LoadState* S, TString* p);
static void LoadConstants(LoadState* S, Proto* f)
{ {
int i,n; int i,n;
n=LoadInt(S); n=LoadInt(S);
f->k=luaM_newvector(S->L,n,TValue);
f->sizek=n;
for (i=0; i<n; i++) setnilvalue(&f->k[i]);
for (i=0; i<n; i++)
{
TValue* o=&f->k[i];
int t=LoadChar(S);
switch (t)
{
case LUA_TNIL:
setnilvalue(o);
break;
case LUA_TBOOLEAN:
setbvalue(o,LoadChar(S));
break;
case LUA_TNUMBER:
setnvalue(o,LoadNumber(S));
break;
case LUA_TSTRING:
setsvalue2n(S->L,o,LoadString(S));
break;
default:
IF (1, "bad constant");
break;
}
}
n=LoadInt(S);
f->p=luaM_newvector(S->L,n,Proto*);
f->sizep=n;
for (i=0; i<n; i++) f->p[i]=NULL;
for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
}
static void LoadDebug(LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
f->lineinfo=luaM_newvector(S->L,n,int);
f->sizelineinfo=n;
LoadVector(S,f->lineinfo,n,sizeof(int));
n=LoadInt(S);
f->locvars=luaM_newvector(S->L,n,LocVar); f->locvars=luaM_newvector(S->L,n,LocVar);
f->sizelocvars=n; f->sizelocvars=n;
for (i=0; i<n; i++) f->locvars[i].varname=NULL; for (i=0; i<n; i++) f->locvars[i].varname=NULL;
@@ -131,75 +150,17 @@ static void LoadLocals (LoadState* S, Proto* f)
f->locvars[i].startpc=LoadInt(S); f->locvars[i].startpc=LoadInt(S);
f->locvars[i].endpc=LoadInt(S); f->locvars[i].endpc=LoadInt(S);
} }
}
static void LoadLines (LoadState* S, Proto* f)
{
int size=LoadInt(S);
f->lineinfo=luaM_newvector(S->L,size,int);
f->sizelineinfo=size;
LoadVector(S,f->lineinfo,size,sizeof(*f->lineinfo));
}
static void LoadUpvalues (LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S); n=LoadInt(S);
if (n!=0 && n!=f->nups)
luaG_runerror(S->L,"bad nupvalues in %s: read %d; expected %d",
S->name,n,f->nups);
f->upvalues=luaM_newvector(S->L,n,TString*); f->upvalues=luaM_newvector(S->L,n,TString*);
f->sizeupvalues=n; f->sizeupvalues=n;
for (i=0; i<n; i++) f->upvalues[i]=NULL; for (i=0; i<n; i++) f->upvalues[i]=NULL;
for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);
} }
static Proto* LoadFunction (LoadState* S, TString* p); static Proto* LoadFunction(LoadState* S, TString* p)
static void LoadConstants (LoadState* S, Proto* f)
{ {
int i,n; Proto* f=luaF_newproto(S->L);
lua_State *L=S->L; setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
n=LoadInt(S);
f->k=luaM_newvector(L,n,TValue);
f->sizek=n;
for (i=0; i<n; i++) setnilvalue(&f->k[i]);
for (i=0; i<n; i++)
{
TValue* o=&f->k[i];
int t=LoadByte(S);
switch (t)
{
case LUA_TNUMBER:
setnvalue(o,LoadNumber(S));
break;
case LUA_TSTRING:
setsvalue2n(L, o,LoadString(S));
break;
case LUA_TNIL:
setnilvalue(o);
break;
case LUA_TBOOLEAN:
setbvalue(o, LoadByte(S));
break;
default:
luaG_runerror(L,"bad constant type (%d) in %s",t,S->name);
break;
}
}
n=LoadInt(S);
f->p=luaM_newvector(L,n,Proto*);
f->sizep=n;
for (i=0; i<n; i++) f->p[i]=NULL;
for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
}
static Proto* LoadFunction (LoadState* S, TString* p)
{
lua_State *L=S->L;
Proto* f=luaF_newproto(L);
setptvalue2s(L, L->top, f);
incr_top(L);
f->source=LoadString(S); if (f->source==NULL) f->source=p; f->source=LoadString(S); if (f->source==NULL) f->source=p;
f->linedefined=LoadInt(S); f->linedefined=LoadInt(S);
f->lastlinedefined=LoadInt(S); f->lastlinedefined=LoadInt(S);
@@ -207,90 +168,56 @@ static Proto* LoadFunction (LoadState* S, TString* p)
f->numparams=LoadByte(S); f->numparams=LoadByte(S);
f->is_vararg=LoadByte(S); f->is_vararg=LoadByte(S);
f->maxstacksize=LoadByte(S); f->maxstacksize=LoadByte(S);
LoadLines(S,f);
LoadLocals(S,f);
LoadUpvalues(S,f);
LoadConstants(S,f);
LoadCode(S,f); LoadCode(S,f);
#ifndef TRUST_BINARIES LoadConstants(S,f);
if (!luaG_checkcode(f)) luaG_runerror(L,"bad code in %s",S->name); LoadDebug(S,f);
#endif IF (!luaG_checkcode(f), "bad code");
L->top--; S->L->top--;
return f; return f;
} }
static void LoadSignature (LoadState* S) static void LoadHeader(LoadState* S)
{ {
const char* s=LUA_SIGNATURE; char h[LUAC_HEADERSIZE];
while (*s!=0 && ezgetc(S)==*s) char s[LUAC_HEADERSIZE];
++s; luaU_header(h);
if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name); LoadBlock(S,s,LUAC_HEADERSIZE);
} IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
static void TestSize (LoadState* S, int s, const char* what)
{
int r=LoadByte(S);
if (r!=s)
luaG_runerror(S->L,"virtual machine mismatch in %s: "
"size of %s is %d but read %d",S->name,what,s,r);
}
#define TESTSIZE(s,w) TestSize(S,s,w)
#define V(v) v/16,v%16
static void LoadHeader (LoadState* S)
{
int version;
lua_Number x,tx=TEST_NUMBER;
LoadSignature(S);
version=LoadByte(S);
if (version>VERSION)
luaG_runerror(S->L,"%s too new: "
"read version %d.%d; expected at most %d.%d",
S->name,V(version),V(VERSION));
if (version<VERSION0) /* check last major change */
luaG_runerror(S->L,"%s too old: "
"read version %d.%d; expected at least %d.%d",
S->name,V(version),V(VERSION0));
S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */
TESTSIZE(sizeof(int),"int");
TESTSIZE(sizeof(size_t), "size_t");
TESTSIZE(sizeof(Instruction), "Instruction");
TESTSIZE(sizeof(lua_Number), "number");
x=LoadNumber(S);
if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */
luaG_runerror(S->L,"unknown number format in %s",S->name);
}
static Proto* LoadChunk (LoadState* S)
{
LoadHeader(S);
return LoadFunction(S,NULL);
} }
/* /*
** load precompiled chunk ** load precompiled chunk
*/ */
Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char *s) Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
{ {
LoadState S; LoadState S;
if (*s=='@' || *s=='=') if (*name=='@' || *name=='=')
S.name=s+1; S.name=name+1;
else if (*s==LUA_SIGNATURE[0]) else if (*name==LUA_SIGNATURE[0])
S.name="binary string"; S.name="binary string";
else else
S.name=s; S.name=name;
S.L=L; S.L=L;
S.Z=Z; S.Z=Z;
S.b=buff; S.b=buff;
return LoadChunk(&S); LoadHeader(&S);
return LoadFunction(&S,luaS_newliteral(L,"=?"));
} }
/* /*
** find byte order * make header
*/ */
int luaU_endianness (void) void luaU_header (char* h)
{ {
int x=1; int x=1;
return *(char*)&x; memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
h+=sizeof(LUA_SIGNATURE)-1;
*h++=(char)LUAC_VERSION;
*h++=(char)LUAC_FORMAT;
*h++=(char)*(char*)&x; /* endianness */
*h++=(char)sizeof(int);
*h++=(char)sizeof(size_t);
*h++=(char)sizeof(Instruction);
*h++=(char)sizeof(lua_Number);
*h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
} }

View File

@@ -1,6 +1,6 @@
/* /*
** $Id: lundump.h,v 1.35 2005/04/25 19:24:10 roberto Exp roberto $ ** $Id: lundump.h,v 1.39 2005/11/01 17:04:55 lhf Exp lhf $
** load pre-compiled Lua chunks ** load precompiled Lua chunks
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -11,25 +11,26 @@
#include "lzio.h" #include "lzio.h"
/* load one chunk; from lundump.c */ /* load one chunk; from lundump.c */
LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
const char *name);
/* find byte order; from lundump.c */ /* make header; from lundump.c */
LUAI_FUNC int luaU_endianness (void); LUAI_FUNC void luaU_header (char* h);
/* dump one chunk; from ldump.c */ /* dump one chunk; from ldump.c */
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* Main, lua_Writer w, LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
void* data, int strip);
#ifdef luac_c
/* print one chunk; from print.c */ /* print one chunk; from print.c */
LUAI_FUNC void luaU_print (const Proto* Main); LUAI_FUNC void luaU_print (const Proto* f, int full);
#endif
/* definitions for headers of binary files */ /* for header of binary files -- this is Lua 5.1 */
#define VERSION 0x50 /* last format change was in 5.0 */ #define LUAC_VERSION 0x51
#define VERSION0 0x50 /* last major change was in 5.0 */
/* a multiple of PI for testing native format */ /* for header of binary files -- this is the official format */
/* multiplying by 1E7 gives non-trivial integer values */ #define LUAC_FORMAT 0
#define TEST_NUMBER ((lua_Number)3.14159265358979323846E7)
/* size of header of binary files */
#define LUAC_HEADERSIZE 12
#endif #endif

134
lvm.c
View File

@@ -1,11 +1,10 @@
/* /*
** $Id: lvm.c,v 2.54 2005/08/29 20:49:21 roberto Exp roberto $ ** $Id: lvm.c,v 2.61 2006/01/10 12:50:00 roberto Exp roberto $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
#include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -66,7 +65,6 @@ static void traceexec (lua_State *L, const Instruction *pc) {
if (L->hookcount == 0) { if (L->hookcount == 0) {
resethookcount(L); resethookcount(L);
luaD_callhook(L, LUA_HOOKCOUNT, -1); luaD_callhook(L, LUA_HOOKCOUNT, -1);
return;
} }
} }
if (mask & LUA_MASKLINE) { if (mask & LUA_MASKLINE) {
@@ -97,7 +95,8 @@ static void callTMres (lua_State *L, StkId res, const TValue *f,
static void callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, const TValue *p3) { static void callTM (lua_State *L, const TValue *f, const TValue *p1,
const TValue *p2, const TValue *p3) {
setobj2s(L, L->top, f); /* push function */ setobj2s(L, L->top, f); /* push function */
setobj2s(L, L->top+1, p1); /* 1st argument */ setobj2s(L, L->top+1, p1); /* 1st argument */
setobj2s(L, L->top+2, p2); /* 2nd argument */ setobj2s(L, L->top+2, p2); /* 2nd argument */
@@ -226,7 +225,7 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
if (ttype(l) != ttype(r)) if (ttype(l) != ttype(r))
return luaG_ordererror(L, l, r); return luaG_ordererror(L, l, r);
else if (ttisnumber(l)) else if (ttisnumber(l))
return luai_numlt(L, nvalue(l), nvalue(r)); return luai_numlt(nvalue(l), nvalue(r));
else if (ttisstring(l)) else if (ttisstring(l))
return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
@@ -240,7 +239,7 @@ static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
if (ttype(l) != ttype(r)) if (ttype(l) != ttype(r))
return luaG_ordererror(L, l, r); return luaG_ordererror(L, l, r);
else if (ttisnumber(l)) else if (ttisnumber(l))
return luai_numle(L, nvalue(l), nvalue(r)); return luai_numle(nvalue(l), nvalue(r));
else if (ttisstring(l)) else if (ttisstring(l))
return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
@@ -256,7 +255,7 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
lua_assert(ttype(t1) == ttype(t2)); lua_assert(ttype(t1) == ttype(t2));
switch (ttype(t1)) { switch (ttype(t1)) {
case LUA_TNIL: return 1; case LUA_TNIL: return 1;
case LUA_TNUMBER: return luai_numeq(L, nvalue(t1), nvalue(t2)); case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
case LUA_TUSERDATA: { case LUA_TUSERDATA: {
@@ -319,13 +318,13 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
(c = luaV_tonumber(rc, &tempc)) != NULL) { (c = luaV_tonumber(rc, &tempc)) != NULL) {
lua_Number nb = nvalue(b), nc = nvalue(c); lua_Number nb = nvalue(b), nc = nvalue(c);
switch (op) { switch (op) {
case TM_ADD: setnvalue(ra, luai_numadd(L, nb, nc)); break; case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
case TM_SUB: setnvalue(ra, luai_numsub(L, nb, nc)); break; case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
case TM_MUL: setnvalue(ra, luai_nummul(L, nb, nc)); break; case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
case TM_DIV: setnvalue(ra, luai_numdiv(L, nb, nc)); break; case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
case TM_MOD: setnvalue(ra, luai_nummod(L, nb, nc)); break; case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
case TM_POW: setnvalue(ra, luai_numpow(L, nb, nc)); break; case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
case TM_UNM: setnvalue(ra, luai_numunm(L, nb)); break; case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
default: lua_assert(0); break; default: lua_assert(0); break;
} }
} }
@@ -358,6 +357,19 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
#define arith_op(op,tm) { \
TValue *rb = RKB(i); \
TValue *rc = RKC(i); \
if (ttisnumber(rb) && ttisnumber(rc)) { \
lua_Number nb = nvalue(rb), nc = nvalue(rc); \
setnvalue(ra, op(nb, nc)); \
} \
else \
Protect(Arith(L, ra, rb, rc, tm)); \
}
void luaV_execute (lua_State *L, int nexeccalls) { void luaV_execute (lua_State *L, int nexeccalls) {
LClosure *cl; LClosure *cl;
StkId base; StkId base;
@@ -455,76 +467,34 @@ void luaV_execute (lua_State *L, int nexeccalls) {
continue; continue;
} }
case OP_ADD: { case OP_ADD: {
TValue *rb = RKB(i); arith_op(luai_numadd, TM_ADD);
TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
setnvalue(ra, luai_numadd(L, nb, nc));
}
else
Protect(Arith(L, ra, rb, rc, TM_ADD));
continue; continue;
} }
case OP_SUB: { case OP_SUB: {
TValue *rb = RKB(i); arith_op(luai_numsub, TM_SUB);
TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
setnvalue(ra, luai_numsub(L, nb, nc));
}
else
Protect(Arith(L, ra, rb, rc, TM_SUB));
continue; continue;
} }
case OP_MUL: { case OP_MUL: {
TValue *rb = RKB(i); arith_op(luai_nummul, TM_MUL);
TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
setnvalue(ra, luai_nummul(L, nb, nc));
}
else
Protect(Arith(L, ra, rb, rc, TM_MUL));
continue; continue;
} }
case OP_DIV: { case OP_DIV: {
TValue *rb = RKB(i); arith_op(luai_numdiv, TM_DIV);
TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
setnvalue(ra, luai_numdiv(L, nb, nc));
}
else
Protect(Arith(L, ra, rb, rc, TM_DIV));
continue; continue;
} }
case OP_MOD: { case OP_MOD: {
TValue *rb = RKB(i); arith_op(luai_nummod, TM_MOD);
TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
setnvalue(ra, luai_nummod(L, nb, nc));
}
else
Protect(Arith(L, ra, rb, rc, TM_MOD));
continue; continue;
} }
case OP_POW: { case OP_POW: {
TValue *rb = RKB(i); arith_op(luai_numpow, TM_POW);
TValue *rc = RKC(i);
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
setnvalue(ra, luai_numpow(L, nb, nc));
}
else
Protect(Arith(L, ra, rb, rc, TM_POW));
continue; continue;
} }
case OP_UNM: { case OP_UNM: {
TValue *rb = RB(i); TValue *rb = RB(i);
if (ttisnumber(rb)) { if (ttisnumber(rb)) {
lua_Number nb = nvalue(rb); lua_Number nb = nvalue(rb);
setnvalue(ra, luai_numunm(L, nb)); setnvalue(ra, luai_numunm(nb));
} }
else { else {
Protect(Arith(L, ra, rb, rb, TM_UNM)); Protect(Arith(L, ra, rb, rb, TM_UNM));
@@ -540,16 +510,16 @@ void luaV_execute (lua_State *L, int nexeccalls) {
const TValue *rb = RB(i); const TValue *rb = RB(i);
switch (ttype(rb)) { switch (ttype(rb)) {
case LUA_TTABLE: { case LUA_TTABLE: {
setnvalue(ra, cast(lua_Number, luaH_getn(hvalue(rb)))); setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
break; break;
} }
case LUA_TSTRING: { case LUA_TSTRING: {
setnvalue(ra, cast(lua_Number, tsvalue(rb)->len)); setnvalue(ra, cast_num(tsvalue(rb)->len));
break; break;
} }
default: { /* try metamethod */ default: { /* try metamethod */
Protect( Protect(
if (!call_binTM(L, rb, &luaO_nilobject, ra, TM_LEN)) if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))
luaG_typeerror(L, rb, "get length of"); luaG_typeerror(L, rb, "get length of");
) )
} }
@@ -594,18 +564,18 @@ void luaV_execute (lua_State *L, int nexeccalls) {
continue; continue;
} }
case OP_TEST: { case OP_TEST: {
if (l_isfalse(ra) == GETARG_C(i)) pc++; if (l_isfalse(ra) != GETARG_C(i))
else dojump(L, pc, GETARG_sBx(*pc));
dojump(L, pc, GETARG_sBx(*pc) + 1); pc++;
continue; continue;
} }
case OP_TESTSET: { case OP_TESTSET: {
TValue *rb = RB(i); TValue *rb = RB(i);
if (l_isfalse(rb) == GETARG_C(i)) pc++; if (l_isfalse(rb) != GETARG_C(i)) {
else {
setobjs2s(L, ra, rb); setobjs2s(L, ra, rb);
dojump(L, pc, GETARG_sBx(*pc) + 1); dojump(L, pc, GETARG_sBx(*pc));
} }
pc++;
continue; continue;
} }
case OP_CALL: { case OP_CALL: {
@@ -678,9 +648,10 @@ void luaV_execute (lua_State *L, int nexeccalls) {
} }
case OP_FORLOOP: { case OP_FORLOOP: {
lua_Number step = nvalue(ra+2); lua_Number step = nvalue(ra+2);
lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
lua_Number limit = nvalue(ra+1); lua_Number limit = nvalue(ra+1);
if (step > 0 ? luai_numle(L, idx, limit) : luai_numle(L, limit, idx)) { if (luai_numlt(0, step) ? luai_numle(idx, limit)
: luai_numle(limit, idx)) {
dojump(L, pc, GETARG_sBx(i)); /* jump back */ dojump(L, pc, GETARG_sBx(i)); /* jump back */
setnvalue(ra, idx); /* update internal index... */ setnvalue(ra, idx); /* update internal index... */
setnvalue(ra+3, idx); /* ...and external index */ setnvalue(ra+3, idx); /* ...and external index */
@@ -698,7 +669,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
luaG_runerror(L, LUA_QL("for") " limit must be a number"); luaG_runerror(L, LUA_QL("for") " limit must be a number");
else if (!tonumber(pstep, ra+2)) else if (!tonumber(pstep, ra+2))
luaG_runerror(L, LUA_QL("for") " step must be a number"); luaG_runerror(L, LUA_QL("for") " step must be a number");
setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
dojump(L, pc, GETARG_sBx(i)); dojump(L, pc, GETARG_sBx(i));
continue; continue;
} }
@@ -711,12 +682,11 @@ void luaV_execute (lua_State *L, int nexeccalls) {
Protect(luaD_call(L, cb, GETARG_C(i))); Protect(luaD_call(L, cb, GETARG_C(i)));
L->top = L->ci->top; L->top = L->ci->top;
cb = RA(i) + 3; /* previous call may change the stack */ cb = RA(i) + 3; /* previous call may change the stack */
if (ttisnil(cb)) /* break loop? */ if (!ttisnil(cb)) { /* continue loop? */
pc++; /* skip jump (break loop) */
else {
setobjs2s(L, cb-1, cb); /* save control variable */ setobjs2s(L, cb-1, cb); /* save control variable */
dojump(L, pc, GETARG_sBx(*pc) + 1); /* jump back */ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */
} }
pc++;
continue; continue;
} }
case OP_SETLIST: { case OP_SETLIST: {
@@ -725,10 +695,10 @@ void luaV_execute (lua_State *L, int nexeccalls) {
int last; int last;
Table *h; Table *h;
if (n == 0) { if (n == 0) {
n = cast(int, L->top - ra) - 1; n = cast_int(L->top - ra) - 1;
L->top = L->ci->top; L->top = L->ci->top;
} }
if (c == 0) c = cast(int, *pc++); if (c == 0) c = cast_int(*pc++);
runtime_check(L, ttistable(ra)); runtime_check(L, ttistable(ra));
h = hvalue(ra); h = hvalue(ra);
last = ((c-1)*LFIELDS_PER_FLUSH) + n; last = ((c-1)*LFIELDS_PER_FLUSH) + n;
@@ -769,7 +739,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
int b = GETARG_B(i) - 1; int b = GETARG_B(i) - 1;
int j; int j;
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
int n = cast(int, ci->base - ci->func) - cl->p->numparams - 1; int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;
if (b == LUA_MULTRET) { if (b == LUA_MULTRET) {
Protect(luaD_checkstack(L, n)); Protect(luaD_checkstack(L, n));
ra = RA(i); /* previous call may change the stack */ ra = RA(i); /* previous call may change the stack */

View File

@@ -29,7 +29,7 @@ MYLIBS=
# enable Linux goodies # enable Linux goodies
MYCFLAGS= $(LOCAL) -DLUA_USE_DLOPEN -DLUA_USE_READLINE MYCFLAGS= $(LOCAL) -DLUA_USE_LINUX
MYLDFLAGS= -Wl,-E MYLDFLAGS= -Wl,-E
MYLIBS= -ldl -lreadline -lhistory -lncurses MYLIBS= -ldl -lreadline -lhistory -lncurses