LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { int status; CallInfo *ci; lua_lock(L); for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { level--; if (!(ci->state & CI_C)) /* Lua function? */ level -= ci->u.l.tailcalls; /* skip lost tail calls */ } if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */ else if (level < 0) { /* level is of a lost tail call */ status = 1; ar->i_ci = 0; } else { status = 1; ar->i_ci = ci - L->base_ci; } lua_unlock(L); return status; }
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { int status; CallInfo *ci; lua_lock(L); for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { level--; if (f_isLua(ci)) /* Lua function? */ level -= ci->tailcalls; /* skip lost tail calls */ } if (level == 0 && ci > L->base_ci) { /* level found? */ status = 1; ar->i_ci = cast_int(ci - L->base_ci); } else if (level < 0) { /* level is of a lost tail call? */ status = 1; ar->i_ci = 0; } else status = 0; /* no such level */ lua_unlock(L); return status; }
LUA_API const char * lua_setlocal(lua_State * L, const lua_Debug * ar, int n) { const char *name; CallInfo *ci; Proto *fp; lua_lock(L); name = NULL; ci = L->base_ci + ar->i_ci; fp = getluaproto(ci); L->top--; /* pop new value */ if (fp) { /* is a Lua function? */ name = luaF_getlocalname(fp, n, currentpc(ci)); if (!name || name[0] == '(') /* `(' starts private locals */ name = NULL; else setobjs2s(ci->base + (n - 1), L->top); } lua_unlock(L); return name; }
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { int status = 1; lua_lock(L); if (*what == '>') { StkId f = L->top - 1; if (!ttisfunction(f)) luaG_runerror(L, "value for `lua_getinfo' is not a function"); status = auxgetinfo(L, what + 1, ar, f, NULL); L->top--; /* pop function */ } else if (ar->i_ci != 0) { /* no tail call? */ CallInfo *ci = L->base_ci + ar->i_ci; lua_assert(ttisfunction(ci->base - 1)); status = auxgetinfo(L, what, ar, ci->base - 1, ci); } else info_tailcall(L, ar); if (strchr(what, 'f')) incr_top(L); lua_unlock(L); return status; }
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { const char *name; lua_lock(L); if (ar == NULL) { /* information about non-active function? */ if (!isLfunction(L->top - 1)) /* not a Lua function? */ name = NULL; else /* consider live variables at function start (parameters) */ name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); } else { /* active function; get information through 'ar' */ StkId pos = 0; /* to avoid warnings */ name = findlocal(L, ar->i_ci, n, &pos); if (name) { setobj2s(L, L->top, pos); api_incr_top(L); api_check(L, L->top <= L->ci->top); } } lua_unlock(L); return name; }
static void DumpEndianBlock(const void* b, size_t size, DumpState* D) { if (D->status==0) { lua_unlock(D->L); if (D->swap) { char* origSwapBuffer=luaZ_openspace(D->L,&D->b,size); char* swapBuffer = origSwapBuffer; char* p =(char*) b+size-1; while (p >= (char*)b) *swapBuffer++ = *p--; D->status=(*D->writer)(D->L,origSwapBuffer,size,D->data); } else { D->status=(*D->writer)(D->L,b,size,D->data); } lua_lock(D->L); } }
LUA_API void lua_arith (lua_State *L, int op) { StkId o1; /* 1st operand */ StkId o2; /* 2nd operand */ lua_lock(L); if (op != LUA_OPUNM) /* all other operations expect two operands */ api_checknelems(L, 2); else { /* for unary minus, add fake 2nd operand */ api_checknelems(L, 1); setobjs2s(L, L->top, L->top - 1); L->top++; } o1 = L->top - 2; o2 = L->top - 1; if (ttisnumber(o1) && ttisnumber(o2)) { setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); } else luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); L->top--; lua_unlock(L); }
LUA_API void lua_settop( lua_State *L, int idx ) { lua_lock(L); RtStackView& currentStackFrame = L->GetCurrentStackFrame(); if ( idx != 0 ) { stackOffset_t stackOffset = index2stackindex( L, idx ); stackOffset_t absoluteStackOffset = currentStackFrame.GetAbsoluteStackOffset( L, L->rtStack, stackOffset ); currentStackFrame.SetTopOffset( L, L->rtStack, absoluteStackOffset ); } else { currentStackFrame.Clear( L, L->rtStack ); } lua_unlock(L); }
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { int status; Closure *f = NULL; CallInfo *ci = NULL; void *plight = NULL; lua_lock(L); if (*what == '>') { StkId func = L->top - 1; luai_apicheck(L, ttisfunction(func) || ttislightfunction(func)); what++; /* skip the '>' */ if (ttisfunction(func)) f = clvalue(func); else plight = fvalue(func); L->top--; /* pop function */ } else if (ar->i_ci != 0) { /* no tail call? */ ci = L->base_ci + ar->i_ci; lua_assert(ttisfunction(ci->func) || ttislightfunction(ci->func)); if (ttisfunction(ci->func)) f = clvalue(ci->func); else plight = fvalue(ci->func); } status = auxgetinfo(L, what, ar, f, plight, ci); if (strchr(what, 'f')) { if (f != NULL) setclvalue(L, L->top, f) else if (plight != NULL) setfvalue(L->top, plight) else setnilvalue(L->top); incr_top(L); } if (strchr(what, 'L')) collectvalidlines(L, f); lua_unlock(L); return status; }
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); if (n == 0) { setfvalue(L->top, fn); } else { CClosure *cl; api_checknelems(L, n); api_check(n <= MAXUPVAL, "upvalue index too large"); luaC_checkGC(L); cl = luaF_newCclosure(L, n); cl->f = fn; L->top -= n; while (n--) { setobj2n(L, &cl->upvalue[n], L->top + n); /* does not need barrier because closure is white */ } setclCvalue(L, L->top, cl); } api_incr_top(L); lua_unlock(L); }
LUA_API int lua_setmetatable (lua_State *L, int objindex) { TObject *obj, *mt; int res = 1; lua_lock(L); api_checknelems(L, 1); obj = luaA_index(L, objindex); mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L); api_check(L, ttistable(mt)); switch (ttype(obj)) { case LUA_TTABLE: { #if LUA_REFCOUNT __AddRefDirect(hvalue(mt)); __ReleaseDirect(L, hvalue(obj)->metatable); #endif LUA_REFCOUNT hvalue(obj)->metatable = hvalue(mt); /* write barrier */ break; } case LUA_TUSERDATA: { #if LUA_REFCOUNT __AddRefDirect(hvalue(mt)); __ReleaseDirect(L, &uvalue(obj)->uv.metatable); #endif LUA_REFCOUNT uvalue(obj)->uv.metatable = hvalue(mt); /* write barrier */ break; } default: { res = 0; /* cannot set */ break; } } #if LUA_REFCOUNT setnilvalue(--L->top); #else !LUA_REFCOUNT L->top--; #endif LUA_REFCOUNT lua_unlock(L); return res; }
LUA_API int lua_setmetatable (lua_State *L, int objindex) { TValue *obj; Table *mt; lua_lock(L); api_checknelems(L, 1); obj = index2addr(L, objindex); api_checkvalidindex(L, obj); if (ttisnil(L->top - 1)) mt = NULL; else { api_check(L, ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } switch (ttypenv(obj)) { case LUA_TTABLE: { hvalue(obj)->metatable = mt; if (mt) luaC_objbarrierback(L, gcvalue(obj), mt); luaC_checkfinalizer(L, gcvalue(obj), mt); break; } case LUA_TUSERDATA: { uvalue(obj)->metatable = mt; if (mt) { luaC_objbarrier(L, rawuvalue(obj), mt); luaC_checkfinalizer(L, gcvalue(obj), mt); } break; } default: { G(L)->mt[ttypenv(obj)] = mt; break; } } L->top--; lua_unlock(L); return 1; }
LUA_API void lua_settop (lua_State *L, int idx) { lua_lock(L); if (idx >= 0) { api_check(L, idx <= L->stack_last - L->base); while (L->top < L->base + idx) setnilvalue(L->top++); L->top = L->base + idx; } else { #if LUA_REFCOUNT StkId origTop = L->top; int origIdx = idx; api_check(L, -(idx+1) <= (L->top - L->base)); while (++idx < 0) setnilvalue(--L->top); lua_assert(L->top == origTop + (origIdx + 1)); #else !LUA_REFCOUNT api_check(L, -(idx+1) <= (L->top - L->base)); L->top += idx+1; /* `subtract' index (index is negative) */ #endif LUA_REFCOUNT } lua_unlock(L); }
LUA_API void lua_close (lua_State *L) { L = G(L)->mainthread; /* only the main thread can be closed */ lua_lock(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ #if !LUA_EXT_RESUMABLEVM L->errfunc = 0; /* no error function during GC metamethods */ #endif /* LUA_EXT_RESUMABLEVM */ do { /* repeat until no more errors */ L->ci = L->base_ci; #if LUA_EXT_RESUMABLEVM L->ci->errfunc = 0; /* no error function during GC metamethods */ #endif /* LUA_EXT_RESUMABLEVM */ L->base = L->top = L->ci->base; #if LUA_EXT_RESUMABLEVM L->nCcalls = 0; #else L->nCcalls = L->baseCcalls = 0; #endif /* LUA_EXT_RESUMABLEVM */ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); lua_assert(G(L)->tmudata == NULL); luai_userstateclose(L); close_state(L); }
LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { StkId o1, o2; int i = 0; lua_lock(L); /* may call tag method */ o1 = index2addr(L, index1); o2 = index2addr(L, index2); if (isvalid(o1) && isvalid(o2)) { 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"); } } lua_unlock(L); return i; }
LUA_API void lua_pushboolean (lua_State *L, int b) { lua_lock(L); setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ api_incr_top(L); lua_unlock(L); }
LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); setnvalue(L->top, cast_num(n)); api_incr_top(L); lua_unlock(L); }
LUA_API void lua_pushnil (lua_State *L) { lua_lock(L); setnilvalue(L->top); api_incr_top(L); lua_unlock(L); }
LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); setobj2s(L, L->top, index2addr(L, idx)); api_incr_top(L); lua_unlock(L); }
LUA_API void lua_pushlwstring (lua_State *L, const lua_WChar *s, size_t len) { lua_lock(L); setwsvalue(L->top, luaS_newlwstr(L, s, len)); api_incr_top(L); lua_unlock(L); }
static void DumpBlock(const void* b, size_t size, DumpState* D) { lua_unlock(D->L); (*D->write)(D->L,b,size,D->data); lua_lock(D->L); }
LUA_API void lua_setglobal (lua_State *L, const char *name) { Table *reg = hvalue(&G(L)->l_registry); lua_lock(L); /* unlock done in 'auxsetstr' */ auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); }
LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); setivalue(L->top, n); api_incr_top(L); lua_unlock(L); }
LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); setfltvalue(L->top, n); api_incr_top(L); lua_unlock(L); }
LUA_API void lua_close (lua_State *L) { L = G(L)->mainthread; /* only the main thread can be closed */ lua_lock(L); close_state(L); }
LUA_API void luaclr_setbytecodeenabled (lua_State *L, int value) { lua_lock(L); lua_assert(value == 0 || value == 1); G(L)->readbytecode = value; lua_unlock(L); }
LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { lua_lock(L); return auxgetstr(L, index2addr(L, idx), k); }
LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { lua_lock(L); setpvalue(L->top, p); api_incr_top(L); lua_unlock(L); }
static int pmain(lua_State* L) { struct Smain* s = (struct Smain*)lua_touserdata(L, 1); int argc=s->argc; char** argv=s->argv; Proto* f; int scripts=0; int i; if (!lua_checkstack(L,argc)) fatal("too many input files"); lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ luaL_openlibs(L); /* open libraries */ lua_gc(L, LUA_GCRESTART, 0); /* compile each script from command line into a Lua function. */ for (i=0; i<argc; i++) { const char* filename=IS("-") ? NULL : argv[i]; if(IS("-L")) break; if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1)); scripts++; } /* compile each preload library from the command line into a Lua function. */ for (i=0; i<preloads; i++) { char* filename=preload_libs[i]; char* p; /* try loading library as if it is a normal file. */ if (luaL_loadfile(L,filename)!=0) { /* try pre-loading library with 'require' module loading system. */ lua_getglobal(L, "require"); lua_pushstring(L, filename); lua_pushboolean(L, 1); lua_call(L, 2, 1); if (lua_iscfunction(L, -1)) { /* make sure it is not a C-Function. */ lua_pop(L, 1); lua_pushfstring(L, "\nCan't preload C module: '%s'\n", filename); lua_concat(L, 2); /* accumulate with error from luaL_findfile */ fatal(lua_tostring(L,-1)); } if (!lua_isfunction(L, -1)) { /* did we get an error? */ lua_pushliteral(L, "\n"); lua_concat(L, 3); /* accumulate with error from luaL_findfile */ fatal(lua_tostring(L,-1)); } else { lua_remove(L, -2); /* remove error from luaL_findfile. */ } } else { /* convert filename into package name. */ p= filename + strlen(filename); for(;p >= filename; p--) { if(p[0] == '.') { /* Remove file extension. */ p[0] = '\0'; continue; } if(p[0] == '/') { /* Remove file path. */ preload_libs[i] = p+1; break; } } } } /* generate a new Lua function to combine all of the compiled scripts. */ f=combine(L, scripts); if (listing) luaU_print(f,listing>1); if (c_code && !parse_only) { FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); if (D==NULL) cannot("open"); lua_lock(L); slua_dumper_dump(D, output, L, f, stripping); lua_unlock(L); if (ferror(D)) cannot("write"); if (fclose(D)) cannot("close"); } if (dumping && !parse_only) { FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); if (D==NULL) cannot("open"); lua_lock(L); luaU_dump(L,f,writer,D,stripping); lua_unlock(L); if (ferror(D)) cannot("write"); if (fclose(D)) cannot("close"); } return 0; }
LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { lua_lock(L); /* unlock done in 'auxsetstr' */ auxsetstr(L, index2addr(L, idx), k); }