public static int lua_checkstack(lua_State L, int n) { int res; CallInfo ci = L.ci; lua_lock(L); imp.api_check(n >= 0, "negative 'n'"); if (L.stack_last - L.top > n) /* stack large enough? */ { res = 1; /* yes; check is OK */ } else /* no; need to grow stack */ { int inuse = L.top + imp.EXTRA_STACK; if (inuse > imp.LUAI_MAXSTACK - n) /* can grow without overflow? */ { res = 0; /* no */ } else /* try to grow stack */ { res = (imp.luaD_rawrunprotected(L, imp.growstack, n) == LUA_OK ? 1 : 0); } } if (res > 0 && ci.top < L.top + n) { ci.top = L.top + n; /* adjust frame top */ } lua_unlock(L); return(res); }
public static CallInfo luaE_extendCI(lua_State L) { CallInfo ci = luaM_newobject <CallInfo> (L); lua_assert(L.ci.next == null); L.ci.next = ci; ci.previous = L.ci; ci.next = null; return(ci); }
public static string findvararg(lua_State L, CallInfo ci, int n, ref int pos) { int nparam = clLvalue(L, ci.func).p.numparams; if (n >= ci.u.l.nbase - ci.func - nparam) { return(null); } else { pos = ci.func + nparam + n; return("(*vararg)"); } }
/* ** Checks whether value 'o' came from an upvalue. (That can only happen ** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on ** upvalues.) */ public static string getupvalname(lua_State L, CallInfo ci, TValue o, ref string name) { LClosure c = ci_func(L, ci); for (int i = 0; i < c.nupvalues; i++) { if (c.upvals[i].v == o) { name = upvalname(c.p, i); return("upvalue"); } } return(null); }
public static int lua_pcallk(lua_State L, int nargs, int nresults, int errfunc, long ctx, lua_KFunction k) { lua_lock(L); imp.api_check(k == null || imp.isLua(L.ci) == false, "cannot use continuations inside hooks"); imp.api_checknelems(L, nargs + 1); imp.api_check(L.status == LUA_OK, "cannot do calls on non-normal thread"); imp.checkresults(L, nargs, nresults); int func = 0; if (errfunc == 0) { func = 0; } else { TValue o = imp.index2addr(L, errfunc); imp.api_checkstackindex(errfunc, o); func = imp.savestack(L, errfunc); } CallS c = new CallS(); c.func = L.top - (nargs + 1); /* function to be called */ int status = 0; if (k == null && L.nny > 0) /* no continuation or no yieldable? */ { c.nresults = nresults; /* do a 'conventional' protected call */ status = imp.luaD_pcall(L, imp.f_call, c, imp.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.extra = imp.savestack(L, c.func); ci.u.c.old_errfunc = L.errfunc; L.errfunc = func; imp.setoah(ref ci.callstatus, L.allowhook); /* save value of 'allowhook' */ ci.callstatus |= imp.CIST_YPCALL; /* function can do error recovery */ imp.luaD_call(L, c.func, nresults, 1); /* do the call */ ci.callstatus = (byte)(ci.callstatus & (~imp.CIST_YPCALL)); L.errfunc = ci.u.c.old_errfunc; status = LUA_OK; /* if it is here, there were no errors */ } imp.adjustresults(L, nresults); lua_unlock(L); return(status); }
public static string varinfo(lua_State L, TValue o) { string name = null; CallInfo ci = L.ci; string kind = null; if (isLua(ci)) { kind = getupvalname(L, ci, o, ref name); if (kind == null && isinstatck(ci, o)) { // TODO : reg kind = getobjname(ci_func(L, ci).p, currentpc(L, ci), 0, ref name); } } return((kind != null) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""); }
/* ** free half of the CallInfo structures not in use by a thread */ public static void luaE_shrinkCI(lua_State L) { CallInfo ci = L.ci; while (ci.next != null) /* while there is 'next' */ { CallInfo next2 = ci.next.next; /* next's next */ if (next2 == null) { break; } luaM_free(L, ci.next); /* remove next */ ci.next = next2; /* remove 'next' from the list */ next2.previous = ci; ci = next2; } }
/* ** free all CallInfo structures not in use by a thread */ public static void luaE_freeCI(lua_State L) { CallInfo ci = L.ci; CallInfo next = ci.next; ci.next = null; while (true) { ci = next; if (ci == null) { break; } next = ci.next; luaM_free(L, ci); } }
public static void luaG_traceexec(lua_State L) { CallInfo ci = L.ci; byte mask = L.hookmask; bool counthook = ((mask & cc.LUA_MASKCOUNT) != 0 && L.hookcount == 0); if (counthook) { resethookcount(L); /* reset count */ } if ((ci.callstatus & CIST_HOOKYIELD) != 0) /* called hook last time? */ { ci.callstatus = (byte)(ci.callstatus & (~CIST_HOOKYIELD)); /* erase mark */ return; /* do not call hook again (VM yielded, so it did not move) */ } if (counthook) { luaD_hook(L, cc.LUA_HOOKCOUNT, -1); /* call count hook */ } if ((mask & cc.LUA_MASKLINE) != 0) { Proto p = ci_func(L, ci).p; int npc = pcRel(ci.u.l.savedpc, p); int newline = getfuncline(p, npc); if (npc == 0 || /* call linehook when enter a new function, */ ci.u.l.savedpc <= L.oldpc || /* when jump back (loop), or when */ newline != getfuncline(p, pcRel(L.oldpc, p))) /* enter a new line */ { luaD_hook(L, cc.LUA_HOOKLINE, newline); /* call line hook */ } } L.oldpc = ci.u.l.savedpc; if (L.status == cc.LUA_YIELD) /* did hook yield? */ { if (counthook) { L.hookcount = 1; /* undo decrement to zero */ } ci.u.l.savedpc--; /* undo increment (resume will increment it again) */ ci.callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ ci.func = L.top - 1; /* protect stack below results */ luaD_throw(L, cc.LUA_YIELD); } }
public static void stack_init(lua_State L1, lua_State L) { L1.stack = luaM_fullvector <TValue> (L, lstate.BASIC_STACK_SIZE); L1.stacksize = lstate.BASIC_STACK_SIZE; for (int i = 0; i < lstate.BASIC_STACK_SIZE; i++) { setnilvalue(L1.stack[i]); /* erase new stack */ } L1.top = 0; L1.stack_last = L1.stacksize - EXTRA_STACK; /* initialize first ci */ CallInfo ci = L1.base_ci; ci.next = null; ci.previous = null; ci.callstatus = 0; ci.func = L1.top; setnilvalue(L1.stack[L1.top++]); /* 'function' entry for this 'ci' */ ci.top = L1.top + cc.LUA_MINSTACK; L1.ci = ci; }
public static TValue index2addr(lua_State L, int idx) { CallInfo ci = L.ci; if (idx > 0) { api_check(idx <= ci.top - (ci.func + 1), "unacceptable index"); if (ci.func + idx >= L.top) { return(lapi.NONVALIDVALUE); } else { return(L.stack[ci.func + idx]); } } else if (ispseudo(idx) == false) /* negative index */ { api_check(idx != 0 && -idx <= L.top - (ci.func + 1), "invalid index"); return(L.stack[L.top + idx]); } else if (idx == cc.LUA_REGISTRYINDEX) { return(G(L).l_registry); } else /* upvalues */ { idx = cc.LUA_REGISTRYINDEX - idx; api_check(idx <= MAXUPVAL + 1, "upvalue index too large"); if (ttislcf(L.stack[ci.func])) /* light C function? */ { return(lapi.NONVALIDVALUE); /* it has no upvalues */ } else { CClosure func = clCvalue(L.stack[ci.func]); return((idx <= func.nupvalues) ? func.upvalue[idx - 1] : lapi.NONVALIDVALUE); } } }
public static string findlocal(lua_State L, CallInfo ci, int n, ref int pos) { string name = null; int sbase = 0; if (isLua(ci)) { if (n < 0) /* access to vararg values? */ { return(findvararg(L, ci, -n, ref pos)); } else { sbase = ci.u.l.nbase; name = luaF_getlocalname(ci_func(L, ci).p, n, currentpc(L, ci)); } } else { sbase = ci.func + 1; } if (name == null) /* no 'standard' name? */ { int limit = (ci == L.ci ? L.top : ci.next.func); if (limit - sbase >= n && n > 0) /* is 'n' inside 'ci' stack? */ { name = "(*temporary)"; /* generic name for any valid slot */ } else { return(null); /* no name */ } } pos = sbase + (n - 1); return(name); }
public static int auxgetinfo(lua_State L, string what, int index, lua_Debug ar, Closure f, CallInfo ci) { int status = 1; for (int i = index; i < what.Length; i++) { switch (what[i]) { case 'S': { funcinfo(ar, f); break; } case 'l': { ar.currentline = (ci != null && isLua(ci)) ? currentline(L, ci) : -1; break; } case 'u': { ar.nups = (byte)((f == null) ? 0 : f.c.nupvalues); if (ldebug.noLuaClosure(f)) { ar.isvararg = 1; ar.nparams = 0; } else { ar.isvararg = f.l.p.is_vararg; ar.nparams = f.l.p.numparams; } break; } case 't': { ar.istailcall = (byte)((ci != null) ? (ci.callstatus & CIST_TAIL) : 0); break; } case 'n': { /* calling function is a known Lua function? */ if (ci != null && ((ci.callstatus & CIST_TAIL) != 0) && isLua(ci.previous)) { ar.namewhat = getfuncname(L, ci.previous, ref ar.name); } else { ar.namewhat = null; } if (ar.namewhat == null) { ar.namewhat = ""; /* not found */ ar.name = null; } break; } case 'L': goto case 'f'; case 'f': /* handled by lua_getinfo */ break; default: { status = 0; /* invalid option */ break; } } } return(status); }
public lua_State() { base_ci = imp.luaM_newobject <CallInfo> (null); }
public static int currentpc(lua_State L, CallInfo ci) { lua_assert(isLua(ci)); return(pcRel(ci.u.l.savedpc, ci_func(L, ci).p)); }
/* }====================================================== */ /* ** The subtraction of two potentially unrelated pointers is ** not ISO C, but it should not crash a program; the subsequent ** checks are ISO C and ensure a correct result. */ public static bool isinstatck(CallInfo ci, TValue o) { // TODO return(false); }
public static int currentline(lua_State L, CallInfo ci) { return(getfuncline(ci_func(L, ci).p, currentpc(L, ci))); }
public static string getfuncname(lua_State L, CallInfo ci, ref string name) { TMS tm = (TMS)0; /* to avoid warnings */ Proto p = ci_func(L, ci).p; /* calling function */ int pc = currentpc(L, ci); /* calling instruction index */ uint i = p.code[pc]; /* calling instruction */ if ((ci.callstatus & CIST_HOOKED) != 0) /* was it called inside a hook? */ { name = "?"; return("hook"); } switch (GET_OPCODE(i)) { case OpCode.OP_CALL: goto case OpCode.OP_TAILCALL; case OpCode.OP_TAILCALL: /* get function name */ return(getobjname(p, pc, GETARG_A(i), ref name)); case OpCode.OP_TFORCALL: { /* for iterator */ name = "for iterator"; return("for iterator"); } /* all other instructions can call only through metamethods */ case OpCode.OP_SELF: goto case OpCode.OP_GETTABLE; case OpCode.OP_GETTABUP: goto case OpCode.OP_GETTABLE; case OpCode.OP_GETTABLE: tm = TMS.TM_INDEX; break; case OpCode.OP_SETTABUP: goto case OpCode.OP_SETTABLE; case OpCode.OP_SETTABLE: tm = TMS.TM_NEWINDEX; break; case OpCode.OP_ADD: goto case OpCode.OP_SHR; case OpCode.OP_SUB: goto case OpCode.OP_SHR; case OpCode.OP_MUL: goto case OpCode.OP_SHR; case OpCode.OP_MOD: goto case OpCode.OP_SHR; case OpCode.OP_POW: goto case OpCode.OP_SHR; case OpCode.OP_DIV: goto case OpCode.OP_SHR; case OpCode.OP_IDIV: goto case OpCode.OP_SHR; case OpCode.OP_BAND: goto case OpCode.OP_SHR; case OpCode.OP_BOR: goto case OpCode.OP_SHR; case OpCode.OP_BXOR: goto case OpCode.OP_SHR; case OpCode.OP_SHL: goto case OpCode.OP_SHR; case OpCode.OP_SHR: { int offset = GET_OPCODE(i) - OpCode.OP_ADD; /* ORDER OP */ tm = TMS.TM_ADD + offset; /* ORDER TM */ break; } case OpCode.OP_UNM: tm = TMS.TM_UNM; break; case OpCode.OP_BNOT: tm = TMS.TM_BNOT; break; case OpCode.OP_LEN: tm = TMS.TM_LEN; break; case OpCode.OP_CONCAT: tm = TMS.TM_CONCAT; break; case OpCode.OP_EQ: tm = TMS.TM_EQ; break; case OpCode.OP_LT: tm = TMS.TM_LT; break; case OpCode.OP_LE: tm = TMS.TM_LE; break; default: lua_assert(false); break; /* other instructions cannot call a function */ } name = getsstr(G(L).tmname[(int)tm]); return("metamethod"); }
/* Active Lua function (given call info) */ public static LClosure ci_func(lua_State L, CallInfo ci) { return(clLvalue(L, ci.func)); }
public const int CIST_HOOKYIELD = 1 << 6; /* last hook called yielded */ public static bool isLua(CallInfo ci) { return((ci.callstatus & CIST_LUA) != 0); }