Path: blob/main/sys/contrib/openzfs/module/lua/lapi.c
48383 views
// SPDX-License-Identifier: MIT1/*2** $Id: lapi.c,v 2.171.1.1 2013/04/12 18:48:47 roberto Exp $3** Lua API4** See Copyright Notice in lua.h5*/678#define lapi_c9#define LUA_CORE1011#include <sys/lua/lua.h>1213#include "lapi.h"14#include "ldebug.h"15#include "ldo.h"16#include "lfunc.h"17#include "lgc.h"18#include "lmem.h"19#include "lobject.h"20#include "lstate.h"21#include "lstring.h"22#include "ltable.h"23#include "ltm.h"24#include "lvm.h"25262728const char lua_ident[] =29"$LuaVersion: " LUA_COPYRIGHT " $"30"$LuaAuthors: " LUA_AUTHORS " $";313233/* value at a non-valid index */34#define NONVALIDVALUE cast(TValue *, luaO_nilobject)3536/* corresponding test */37#define isvalid(o) ((o) != luaO_nilobject)3839/* test for pseudo index */40#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX)4142/* test for valid but not pseudo index */43#define isstackindex(i, o) (isvalid(o) && !ispseudo(i))4445#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index")4647#define api_checkstackindex(L, i, o) \48api_check(L, isstackindex(i, o), "index not in the stack")495051static TValue *index2addr (lua_State *L, int idx) {52CallInfo *ci = L->ci;53if (idx > 0) {54TValue *o = ci->func + idx;55api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index");56if (o >= L->top) return NONVALIDVALUE;57else return o;58}59else if (!ispseudo(idx)) { /* negative index */60api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");61return L->top + idx;62}63else if (idx == LUA_REGISTRYINDEX)64return &G(L)->l_registry;65else { /* upvalues */66idx = LUA_REGISTRYINDEX - idx;67api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");68if (ttislcf(ci->func)) /* light C function? */69return NONVALIDVALUE; /* it has no upvalues */70else {71CClosure *func = clCvalue(ci->func);72return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE;73}74}75}767778/*79** to be called by 'lua_checkstack' in protected mode, to grow stack80** capturing memory errors81*/82static void growstack (lua_State *L, void *ud) {83int size = *(int *)ud;84luaD_growstack(L, size);85}868788LUA_API int lua_checkstack (lua_State *L, int size) {89int res;90CallInfo *ci = L->ci;91lua_lock(L);92if (L->stack_last - L->top > size) /* stack large enough? */93res = 1; /* yes; check is OK */94else { /* no; need to grow stack */95int inuse = cast_int(L->top - L->stack) + EXTRA_STACK;96if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */97res = 0; /* no */98else /* try to grow stack */99res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK);100}101if (res && ci->top < L->top + size)102ci->top = L->top + size; /* adjust frame top */103lua_unlock(L);104return res;105}106107108LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {109int i;110if (from == to) return;111lua_lock(to);112api_checknelems(from, n);113api_check(from, G(from) == G(to), "moving among independent states");114api_check(from, to->ci->top - to->top >= n, "not enough elements to move");115from->top -= n;116for (i = 0; i < n; i++) {117setobj2s(to, to->top++, from->top + i);118}119lua_unlock(to);120}121122123LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {124lua_CFunction old;125lua_lock(L);126old = G(L)->panic;127G(L)->panic = panicf;128lua_unlock(L);129return old;130}131132133LUA_API const lua_Number *lua_version (lua_State *L) {134static const lua_Number version = LUA_VERSION_NUM;135if (L == NULL) return &version;136else return G(L)->version;137}138139140141/*142** basic stack manipulation143*/144145146/*147** convert an acceptable stack index into an absolute index148*/149LUA_API int lua_absindex (lua_State *L, int idx) {150return (idx > 0 || ispseudo(idx))151? idx152: cast_int(L->top - L->ci->func + idx);153}154155156LUA_API int lua_gettop (lua_State *L) {157return cast_int(L->top - (L->ci->func + 1));158}159160161LUA_API void lua_settop (lua_State *L, int idx) {162StkId func = L->ci->func;163lua_lock(L);164if (idx >= 0) {165api_check(L, idx <= L->stack_last - (func + 1), "new top too large");166while (L->top < (func + 1) + idx)167setnilvalue(L->top++);168L->top = (func + 1) + idx;169}170else {171api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");172L->top += idx+1; /* `subtract' index (index is negative) */173}174lua_unlock(L);175}176177178LUA_API void lua_remove (lua_State *L, int idx) {179StkId p;180lua_lock(L);181p = index2addr(L, idx);182api_checkstackindex(L, idx, p);183while (++p < L->top) setobjs2s(L, p-1, p);184L->top--;185lua_unlock(L);186}187188189LUA_API void lua_insert (lua_State *L, int idx) {190StkId p;191StkId q;192lua_lock(L);193p = index2addr(L, idx);194api_checkstackindex(L, idx, p);195for (q = L->top; q > p; q--) /* use L->top as a temporary */196setobjs2s(L, q, q - 1);197setobjs2s(L, p, L->top);198lua_unlock(L);199}200201202static void moveto (lua_State *L, TValue *fr, int idx) {203TValue *to = index2addr(L, idx);204api_checkvalidindex(L, to);205setobj(L, to, fr);206if (idx < LUA_REGISTRYINDEX) /* function upvalue? */207luaC_barrier(L, clCvalue(L->ci->func), fr);208/* LUA_REGISTRYINDEX does not need gc barrier209(collector revisits it before finishing collection) */210}211212213LUA_API void lua_replace (lua_State *L, int idx) {214lua_lock(L);215api_checknelems(L, 1);216moveto(L, L->top - 1, idx);217L->top--;218lua_unlock(L);219}220221222LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {223TValue *fr;224lua_lock(L);225fr = index2addr(L, fromidx);226moveto(L, fr, toidx);227lua_unlock(L);228}229230231LUA_API void lua_pushvalue (lua_State *L, int idx) {232lua_lock(L);233setobj2s(L, L->top, index2addr(L, idx));234api_incr_top(L);235lua_unlock(L);236}237238239240/*241** access functions (stack -> C)242*/243244245LUA_API int lua_type (lua_State *L, int idx) {246StkId o = index2addr(L, idx);247return (isvalid(o) ? ttypenv(o) : LUA_TNONE);248}249250251LUA_API const char *lua_typename (lua_State *L, int t) {252UNUSED(L);253if (t > 8 || t < 0)254return "internal_type_error";255return ttypename(t);256}257258259LUA_API int lua_iscfunction (lua_State *L, int idx) {260StkId o = index2addr(L, idx);261return (ttislcf(o) || (ttisCclosure(o)));262}263264265LUA_API int lua_isnumber (lua_State *L, int idx) {266TValue n;267const TValue *o = index2addr(L, idx);268return tonumber(o, &n);269}270271272LUA_API int lua_isstring (lua_State *L, int idx) {273int t = lua_type(L, idx);274return (t == LUA_TSTRING || t == LUA_TNUMBER);275}276277278LUA_API int lua_isuserdata (lua_State *L, int idx) {279const TValue *o = index2addr(L, idx);280return (ttisuserdata(o) || ttislightuserdata(o));281}282283284LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {285StkId o1 = index2addr(L, index1);286StkId o2 = index2addr(L, index2);287return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0;288}289290291LUA_API void lua_arith (lua_State *L, int op) {292StkId o1; /* 1st operand */293StkId o2; /* 2nd operand */294lua_lock(L);295if (op != LUA_OPUNM) /* all other operations expect two operands */296api_checknelems(L, 2);297else { /* for unary minus, add fake 2nd operand */298api_checknelems(L, 1);299setobjs2s(L, L->top, L->top - 1);300L->top++;301}302o1 = L->top - 2;303o2 = L->top - 1;304if (ttisnumber(o1) && ttisnumber(o2)) {305setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2)));306}307else308luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD));309L->top--;310lua_unlock(L);311}312313314LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {315StkId o1, o2;316int i = 0;317lua_lock(L); /* may call tag method */318o1 = index2addr(L, index1);319o2 = index2addr(L, index2);320if (isvalid(o1) && isvalid(o2)) {321switch (op) {322case LUA_OPEQ: i = equalobj(L, o1, o2); break;323case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;324case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;325default: api_check(L, 0, "invalid option");326}327}328lua_unlock(L);329return i;330}331332333LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) {334TValue n;335const TValue *o = index2addr(L, idx);336if (tonumber(o, &n)) {337if (isnum) *isnum = 1;338return nvalue(o);339}340else {341if (isnum) *isnum = 0;342return 0;343}344}345346347LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) {348TValue n;349const TValue *o = index2addr(L, idx);350if (tonumber(o, &n)) {351lua_Integer res;352lua_Number num = nvalue(o);353lua_number2integer(res, num);354if (isnum) *isnum = 1;355return res;356}357else {358if (isnum) *isnum = 0;359return 0;360}361}362363364LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) {365TValue n;366const TValue *o = index2addr(L, idx);367if (tonumber(o, &n)) {368lua_Unsigned res;369lua_Number num = nvalue(o);370lua_number2unsigned(res, num);371if (isnum) *isnum = 1;372return res;373}374else {375if (isnum) *isnum = 0;376return 0;377}378}379380381LUA_API int lua_toboolean (lua_State *L, int idx) {382const TValue *o = index2addr(L, idx);383return !l_isfalse(o);384}385386387LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {388StkId o = index2addr(L, idx);389if (!ttisstring(o)) {390lua_lock(L); /* `luaV_tostring' may create a new string */391if (!luaV_tostring(L, o)) { /* conversion failed? */392if (len != NULL) *len = 0;393lua_unlock(L);394return NULL;395}396luaC_checkGC(L);397o = index2addr(L, idx); /* previous call may reallocate the stack */398lua_unlock(L);399}400if (len != NULL) *len = tsvalue(o)->len;401return svalue(o);402}403404405LUA_API size_t lua_rawlen (lua_State *L, int idx) {406StkId o = index2addr(L, idx);407switch (ttypenv(o)) {408case LUA_TSTRING: return tsvalue(o)->len;409case LUA_TUSERDATA: return uvalue(o)->len;410case LUA_TTABLE: return luaH_getn(hvalue(o));411default: return 0;412}413}414415416LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {417StkId o = index2addr(L, idx);418if (ttislcf(o)) return fvalue(o);419else if (ttisCclosure(o))420return clCvalue(o)->f;421else return NULL; /* not a C function */422}423424425LUA_API void *lua_touserdata (lua_State *L, int idx) {426StkId o = index2addr(L, idx);427switch (ttypenv(o)) {428case LUA_TUSERDATA: return ((void *)(rawuvalue(o) + 1));429case LUA_TLIGHTUSERDATA: return pvalue(o);430default: return NULL;431}432}433434435LUA_API lua_State *lua_tothread (lua_State *L, int idx) {436StkId o = index2addr(L, idx);437return (!ttisthread(o)) ? NULL : thvalue(o);438}439440441LUA_API const void *lua_topointer (lua_State *L, int idx) {442StkId o = index2addr(L, idx);443switch (ttype(o)) {444case LUA_TTABLE: return hvalue(o);445case LUA_TLCL: return clLvalue(o);446case LUA_TCCL: return clCvalue(o);447case LUA_TLCF: return cast(void *, cast(uintptr_t, fvalue(o)));448case LUA_TTHREAD: return thvalue(o);449case LUA_TUSERDATA:450case LUA_TLIGHTUSERDATA:451return lua_touserdata(L, idx);452default: return NULL;453}454}455456457458/*459** push functions (C -> stack)460*/461462463LUA_API void lua_pushnil (lua_State *L) {464lua_lock(L);465setnilvalue(L->top);466api_incr_top(L);467lua_unlock(L);468}469470471LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {472lua_lock(L);473setnvalue(L->top, n);474luai_checknum(L, L->top,475luaG_runerror(L, "C API - attempt to push a signaling NaN"));476api_incr_top(L);477lua_unlock(L);478}479480481LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {482lua_lock(L);483setnvalue(L->top, cast_num(n));484api_incr_top(L);485lua_unlock(L);486}487488489LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) {490lua_Number n;491lua_lock(L);492n = lua_unsigned2number(u);493setnvalue(L->top, n);494api_incr_top(L);495lua_unlock(L);496}497498499LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {500TString *ts;501lua_lock(L);502luaC_checkGC(L);503ts = luaS_newlstr(L, s, len);504setsvalue2s(L, L->top, ts);505api_incr_top(L);506lua_unlock(L);507return getstr(ts);508}509510511LUA_API const char *lua_pushstring (lua_State *L, const char *s) {512if (s == NULL) {513lua_pushnil(L);514return NULL;515}516else {517TString *ts;518lua_lock(L);519luaC_checkGC(L);520ts = luaS_new(L, s);521setsvalue2s(L, L->top, ts);522api_incr_top(L);523lua_unlock(L);524return getstr(ts);525}526}527528529LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,530va_list argp) {531const char *ret;532lua_lock(L);533luaC_checkGC(L);534ret = luaO_pushvfstring(L, fmt, argp);535lua_unlock(L);536return ret;537}538539540LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {541const char *ret;542va_list argp;543lua_lock(L);544luaC_checkGC(L);545va_start(argp, fmt);546ret = luaO_pushvfstring(L, fmt, argp);547va_end(argp);548lua_unlock(L);549return ret;550}551552553LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {554lua_lock(L);555if (n == 0) {556setfvalue(L->top, fn);557}558else {559Closure *cl;560api_checknelems(L, n);561api_check(L, n <= MAXUPVAL, "upvalue index too large");562luaC_checkGC(L);563cl = luaF_newCclosure(L, n);564cl->c.f = fn;565L->top -= n;566while (n--)567setobj2n(L, &cl->c.upvalue[n], L->top + n);568setclCvalue(L, L->top, cl);569}570api_incr_top(L);571lua_unlock(L);572}573574575LUA_API void lua_pushboolean (lua_State *L, int b) {576lua_lock(L);577setbvalue(L->top, (b != 0)); /* ensure that true is 1 */578api_incr_top(L);579lua_unlock(L);580}581582583LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {584lua_lock(L);585setpvalue(L->top, p);586api_incr_top(L);587lua_unlock(L);588}589590591LUA_API int lua_pushthread (lua_State *L) {592lua_lock(L);593setthvalue(L, L->top, L);594api_incr_top(L);595lua_unlock(L);596return (G(L)->mainthread == L);597}598599600601/*602** get functions (Lua -> stack)603*/604605606LUA_API void lua_getglobal (lua_State *L, const char *var) {607Table *reg = hvalue(&G(L)->l_registry);608const TValue *gt; /* global table */609lua_lock(L);610gt = luaH_getint(reg, LUA_RIDX_GLOBALS);611setsvalue2s(L, L->top++, luaS_new(L, var));612luaV_gettable(L, gt, L->top - 1, L->top - 1);613lua_unlock(L);614}615616617LUA_API void lua_gettable (lua_State *L, int idx) {618StkId t;619lua_lock(L);620t = index2addr(L, idx);621luaV_gettable(L, t, L->top - 1, L->top - 1);622lua_unlock(L);623}624625626LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {627StkId t;628lua_lock(L);629t = index2addr(L, idx);630setsvalue2s(L, L->top, luaS_new(L, k));631api_incr_top(L);632luaV_gettable(L, t, L->top - 1, L->top - 1);633lua_unlock(L);634}635636637LUA_API void lua_rawget (lua_State *L, int idx) {638StkId t;639lua_lock(L);640t = index2addr(L, idx);641api_check(L, ttistable(t), "table expected");642setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));643lua_unlock(L);644}645646647LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {648StkId t;649lua_lock(L);650t = index2addr(L, idx);651api_check(L, ttistable(t), "table expected");652setobj2s(L, L->top, luaH_getint(hvalue(t), n));653api_incr_top(L);654lua_unlock(L);655}656657658LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) {659StkId t;660TValue k;661lua_lock(L);662t = index2addr(L, idx);663api_check(L, ttistable(t), "table expected");664setpvalue(&k, cast(void *, p));665setobj2s(L, L->top, luaH_get(hvalue(t), &k));666api_incr_top(L);667lua_unlock(L);668}669670671LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {672Table *t;673lua_lock(L);674luaC_checkGC(L);675t = luaH_new(L);676sethvalue(L, L->top, t);677api_incr_top(L);678if (narray > 0 || nrec > 0)679luaH_resize(L, t, narray, nrec);680lua_unlock(L);681}682683684LUA_API int lua_getmetatable (lua_State *L, int objindex) {685const TValue *obj;686Table *mt = NULL;687int res;688lua_lock(L);689obj = index2addr(L, objindex);690switch (ttypenv(obj)) {691case LUA_TTABLE:692mt = hvalue(obj)->metatable;693break;694case LUA_TUSERDATA:695mt = uvalue(obj)->metatable;696break;697default:698mt = G(L)->mt[ttypenv(obj)];699break;700}701if (mt == NULL)702res = 0;703else {704sethvalue(L, L->top, mt);705api_incr_top(L);706res = 1;707}708lua_unlock(L);709return res;710}711712713LUA_API void lua_getuservalue (lua_State *L, int idx) {714StkId o;715lua_lock(L);716o = index2addr(L, idx);717api_check(L, ttisuserdata(o), "userdata expected");718if (uvalue(o)->env) {719sethvalue(L, L->top, uvalue(o)->env);720} else721setnilvalue(L->top);722api_incr_top(L);723lua_unlock(L);724}725726727/*728** set functions (stack -> Lua)729*/730731732LUA_API void lua_setglobal (lua_State *L, const char *var) {733Table *reg = hvalue(&G(L)->l_registry);734const TValue *gt; /* global table */735lua_lock(L);736api_checknelems(L, 1);737gt = luaH_getint(reg, LUA_RIDX_GLOBALS);738setsvalue2s(L, L->top++, luaS_new(L, var));739luaV_settable(L, gt, L->top - 1, L->top - 2);740L->top -= 2; /* pop value and key */741lua_unlock(L);742}743744745LUA_API void lua_settable (lua_State *L, int idx) {746StkId t;747lua_lock(L);748api_checknelems(L, 2);749t = index2addr(L, idx);750luaV_settable(L, t, L->top - 2, L->top - 1);751L->top -= 2; /* pop index and value */752lua_unlock(L);753}754755756LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {757StkId t;758lua_lock(L);759api_checknelems(L, 1);760t = index2addr(L, idx);761setsvalue2s(L, L->top++, luaS_new(L, k));762luaV_settable(L, t, L->top - 1, L->top - 2);763L->top -= 2; /* pop value and key */764lua_unlock(L);765}766767768LUA_API void lua_rawset (lua_State *L, int idx) {769StkId t;770lua_lock(L);771api_checknelems(L, 2);772t = index2addr(L, idx);773api_check(L, ttistable(t), "table expected");774setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);775invalidateTMcache(hvalue(t));776luaC_barrierback(L, gcvalue(t), L->top-1);777L->top -= 2;778lua_unlock(L);779}780781782LUA_API void lua_rawseti (lua_State *L, int idx, int n) {783StkId t;784lua_lock(L);785api_checknelems(L, 1);786t = index2addr(L, idx);787api_check(L, ttistable(t), "table expected");788luaH_setint(L, hvalue(t), n, L->top - 1);789luaC_barrierback(L, gcvalue(t), L->top-1);790L->top--;791lua_unlock(L);792}793794795LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {796StkId t;797TValue k;798lua_lock(L);799api_checknelems(L, 1);800t = index2addr(L, idx);801api_check(L, ttistable(t), "table expected");802setpvalue(&k, cast(void *, p));803setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1);804luaC_barrierback(L, gcvalue(t), L->top - 1);805L->top--;806lua_unlock(L);807}808809810LUA_API int lua_setmetatable (lua_State *L, int objindex) {811TValue *obj;812Table *mt;813lua_lock(L);814api_checknelems(L, 1);815obj = index2addr(L, objindex);816if (ttisnil(L->top - 1))817mt = NULL;818else {819api_check(L, ttistable(L->top - 1), "table expected");820mt = hvalue(L->top - 1);821}822switch (ttypenv(obj)) {823case LUA_TTABLE: {824hvalue(obj)->metatable = mt;825if (mt) {826luaC_objbarrierback(L, gcvalue(obj), mt);827luaC_checkfinalizer(L, gcvalue(obj), mt);828}829break;830}831case LUA_TUSERDATA: {832uvalue(obj)->metatable = mt;833if (mt) {834luaC_objbarrier(L, rawuvalue(obj), mt);835luaC_checkfinalizer(L, gcvalue(obj), mt);836}837break;838}839default: {840G(L)->mt[ttypenv(obj)] = mt;841break;842}843}844L->top--;845lua_unlock(L);846return 1;847}848849850LUA_API void lua_setuservalue (lua_State *L, int idx) {851StkId o;852lua_lock(L);853api_checknelems(L, 1);854o = index2addr(L, idx);855api_check(L, ttisuserdata(o), "userdata expected");856if (ttisnil(L->top - 1))857uvalue(o)->env = NULL;858else {859api_check(L, ttistable(L->top - 1), "table expected");860uvalue(o)->env = hvalue(L->top - 1);861luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));862}863L->top--;864lua_unlock(L);865}866867868/*869** `load' and `call' functions (run Lua code)870*/871872873#define checkresults(L,na,nr) \874api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \875"results from function overflow current stack size")876877878LUA_API int lua_getctx (lua_State *L, int *ctx) {879if (L->ci->callstatus & CIST_YIELDED) {880if (ctx) *ctx = L->ci->u.c.ctx;881return L->ci->u.c.status;882}883else return LUA_OK;884}885886887LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx,888lua_CFunction k) {889StkId func;890lua_lock(L);891api_check(L, k == NULL || !isLua(L->ci),892"cannot use continuations inside hooks");893api_checknelems(L, nargs+1);894api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");895checkresults(L, nargs, nresults);896func = L->top - (nargs+1);897if (k != NULL && L->nny == 0) { /* need to prepare continuation? */898L->ci->u.c.k = k; /* save continuation */899L->ci->u.c.ctx = ctx; /* save context */900luaD_call(L, func, nresults, 1); /* do the call */901}902else /* no continuation or no yieldable */903luaD_call(L, func, nresults, 0); /* just do the call */904adjustresults(L, nresults);905lua_unlock(L);906}907908909910/*911** Execute a protected call.912*/913struct CallS { /* data to `f_call' */914StkId func;915int nresults;916};917918919static void f_call (lua_State *L, void *ud) {920struct CallS *c = cast(struct CallS *, ud);921luaD_call(L, c->func, c->nresults, 0);922}923924925926LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,927int ctx, lua_CFunction k) {928struct CallS c;929int status;930ptrdiff_t func;931lua_lock(L);932api_check(L, k == NULL || !isLua(L->ci),933"cannot use continuations inside hooks");934api_checknelems(L, nargs+1);935api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");936checkresults(L, nargs, nresults);937if (errfunc == 0)938func = 0;939else {940StkId o = index2addr(L, errfunc);941api_checkstackindex(L, errfunc, o);942func = savestack(L, o);943}944c.func = L->top - (nargs+1); /* function to be called */945if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */946c.nresults = nresults; /* do a 'conventional' protected call */947status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);948}949else { /* prepare continuation (call is already protected by 'resume') */950CallInfo *ci = L->ci;951ci->u.c.k = k; /* save continuation */952ci->u.c.ctx = ctx; /* save context */953/* save information for error recovery */954ci->extra = savestack(L, c.func);955ci->u.c.old_allowhook = L->allowhook;956ci->u.c.old_errfunc = L->errfunc;957L->errfunc = func;958/* mark that function may do error recovery */959ci->callstatus |= CIST_YPCALL;960luaD_call(L, c.func, nresults, 1); /* do the call */961ci->callstatus &= ~CIST_YPCALL;962L->errfunc = ci->u.c.old_errfunc;963status = LUA_OK; /* if it is here, there were no errors */964}965adjustresults(L, nresults);966lua_unlock(L);967return status;968}969970971LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,972const char *chunkname, const char *mode) {973ZIO z;974int status;975lua_lock(L);976if (!chunkname) chunkname = "?";977luaZ_init(L, &z, reader, data);978status = luaD_protectedparser(L, &z, chunkname, mode);979if (status == LUA_OK) { /* no errors? */980LClosure *f = clLvalue(L->top - 1); /* get newly created function */981if (f->nupvalues == 1) { /* does it have one upvalue? */982/* get global table from registry */983Table *reg = hvalue(&G(L)->l_registry);984const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);985/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */986setobj(L, f->upvals[0]->v, gt);987luaC_barrier(L, f->upvals[0], gt);988}989}990lua_unlock(L);991return status;992}993994#if defined(LUA_USE_DUMP)995LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {996int status;997TValue *o;998lua_lock(L);999api_checknelems(L, 1);1000o = L->top - 1;1001if (isLfunction(o))1002status = luaU_dump(L, getproto(o), writer, data, 0);1003else1004status = 1;1005lua_unlock(L);1006return status;1007}1008#endif10091010LUA_API int lua_status (lua_State *L) {1011return L->status;1012}101310141015/*1016** Garbage-collection function1017*/10181019LUA_API int lua_gc (lua_State *L, int what, int data) {1020int res = 0;1021global_State *g;1022lua_lock(L);1023g = G(L);1024switch (what) {1025case LUA_GCSTOP: {1026g->gcrunning = 0;1027break;1028}1029case LUA_GCRESTART: {1030luaE_setdebt(g, 0);1031g->gcrunning = 1;1032break;1033}1034case LUA_GCCOLLECT: {1035luaC_fullgc(L, 0);1036break;1037}1038case LUA_GCCOUNT: {1039/* GC values are expressed in Kbytes: #bytes/2^10 */1040res = cast_int(gettotalbytes(g) >> 10);1041break;1042}1043case LUA_GCCOUNTB: {1044res = cast_int(gettotalbytes(g) & 0x3ff);1045break;1046}1047case LUA_GCSTEP: {1048if (g->gckind == KGC_GEN) { /* generational mode? */1049res = (g->GCestimate == 0); /* true if it will do major collection */1050luaC_forcestep(L); /* do a single step */1051}1052else {1053lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE;1054if (g->gcrunning)1055debt += g->GCdebt; /* include current debt */1056luaE_setdebt(g, debt);1057luaC_forcestep(L);1058if (g->gcstate == GCSpause) /* end of cycle? */1059res = 1; /* signal it */1060}1061break;1062}1063case LUA_GCSETPAUSE: {1064res = g->gcpause;1065g->gcpause = data;1066break;1067}1068case LUA_GCSETMAJORINC: {1069res = g->gcmajorinc;1070g->gcmajorinc = data;1071break;1072}1073case LUA_GCSETSTEPMUL: {1074res = g->gcstepmul;1075g->gcstepmul = data;1076break;1077}1078case LUA_GCISRUNNING: {1079res = g->gcrunning;1080break;1081}1082case LUA_GCGEN: { /* change collector to generational mode */1083luaC_changemode(L, KGC_GEN);1084break;1085}1086case LUA_GCINC: { /* change collector to incremental mode */1087luaC_changemode(L, KGC_NORMAL);1088break;1089}1090default: res = -1; /* invalid option */1091}1092lua_unlock(L);1093return res;1094}1095109610971098/*1099** miscellaneous functions1100*/110111021103LUA_API int lua_error (lua_State *L) {1104lua_lock(L);1105api_checknelems(L, 1);1106luaG_errormsg(L);1107/* code unreachable; will unlock when control actually leaves the kernel */1108return 0; /* to avoid warnings */1109}111011111112LUA_API int lua_next (lua_State *L, int idx) {1113StkId t;1114int more;1115lua_lock(L);1116t = index2addr(L, idx);1117api_check(L, ttistable(t), "table expected");1118more = luaH_next(L, hvalue(t), L->top - 1);1119if (more) {1120api_incr_top(L);1121}1122else /* no more elements */1123L->top -= 1; /* remove key */1124lua_unlock(L);1125return more;1126}112711281129LUA_API void lua_concat (lua_State *L, int n) {1130lua_lock(L);1131api_checknelems(L, n);1132if (n >= 2) {1133luaC_checkGC(L);1134luaV_concat(L, n);1135}1136else if (n == 0) { /* push empty string */1137setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));1138api_incr_top(L);1139}1140/* else n == 1; nothing to do */1141lua_unlock(L);1142}114311441145LUA_API void lua_len (lua_State *L, int idx) {1146StkId t;1147lua_lock(L);1148t = index2addr(L, idx);1149luaV_objlen(L, L->top, t);1150api_incr_top(L);1151lua_unlock(L);1152}115311541155LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {1156lua_Alloc f;1157lua_lock(L);1158if (ud) *ud = G(L)->ud;1159f = G(L)->frealloc;1160lua_unlock(L);1161return f;1162}116311641165LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {1166lua_lock(L);1167G(L)->ud = ud;1168G(L)->frealloc = f;1169lua_unlock(L);1170}117111721173LUA_API void *lua_newuserdata (lua_State *L, size_t size) {1174Udata *u;1175lua_lock(L);1176luaC_checkGC(L);1177u = luaS_newudata(L, size, NULL);1178setuvalue(L, L->top, u);1179api_incr_top(L);1180lua_unlock(L);1181return u + 1;1182}1183118411851186static const char *aux_upvalue (StkId fi, int n, TValue **val,1187GCObject **owner) {1188switch (ttype(fi)) {1189case LUA_TCCL: { /* C closure */1190CClosure *f = clCvalue(fi);1191if (!(1 <= n && n <= f->nupvalues)) return NULL;1192*val = &f->upvalue[n-1];1193if (owner) *owner = obj2gco(f);1194return "";1195}1196case LUA_TLCL: { /* Lua closure */1197LClosure *f = clLvalue(fi);1198TString *name;1199Proto *p = f->p;1200if (!(1 <= n && n <= p->sizeupvalues)) return NULL;1201*val = f->upvals[n-1]->v;1202if (owner) *owner = obj2gco(f->upvals[n - 1]);1203name = p->upvalues[n-1].name;1204return (name == NULL) ? "" : getstr(name);1205}1206default: return NULL; /* not a closure */1207}1208}120912101211LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {1212const char *name;1213TValue *val = NULL; /* to avoid warnings */1214lua_lock(L);1215name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL);1216if (name) {1217setobj2s(L, L->top, val);1218api_incr_top(L);1219}1220lua_unlock(L);1221return name;1222}122312241225LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {1226const char *name;1227TValue *val = NULL; /* to avoid warnings */1228GCObject *owner = NULL; /* to avoid warnings */1229StkId fi;1230lua_lock(L);1231fi = index2addr(L, funcindex);1232api_checknelems(L, 1);1233name = aux_upvalue(fi, n, &val, &owner);1234if (name) {1235L->top--;1236setobj(L, val, L->top);1237luaC_barrier(L, owner, L->top);1238}1239lua_unlock(L);1240return name;1241}124212431244static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {1245LClosure *f;1246StkId fi = index2addr(L, fidx);1247api_check(L, ttisLclosure(fi), "Lua function expected");1248f = clLvalue(fi);1249api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");1250if (pf) *pf = f;1251return &f->upvals[n - 1]; /* get its upvalue pointer */1252}125312541255LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {1256StkId fi = index2addr(L, fidx);1257switch (ttype(fi)) {1258case LUA_TLCL: { /* lua closure */1259return *getupvalref(L, fidx, n, NULL);1260}1261case LUA_TCCL: { /* C closure */1262CClosure *f = clCvalue(fi);1263api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");1264return &f->upvalue[n - 1];1265}1266default: {1267api_check(L, 0, "closure expected");1268return NULL;1269}1270}1271}127212731274LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,1275int fidx2, int n2) {1276LClosure *f1;1277UpVal **up1 = getupvalref(L, fidx1, n1, &f1);1278UpVal **up2 = getupvalref(L, fidx2, n2, NULL);1279*up1 = *up2;1280luaC_objbarrier(L, f1, *up2);1281}12821283EXPORT_SYMBOL(lua_absindex);1284EXPORT_SYMBOL(lua_atpanic);1285EXPORT_SYMBOL(lua_checkstack);1286EXPORT_SYMBOL(lua_close);1287EXPORT_SYMBOL(lua_createtable);1288EXPORT_SYMBOL(lua_error);1289EXPORT_SYMBOL(lua_getfield);1290EXPORT_SYMBOL(lua_gettable);1291EXPORT_SYMBOL(lua_gettop);1292EXPORT_SYMBOL(lua_isnumber);1293EXPORT_SYMBOL(lua_isstring);1294EXPORT_SYMBOL(lua_newstate);1295EXPORT_SYMBOL(lua_newuserdata);1296EXPORT_SYMBOL(lua_next);1297EXPORT_SYMBOL(lua_pcallk);1298EXPORT_SYMBOL(lua_pushboolean);1299EXPORT_SYMBOL(lua_pushcclosure);1300EXPORT_SYMBOL(lua_pushfstring);1301EXPORT_SYMBOL(lua_pushinteger);1302EXPORT_SYMBOL(lua_pushlightuserdata);1303EXPORT_SYMBOL(lua_pushnil);1304EXPORT_SYMBOL(lua_pushnumber);1305EXPORT_SYMBOL(lua_pushstring);1306EXPORT_SYMBOL(lua_pushvalue);1307EXPORT_SYMBOL(lua_pushvfstring);1308EXPORT_SYMBOL(lua_remove);1309EXPORT_SYMBOL(lua_replace);1310EXPORT_SYMBOL(lua_setfield);1311EXPORT_SYMBOL(lua_setglobal);1312EXPORT_SYMBOL(lua_sethook);1313EXPORT_SYMBOL(lua_setmetatable);1314EXPORT_SYMBOL(lua_settable);1315EXPORT_SYMBOL(lua_settop);1316EXPORT_SYMBOL(lua_toboolean);1317EXPORT_SYMBOL(lua_tointegerx);1318EXPORT_SYMBOL(lua_tolstring);1319EXPORT_SYMBOL(lua_tonumberx);1320EXPORT_SYMBOL(lua_touserdata);1321EXPORT_SYMBOL(lua_type);1322EXPORT_SYMBOL(lua_typename);132313241325