diff options
author | Lua Team <team@lua.org> | 2010-01-08 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 2010-01-08 12:00:00 +0000 |
commit | 22912c77c80f8de8f7accd3319c726f7c5349fd3 (patch) | |
tree | caf064ecca31cd2ef1c919c585ee6b3d5e6d25d6 /src/lapi.c | |
parent | 300cd56eb905be061aa75bb665549b3b85109bbe (diff) | |
download | lua-github-5.2.0-work1.tar.gz |
Lua 5.2.0-work15.2.0-work1
Diffstat (limited to 'src/lapi.c')
-rw-r--r-- | src/lapi.c | 507 |
1 files changed, 290 insertions, 217 deletions
@@ -1,12 +1,10 @@ /* -** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ +** $Id: lapi.c,v 2.109 2010/01/08 15:16:56 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ -#include <assert.h> -#include <math.h> #include <stdarg.h> #include <string.h> @@ -32,42 +30,47 @@ const char lua_ident[] = - "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" - "$Authors: " LUA_AUTHORS " $\n" - "$URL: www.lua.org $\n"; + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; -#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) +#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject, \ + "invalid index") -#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) - -#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} +static Table *getcurrenv (lua_State *L) { + if (L->ci->previous == NULL) /* no enclosing function? */ + return G(L)->l_gt; /* use global table as environment */ + else { + Closure *func = curr_func(L); + return func->c.env; + } +} -static TValue *index2adr (lua_State *L, int idx) { +static TValue *index2addr (lua_State *L, int idx) { + CallInfo *ci = L->ci; if (idx > 0) { - TValue *o = L->base + (idx - 1); - api_check(L, idx <= L->ci->top - L->base); + TValue *o = ci->func + idx; + api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); if (o >= L->top) return cast(TValue *, luaO_nilobject); else return o; } else if (idx > LUA_REGISTRYINDEX) { - api_check(L, idx != 0 && -idx <= L->top - L->base); + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); return L->top + idx; } else switch (idx) { /* pseudo-indices */ - case LUA_REGISTRYINDEX: return registry(L); + case LUA_REGISTRYINDEX: return &G(L)->l_registry; case LUA_ENVIRONINDEX: { - Closure *func = curr_func(L); - sethvalue(L, &L->env, func->c.env); + sethvalue(L, &L->env, getcurrenv(L)); return &L->env; } - case LUA_GLOBALSINDEX: return gt(L); default: { Closure *func = curr_func(L); - idx = LUA_GLOBALSINDEX - idx; + idx = LUA_ENVIRONINDEX - idx; + api_check(L, idx <= UCHAR_MAX + 1, "upvalue index too large"); return (idx <= func->c.nupvalues) ? &func->c.upvalue[idx-1] : cast(TValue *, luaO_nilobject); @@ -76,32 +79,31 @@ static TValue *index2adr (lua_State *L, int idx) { } -static Table *getcurrenv (lua_State *L) { - if (L->ci == L->base_ci) /* no enclosing function? */ - return hvalue(gt(L)); /* use global table as environment */ - else { - Closure *func = curr_func(L); - return func->c.env; - } -} - - -void luaA_pushobject (lua_State *L, const TValue *o) { - setobj2s(L, L->top, o); - api_incr_top(L); +/* +** to be caled by 'lua_checkstack' in protected mode, to grow stack +** capturing memory errors +*/ +static void growstack (lua_State *L, void *ud) { + int size = *(int *)ud; + luaD_growstack(L, size); } LUA_API int lua_checkstack (lua_State *L, int size) { - int res = 1; + int res; + CallInfo *ci = L->ci; lua_lock(L); - if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) - res = 0; /* stack overflow */ - else if (size > 0) { - luaD_checkstack(L, size); - if (L->ci->top < L->top + size) - L->ci->top = L->top + size; + if (L->stack_last - L->top > size) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else { /* no; need to grow stack */ + int inuse = L->top - L->stack + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK); } + if (res && ci->top < L->top + size) + ci->top = L->top + size; /* adjust frame top */ lua_unlock(L); return res; } @@ -112,8 +114,8 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { if (from == to) return; lua_lock(to); api_checknelems(from, n); - api_check(from, G(from) == G(to)); - api_check(from, to->ci->top - to->top >= n); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); from->top -= n; for (i = 0; i < n; i++) { setobj2s(to, to->top++, from->top + i); @@ -122,11 +124,6 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { } -LUA_API void lua_setlevel (lua_State *from, lua_State *to) { - to->nCcalls = from->nCcalls; -} - - LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { lua_CFunction old; lua_lock(L); @@ -137,16 +134,10 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { } -LUA_API lua_State *lua_newthread (lua_State *L) { - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - L1 = luaE_newthread(L); - setthvalue(L, L->top, L1); - api_incr_top(L); - lua_unlock(L); - luai_userstatethread(L, L1); - return L1; +LUA_API const lua_Number *lua_version (lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + else return G(L)->version; } @@ -157,20 +148,21 @@ LUA_API lua_State *lua_newthread (lua_State *L) { LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - L->base); + return cast_int(L->top - (L->ci->func + 1)); } LUA_API void lua_settop (lua_State *L, int idx) { + StkId func = L->ci->func; lua_lock(L); if (idx >= 0) { - api_check(L, idx <= L->stack_last - L->base); - while (L->top < L->base + idx) + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + while (L->top < (func + 1) + idx) setnilvalue(L->top++); - L->top = L->base + idx; + L->top = (func + 1) + idx; } else { - api_check(L, -(idx+1) <= (L->top - L->base)); + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); L->top += idx+1; /* `subtract' index (index is negative) */ } lua_unlock(L); @@ -180,7 +172,7 @@ LUA_API void lua_settop (lua_State *L, int idx) { LUA_API void lua_remove (lua_State *L, int idx) { StkId p; lua_lock(L); - p = index2adr(L, idx); + p = index2addr(L, idx); api_checkvalidindex(L, p); while (++p < L->top) setobjs2s(L, p-1, p); L->top--; @@ -192,7 +184,7 @@ LUA_API void lua_insert (lua_State *L, int idx) { StkId p; StkId q; lua_lock(L); - p = index2adr(L, idx); + p = index2addr(L, idx); api_checkvalidindex(L, p); for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); setobjs2s(L, p, L->top); @@ -200,34 +192,50 @@ LUA_API void lua_insert (lua_State *L, int idx) { } -LUA_API void lua_replace (lua_State *L, int idx) { - StkId o; - lua_lock(L); - /* explicit test for incompatible code */ - if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) - luaG_runerror(L, "no calling environment"); - api_checknelems(L, 1); - o = index2adr(L, idx); - api_checkvalidindex(L, o); +static void moveto (lua_State *L, TValue *fr, int idx) { + TValue *to = index2addr(L, idx); + api_checkvalidindex(L, to); if (idx == LUA_ENVIRONINDEX) { Closure *func = curr_func(L); - api_check(L, ttistable(L->top - 1)); - func->c.env = hvalue(L->top - 1); - luaC_barrier(L, func, L->top - 1); + api_check(L, ttistable(fr), "table expected"); + func->c.env = hvalue(fr); + luaC_barrier(L, func, fr); } else { - setobj(L, o, L->top - 1); - if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ - luaC_barrier(L, curr_func(L), L->top - 1); + setobj(L, to, fr); + if (idx < LUA_ENVIRONINDEX) /* function upvalue? */ + luaC_barrier(L, curr_func(L), fr); } + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + lua_lock(L); + /* explicit test for incompatible code */ + if (idx == LUA_ENVIRONINDEX && L->ci->previous == NULL) + luaG_runerror(L, "no calling environment"); + api_checknelems(L, 1); + moveto(L, L->top - 1, idx); L->top--; lua_unlock(L); } +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr; + lua_lock(L); + fr = index2addr(L, fromidx); + api_checkvalidindex(L, fr); + moveto(L, fr, toidx); + lua_unlock(L); +} + + LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); - setobj2s(L, L->top, index2adr(L, idx)); + setobj2s(L, L->top, index2addr(L, idx)); api_incr_top(L); lua_unlock(L); } @@ -240,7 +248,7 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); } @@ -252,14 +260,14 @@ LUA_API const char *lua_typename (lua_State *L, int t) { LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); return iscfunction(o); } LUA_API int lua_isnumber (lua_State *L, int idx) { TValue n; - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(L, idx); return tonumber(o, &n); } @@ -271,48 +279,55 @@ LUA_API int lua_isstring (lua_State *L, int idx) { LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(L, idx); return (ttisuserdata(o) || ttislightuserdata(o)); } LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - StkId o1 = index2adr(L, index1); - StkId o2 = index2adr(L, index2); + StkId o1 = index2addr(L, index1); + StkId o2 = index2addr(L, index2); return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : luaO_rawequalObj(o1, o2); } -LUA_API int lua_equal (lua_State *L, int index1, int index2) { - StkId o1, o2; - int i; - lua_lock(L); /* may call tag method */ - o1 = index2adr(L, index1); - o2 = index2adr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); +LUA_API void lua_arith (lua_State *L, int op) { + lua_lock(L); + api_checknelems(L, 2); + if (ttisnumber(L->top - 2) && ttisnumber(L->top - 1)) { + changenvalue(L->top - 2, + luaO_arith(op, nvalue(L->top - 2), nvalue(L->top - 1))); + } + else + luaV_arith(L, L->top - 2, L->top - 2, L->top - 1, op - LUA_OPADD + TM_ADD); + L->top--; lua_unlock(L); - return i; } -LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { +LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { StkId o1, o2; int i; lua_lock(L); /* may call tag method */ - o1 = index2adr(L, index1); - o2 = index2adr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 - : luaV_lessthan(L, o1, o2); + o1 = index2addr(L, index1); + o2 = index2addr(L, index2); + if (o1 == luaO_nilobject || o2 == luaO_nilobject) + i = 0; + else switch (op) { + case LUA_OPEQ: i = equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); i = 0; + } lua_unlock(L); return i; } - LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { TValue n; - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(L, idx); if (tonumber(o, &n)) return nvalue(o); else @@ -322,7 +337,7 @@ LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { TValue n; - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(L, idx); if (tonumber(o, &n)) { lua_Integer res; lua_Number num = nvalue(o); @@ -335,13 +350,13 @@ LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(L, idx); return !l_isfalse(o); } LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); if (!ttisstring(o)) { lua_lock(L); /* `luaV_tostring' may create a new string */ if (!luaV_tostring(L, o)) { /* conversion failed? */ @@ -350,7 +365,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { return NULL; } luaC_checkGC(L); - o = index2adr(L, idx); /* previous call may reallocate the stack */ + o = index2addr(L, idx); /* previous call may reallocate the stack */ lua_unlock(L); } if (len != NULL) *len = tsvalue(o)->len; @@ -358,32 +373,25 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { } -LUA_API size_t lua_objlen (lua_State *L, int idx) { - StkId o = index2adr(L, idx); +LUA_API size_t lua_rawlen (lua_State *L, int idx) { + StkId o = index2addr(L, idx); switch (ttype(o)) { case LUA_TSTRING: return tsvalue(o)->len; case LUA_TUSERDATA: return uvalue(o)->len; case LUA_TTABLE: return luaH_getn(hvalue(o)); - case LUA_TNUMBER: { - size_t l; - lua_lock(L); /* `luaV_tostring' may create a new string */ - l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); - lua_unlock(L); - return l; - } default: return 0; } } LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; } LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); switch (ttype(o)) { case LUA_TUSERDATA: return (rawuvalue(o) + 1); case LUA_TLIGHTUSERDATA: return pvalue(o); @@ -393,13 +401,13 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) { LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); return (!ttisthread(o)) ? NULL : thvalue(o); } LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); switch (ttype(o)) { case LUA_TTABLE: return hvalue(o); case LUA_TFUNCTION: return clvalue(o); @@ -442,20 +450,25 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { } -LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { +LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { + TString *ts; lua_lock(L); luaC_checkGC(L); - setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); + ts = luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); api_incr_top(L); lua_unlock(L); + return getstr(ts); } -LUA_API void lua_pushstring (lua_State *L, const char *s) { - if (s == NULL) +LUA_API const char *lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) { lua_pushnil(L); + return NULL; + } else - lua_pushlstring(L, s, strlen(s)); + return lua_pushlstring(L, s, strlen(s)); } @@ -486,8 +499,9 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { Closure *cl; lua_lock(L); - luaC_checkGC(L); api_checknelems(L, n); + api_check(L, n <= UCHAR_MAX, "upvalue index too large"); + luaC_checkGC(L); cl = luaF_newCclosure(L, n, getcurrenv(L)); cl->c.f = fn; L->top -= n; @@ -534,7 +548,7 @@ LUA_API int lua_pushthread (lua_State *L) { LUA_API void lua_gettable (lua_State *L, int idx) { StkId t; lua_lock(L); - t = index2adr(L, idx); + t = index2addr(L, idx); api_checkvalidindex(L, t); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); @@ -543,13 +557,12 @@ LUA_API void lua_gettable (lua_State *L, int idx) { LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { StkId t; - TValue key; lua_lock(L); - t = index2adr(L, idx); + t = index2addr(L, idx); api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_gettable(L, t, &key, L->top); + setsvalue2s(L, L->top, luaS_new(L, k)); api_incr_top(L); + luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); } @@ -557,8 +570,8 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { LUA_API void lua_rawget (lua_State *L, int idx) { StkId t; lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); lua_unlock(L); } @@ -567,19 +580,23 @@ LUA_API void lua_rawget (lua_State *L, int idx) { LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { StkId o; lua_lock(L); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(o), n)); api_incr_top(L); lua_unlock(L); } LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + Table *t; lua_lock(L); luaC_checkGC(L); - sethvalue(L, L->top, luaH_new(L, narray, nrec)); + t = luaH_new(L); + sethvalue(L, L->top, t); api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); lua_unlock(L); } @@ -589,7 +606,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { Table *mt = NULL; int res; lua_lock(L); - obj = index2adr(L, objindex); + obj = index2addr(L, objindex); switch (ttype(obj)) { case LUA_TTABLE: mt = hvalue(obj)->metatable; @@ -616,7 +633,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { LUA_API void lua_getfenv (lua_State *L, int idx) { StkId o; lua_lock(L); - o = index2adr(L, idx); + o = index2addr(L, idx); api_checkvalidindex(L, o); switch (ttype(o)) { case LUA_TFUNCTION: @@ -625,9 +642,6 @@ LUA_API void lua_getfenv (lua_State *L, int idx) { case LUA_TUSERDATA: sethvalue(L, L->top, uvalue(o)->env); break; - case LUA_TTHREAD: - setobj2s(L, L->top, gt(thvalue(o))); - break; default: setnilvalue(L->top); break; @@ -646,7 +660,7 @@ LUA_API void lua_settable (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); - t = index2adr(L, idx); + t = index2addr(L, idx); api_checkvalidindex(L, t); luaV_settable(L, t, L->top - 2, L->top - 1); L->top -= 2; /* pop index and value */ @@ -656,14 +670,13 @@ LUA_API void lua_settable (lua_State *L, int idx) { LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { StkId t; - TValue key; lua_lock(L); api_checknelems(L, 1); - t = index2adr(L, idx); + t = index2addr(L, idx); api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_settable(L, t, &key, L->top - 1); - L->top--; /* pop value */ + setsvalue2s(L, L->top++, luaS_new(L, k)); + luaV_settable(L, t, L->top - 1, L->top - 2); + L->top -= 2; /* pop value and key */ lua_unlock(L); } @@ -672,8 +685,8 @@ LUA_API void lua_rawset (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); - t = index2adr(L, idx); - api_check(L, ttistable(t)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); luaC_barriert(L, hvalue(t), L->top-1); L->top -= 2; @@ -685,9 +698,9 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) { StkId o; lua_lock(L); api_checknelems(L, 1); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1); luaC_barriert(L, hvalue(o), L->top-1); L->top--; lua_unlock(L); @@ -699,12 +712,12 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { Table *mt; lua_lock(L); api_checknelems(L, 1); - obj = index2adr(L, objindex); + obj = index2addr(L, objindex); api_checkvalidindex(L, obj); if (ttisnil(L->top - 1)) mt = NULL; else { - api_check(L, ttistable(L->top - 1)); + api_check(L, ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } switch (ttype(obj)) { @@ -716,8 +729,10 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { } case LUA_TUSERDATA: { uvalue(obj)->metatable = mt; - if (mt) + if (mt) { luaC_objbarrier(L, rawuvalue(obj), mt); + luaC_checkfinalizer(L, rawuvalue(obj)); + } break; } default: { @@ -736,9 +751,9 @@ LUA_API int lua_setfenv (lua_State *L, int idx) { int res = 1; lua_lock(L); api_checknelems(L, 1); - o = index2adr(L, idx); + o = index2addr(L, idx); api_checkvalidindex(L, o); - api_check(L, ttistable(L->top - 1)); + api_check(L, ttistable(L->top - 1), "table expected"); switch (ttype(o)) { case LUA_TFUNCTION: clvalue(o)->c.env = hvalue(L->top - 1); @@ -746,9 +761,6 @@ LUA_API int lua_setfenv (lua_State *L, int idx) { case LUA_TUSERDATA: uvalue(o)->env = hvalue(L->top - 1); break; - case LUA_TTHREAD: - sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); - break; default: res = 0; break; @@ -765,21 +777,36 @@ LUA_API int lua_setfenv (lua_State *L, int idx) { */ -#define adjustresults(L,nres) \ - { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + "results from function overflow current stack size") + +LUA_API int lua_getctx (lua_State *L, int *ctx) { + if (L->ci->callstatus & CIST_YIELDED) { + if (ctx) *ctx = L->ci->u.c.ctx; + return L->ci->u.c.status; + } + else return LUA_OK; +} -#define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) - -LUA_API void lua_call (lua_State *L, int nargs, int nresults) { +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k) { StkId func; lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); checkresults(L, nargs, nresults); func = L->top - (nargs+1); - luaD_call(L, func, nresults); + if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults, 1); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_call(L, func, nresults, 0); /* just do the call */ adjustresults(L, nresults); lua_unlock(L); } @@ -797,68 +824,55 @@ struct CallS { /* data to `f_call' */ static void f_call (lua_State *L, void *ud) { struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults); + luaD_call(L, c->func, c->nresults, 0); } -LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { +LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k) { struct CallS c; int status; ptrdiff_t func; lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); checkresults(L, nargs, nresults); if (errfunc == 0) func = 0; else { - StkId o = index2adr(L, errfunc); + StkId o = index2addr(L, errfunc); api_checkvalidindex(L, o); func = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ - c.nresults = nresults; - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else { /* prepare continuation (call is already protected by 'resume') */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->u.c.oldtop = savestack(L, c.func); + ci->u.c.old_allowhook = L->allowhook; + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + /* mark that function may do error recovery */ + ci->callstatus |= CIST_YPCALL; + luaD_call(L, c.func, nresults, 1); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } adjustresults(L, nresults); lua_unlock(L); return status; } -/* -** Execute a protected C call. -*/ -struct CCallS { /* data to `f_Ccall' */ - lua_CFunction func; - void *ud; -}; - - -static void f_Ccall (lua_State *L, void *ud) { - struct CCallS *c = cast(struct CCallS *, ud); - Closure *cl; - cl = luaF_newCclosure(L, 0, getcurrenv(L)); - cl->c.f = c->func; - setclvalue(L, L->top, cl); /* push function */ - api_incr_top(L); - setpvalue(L->top, c->ud); /* push only argument */ - api_incr_top(L); - luaD_call(L, L->top - 2, 0); -} - - -LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { - struct CCallS c; - int status; - lua_lock(L); - c.func = func; - c.ud = ud; - status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); - lua_unlock(L); - return status; -} - - LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *chunkname) { ZIO z; @@ -879,7 +893,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { api_checknelems(L, 1); o = L->top - 1; if (isLfunction(o)) - status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); + status = luaU_dump(L, getproto(o), writer, data, 0); else status = 1; lua_unlock(L); @@ -911,7 +925,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { break; } case LUA_GCCOLLECT: { - luaC_fullgc(L); + luaC_fullgc(L, 0); break; } case LUA_GCCOUNT: { @@ -924,11 +938,9 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { break; } case LUA_GCSTEP: { + lu_mem oldts = g->GCthreshold; lu_mem a = (cast(lu_mem, data) << 10); - if (a <= g->totalbytes) - g->GCthreshold = g->totalbytes - a; - else - g->GCthreshold = 0; + g->GCthreshold = (a <= g->totalbytes) ? g->totalbytes - a : 0; while (g->GCthreshold <= g->totalbytes) { luaC_step(L); if (g->gcstate == GCSpause) { /* end of cycle? */ @@ -936,6 +948,8 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { break; } } + if (oldts == MAX_LUMEM) /* collector was stopped? */ + g->GCthreshold = oldts; /* keep it that way */ break; } case LUA_GCSETPAUSE: { @@ -948,6 +962,10 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { g->gcstepmul = data; break; } + case LUA_GCISRUNNING: { + res = (g->GCthreshold != MAX_LUMEM); + break; + } default: res = -1; /* invalid option */ } lua_unlock(L); @@ -974,8 +992,8 @@ LUA_API int lua_next (lua_State *L, int idx) { StkId t; int more; lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); more = luaH_next(L, hvalue(t), L->top - 1); if (more) { api_incr_top(L); @@ -992,8 +1010,7 @@ LUA_API void lua_concat (lua_State *L, int n) { api_checknelems(L, n); if (n >= 2) { luaC_checkGC(L); - luaV_concat(L, n, cast_int(L->top - L->base) - 1); - L->top -= (n-1); + luaV_concat(L, n); } else if (n == 0) { /* push empty string */ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); @@ -1004,6 +1021,16 @@ LUA_API void lua_concat (lua_State *L, int n) { } +LUA_API void lua_len (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); + lua_unlock(L); +} + + LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { lua_Alloc f; lua_lock(L); @@ -1049,7 +1076,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val) { Proto *p = f->l.p; if (!(1 <= n && n <= p->sizeupvalues)) return NULL; *val = f->l.upvals[n-1]->v; - return getstr(p->upvalues[n-1]); + return getstr(p->upvalues[n-1].name); } } @@ -1058,7 +1085,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val; lua_lock(L); - name = aux_upvalue(index2adr(L, funcindex), n, &val); + name = aux_upvalue(index2addr(L, funcindex), n, &val); if (name) { setobj2s(L, L->top, val); api_incr_top(L); @@ -1073,7 +1100,7 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { TValue *val; StkId fi; lua_lock(L); - fi = index2adr(L, funcindex); + fi = index2addr(L, funcindex); api_checknelems(L, 1); name = aux_upvalue(fi, n, &val); if (name) { @@ -1085,3 +1112,49 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { return name; } + +static UpVal **getupvalref (lua_State *L, int fidx, int n, Closure **pf) { + Closure *f; + Proto *p; + StkId fi = index2addr(L, fidx); + api_check(L, ttisfunction(fi), "function expected"); + f = clvalue(fi); + api_check(L, !f->c.isC, "Lua function expected"); + p = f->l.p; + api_check(L, (1 <= n && n <= p->sizeupvalues), "invalid upvalue index"); + if (pf) *pf = f; + return &f->l.upvals[n - 1]; /* get its upvalue pointer */ +} + + +LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { + Closure *f; + StkId fi = index2addr(L, fidx); + api_check(L, ttisfunction(fi), "function expected"); + f = clvalue(fi); + if (f->c.isC) { + api_check(L, 1 <= n && n <= f->c.nupvalues, "invalid upvalue index"); + return &f->c.upvalue[n - 1]; + } + else return *getupvalref(L, fidx, n, NULL); +} + + +LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, + int fidx2, int n2) { + Closure *f1; + UpVal **up1 = getupvalref(L, fidx1, n1, &f1); + UpVal **up2 = getupvalref(L, fidx2, n2, NULL); + *up1 = *up2; + luaC_objbarrier(L, f1, *up2); +} + + +#if defined(LUA_COMPAT_CPCALL) +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_CPCALL); + lua_pushlightuserdata(L, &func); + lua_pushlightuserdata(L, ud); + return lua_pcall(L, 2, 0, 0); +} +#endif |