/* ** {====================================================== ** Error-report functions ** ======================================================= */ public static int LinyeeLArgError(LinyeeState L, int narg, CharPtr extramsg) { LinyeeDebug ar = new LinyeeDebug(); if (LinyeeGetStack(L, 0, ref ar) == 0) /* no stack frame? */ { return(LinyeeLError(L, "bad argument #%d (%s)", narg, extramsg)); } LinyeeGetInfo(L, "n", ref ar); if (strcmp(ar.namewhat, "method") == 0) { narg--; /* do not count `self' */ if (narg == 0) /* error is in the self argument itself? */ { return(LinyeeLError(L, "calling " + LINYEE_QS + " on bad self ({1})", ar.name, extramsg)); } } if (ar.name == null) { ar.name = "?"; } return(LinyeeLError(L, "bad argument #%d to " + LINYEE_QS + " (%s)", narg, ar.name, extramsg)); }
public static int LinyeeGetStack(LinyeeState L, int level, ref LinyeeDebug ar) { int status; CallInfo ci; LinyeeLock(L); for (ci = L.ci; level > 0 && ci > L.base_ci[0]; CallInfo.Dec(ref ci)) { level--; if (FIsLinyee(ci)) /* Linyee function? */ { level -= ci.tailcalls; /* skip lost tail calls */ } } if (level == 0 && ci > L.base_ci[0]) /* level found? */ { status = 1; ar.i_ci = ci - L.base_ci[0]; } else if (level < 0) /* level is of a lost tail call? */ { status = 1; ar.i_ci = 0; } else { status = 0; /* no such level */ } LinyeeUnlock(L); return(status); }
private static int costatus(LinyeeState L, LinyeeState co) { if (L == co) { return(CO_RUN); } switch (LinyeeStatus(co)) { case LINYEE_YIELD: return(CO_SUS); case 0: { LinyeeDebug ar = new LinyeeDebug(); if (LinyeeGetStack(co, 0, ref ar) > 0) /* does it have frames? */ { return(CO_NOR); /* it is running */ } else if (LinyeeGetTop(co) == 0) { return(CO_DEAD); } else { return(CO_SUS); /* initial state */ } } default: /* some error occured */ return(CO_DEAD); } }
public static void LinyeeDCallHook(LinyeeState L, int event_, int line) { LinyeeHook hook = L.hook; if ((hook != null) && (L.allowhook != 0)) { ptrdiff_t top = SaveStack(L, L.top); ptrdiff_t ci_top = SaveStack(L, L.ci.top); LinyeeDebug ar = new LinyeeDebug(); ar.event_ = event_; ar.currentline = line; if (event_ == LINYEE_HOOKTAILRET) { ar.i_ci = 0; /* tail call; no debug information about it */ } else { ar.i_ci = L.ci - L.base_ci; } LinyeeDCheckStack(L, LINYEE_MINSTACK); /* ensure minimum stack size */ L.ci.top = L.top + LINYEE_MINSTACK; LinyeeAssert(L.ci.top <= L.stack_last); L.allowhook = 0; /* cannot call hooks inside a hook */ LinyeeUnlock(L); hook(L, ar); LinyeeLock(L); LinyeeAssert(L.allowhook == 0); L.allowhook = 1; L.ci.top = RestoreStack(L, ci_top); L.top = RestoreStack(L, top); } }
private static int DBGetLocal(LinyeeState L) { int arg; LinyeeState L1 = GetThread(L, out arg); LinyeeDebug ar = new LinyeeDebug(); CharPtr name; if (LinyeeGetStack(L1, LinyeeLCheckInt(L, arg + 1), ref ar) == 0) /* out of range? */ { return(LinyeeLArgError(L, arg + 1, "level out of range")); } name = LinyeeGetLocal(L1, ar, LinyeeLCheckInt(L, arg + 2)); if (name != null) { LinyeeXMove(L1, L, 1); LinyeePushString(L, name); LinyeePushValue(L, -2); return(2); } else { LinyeePushNil(L); return(1); } }
private static void InfoTailCall(LinyeeDebug ar) { ar.name = ar.namewhat = ""; ar.what = "tail"; ar.lastlinedefined = ar.linedefined = ar.currentline = -1; ar.source = "=(tail call)"; LinyeeOChunkID(ar.short_src, ar.source, LINYEE_IDSIZE); ar.nups = 0; }
public static CharPtr LinyeeGetLocal(LinyeeState L, LinyeeDebug ar, int n) { CallInfo ci = L.base_ci[ar.i_ci]; CharPtr name = FindLocal(L, ci, n); LinyeeLock(L); if (name != null) { LinyeeAPushObject(L, ci.base_[n - 1]); } LinyeeUnlock(L); return(name); }
public static CharPtr LinyeeSetLocal(LinyeeState L, LinyeeDebug ar, int n) { CallInfo ci = L.base_ci[ar.i_ci]; CharPtr name = FindLocal(L, ci, n); LinyeeLock(L); if (name != null) { SetObj2S(L, ci.base_[n - 1], L.top - 1); } StkId.Dec(ref L.top); /* pop value */ LinyeeUnlock(L); return(name); }
public static void LinyeeLWhere(LinyeeState L, int level) { LinyeeDebug ar = new LinyeeDebug(); if (LinyeeGetStack(L, level, ref ar) != 0) /* check function at level */ { LinyeeGetInfo(L, "Sl", ref ar); /* get info about it */ if (ar.currentline > 0) /* is there info? */ { LinyeePushFString(L, "%s:%d: ", ar.short_src, ar.currentline); return; } } LinyeePushLiteral(L, ""); /* else, no information available... */ }
private static int AuxGetInfo(LinyeeState L, CharPtr what, LinyeeDebug ar, Closure f, CallInfo ci) { int status = 1; if (f == null) { InfoTailCall(ar); return(status); } for (; what[0] != 0; what = what.next()) { switch (what[0]) { case 'S': { FuncInfo(ar, f); break; } case 'l': { ar.currentline = (ci != null) ? CurrentLine(L, ci) : -1; break; } case 'u': { ar.nups = f.c.nupvalues; break; } case 'n': { ar.namewhat = (ci != null) ? GetFuncName(L, ci, ref ar.name) : null; if (ar.namewhat == null) { ar.namewhat = ""; /* not found */ ar.name = null; } break; } case 'L': case 'f': /* handled by ly_getinfo */ break; default: status = 0; break; /* invalid option */ } } return(status); }
private static int DBSetLocal(LinyeeState L) { int arg; LinyeeState L1 = GetThread(L, out arg); LinyeeDebug ar = new LinyeeDebug(); if (LinyeeGetStack(L1, LinyeeLCheckInt(L, arg + 1), ref ar) == 0) /* out of range? */ { return(LinyeeLArgError(L, arg + 1, "level out of range")); } LinyeeLCheckAny(L, arg + 3); LinyeeSetTop(L, arg + 3); LinyeeXMove(L, L1, 1); LinyeePushString(L, LinyeeSetLocal(L1, ar, LinyeeLCheckInt(L, arg + 2))); return(1); }
private static void FuncInfo(LinyeeDebug ar, Closure cl) { if (cl.c.isC != 0) { ar.source = "=[C]"; ar.linedefined = -1; ar.lastlinedefined = -1; ar.what = "C"; } else { ar.source = GetStr(cl.l.p.source); ar.linedefined = cl.l.p.linedefined; ar.lastlinedefined = cl.l.p.lastlinedefined; ar.what = (ar.linedefined == 0) ? "main" : "Linyee"; } LinyeeOChunkID(ar.short_src, ar.source, LINYEE_IDSIZE); }
public static int LinyeeGetInfo(LinyeeState L, CharPtr what, ref LinyeeDebug ar) { int status; Closure f = null; CallInfo ci = null; LinyeeLock(L); if (what == '>') { StkId func = L.top - 1; luai_apicheck(L, TTIsFunction(func)); what = what.next(); /* skip the '>' */ f = CLValue(func); StkId.Dec(ref L.top); /* pop function */ } else if (ar.i_ci != 0) /* no tail call? */ { ci = L.base_ci[ar.i_ci]; LinyeeAssert(TTIsFunction(ci.func)); f = CLValue(ci.func); } status = AuxGetInfo(L, what, ar, f, ci); if (strchr(what, 'f') != null) { if (f == null) { SetNilValue(L.top); } else { SetCLValue(L, L.top, f); } IncrTop(L); } if (strchr(what, 'L') != null) { CollectValidLines(L, f); } LinyeeUnlock(L); return(status); }
private static void HookF(LinyeeState L, LinyeeDebug ar) { LinyeePushLightUserData(L, KEY_HOOK); LinyeeRawGet(L, LINYEE_REGISTRYINDEX); LinyeePushLightUserData(L, L); LinyeeRawGet(L, -2); if (LinyeeIsFunction(L, -1)) { LinyeePushString(L, hooknames[(int)ar.event_]); if (ar.currentline >= 0) { LinyeePushInteger(L, ar.currentline); } else { LinyeePushNil(L); } LinyeeAssert(LinyeeGetInfo(L, "lS", ref ar)); LinyeeCall(L, 2, 0); } }
private static void GetFunc(LinyeeState L, int opt) { if (LinyeeIsFunction(L, 1)) { LinyeePushValue(L, 1); } else { LinyeeDebug ar = new LinyeeDebug(); int level = (opt != 0) ? LinyeeLOptInt(L, 1, 1) : LinyeeLCheckInt(L, 1); LinyeeLArgCheck(L, level >= 0, 1, "level must be non-negative"); if (LinyeeGetStack(L, level, ref ar) == 0) { LinyeeLArgError(L, 1, "invalid level"); } LinyeeGetInfo(L, "f", ref ar); if (LinyeeIsNil(L, -1)) { LinyeeLError(L, "no function environment for tail call at level %d", level); } } }
static void lstop(LinyeeState L, LinyeeDebug ar) { Linyee.LinyeeSetHook(L, null, 0, 0); Linyee.LinyeeLError(L, $"{Resource.interrupted}{Resource.Keyboard21}"); }
public const int LEVELS2 = 10; /* size of the second part of the stack */ private static int DBErrorFB(LinyeeState L) { int level; bool firstpart = true; /* still before eventual `...' */ int arg; LinyeeState L1 = GetThread(L, out arg); LinyeeDebug ar = new LinyeeDebug(); if (LinyeeIsNumber(L, arg + 2) != 0) { level = (int)LinyeeToInteger(L, arg + 2); LinyeePop(L, 1); } else { level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ } if (LinyeeGetTop(L) == arg) { LinyeePushLiteral(L, ""); } else if (LinyeeIsString(L, arg + 1) == 0) { return(1); /* message is not a string */ } else { LinyeePushLiteral(L, "\n"); } LinyeePushLiteral(L, "stack traceback:"); while (LinyeeGetStack(L1, level++, ref ar) != 0) { if (level > LEVELS1 && firstpart) { /* no more than `LEVELS2' more levels? */ if (LinyeeGetStack(L1, level + LEVELS2, ref ar) == 0) { level--; /* keep going */ } else { LinyeePushLiteral(L, "\n\t..."); /* too many levels */ while (LinyeeGetStack(L1, level + LEVELS2, ref ar) != 0) /* find last levels */ { level++; } } firstpart = false; continue; } LinyeePushLiteral(L, "\n\t"); LinyeeGetInfo(L1, "Snl", ref ar); LinyeePushFString(L, "%s:", ar.short_src); if (ar.currentline > 0) { LinyeePushFString(L, "%d:", ar.currentline); } if (ar.namewhat != '\0') /* is there a name? */ { LinyeePushFString(L, " in function " + LINYEE_QS, ar.name); } else { if (ar.what == 'm') /* main? */ { LinyeePushFString(L, " in main chunk"); } else if (ar.what == 'C' || ar.what == 't') { LinyeePushLiteral(L, " ?"); /* C function or tail call */ } else { LinyeePushFString(L, " in function <%s:%d>", ar.short_src, ar.linedefined); } } LinyeeConcat(L, LinyeeGetTop(L) - arg); } LinyeeConcat(L, LinyeeGetTop(L) - arg); return(1); }
private static int DBGetInfo(LinyeeState L) { LinyeeDebug ar = new LinyeeDebug(); int arg; LinyeeState L1 = GetThread(L, out arg); CharPtr options = LinyeeLOptString(L, arg + 2, "flnSu"); if (LinyeeIsNumber(L, arg + 1) != 0) { if (LinyeeGetStack(L1, (int)LinyeeToInteger(L, arg + 1), ref ar) == 0) { LinyeePushNil(L); /* level out of range */ return(1); } } else if (LinyeeIsFunction(L, arg + 1)) { LinyeePushFString(L, ">%s", options); options = LinyeeToString(L, -1); LinyeePushValue(L, arg + 1); LinyeeXMove(L, L1, 1); } else { return(LinyeeLArgError(L, arg + 1, "function or level expected")); } if (LinyeeGetInfo(L1, options, ref ar) == 0) { return(LinyeeLArgError(L, arg + 2, "invalid option")); } LinyeeCreateTable(L, 0, 2); if (strchr(options, 'S') != null) { SetTabsS(L, "source", ar.source); SetTabsS(L, "short_src", ar.short_src); SetTabSI(L, "linedefined", ar.linedefined); SetTabSI(L, "lastlinedefined", ar.lastlinedefined); SetTabsS(L, "what", ar.what); } if (strchr(options, 'l') != null) { SetTabSI(L, "currentline", ar.currentline); } if (strchr(options, 'u') != null) { SetTabSI(L, "nups", ar.nups); } if (strchr(options, 'n') != null) { SetTabsS(L, "name", ar.name); SetTabsS(L, "namewhat", ar.namewhat); } if (strchr(options, 'L') != null) { TreatStackOption(L, L1, "activelines"); } if (strchr(options, 'f') != null) { TreatStackOption(L, L1, "func"); } return(1); /* return table */ }