static int getboolfield (lv_State *L, const char *key) { int res; lv_getfield(L, -1, key); res = lv_isnil(L, -1) ? -1 : lv_toboolean(L, -1); lv_pop(L, 1); return res; }
int beginDebug( lv_State *L ) { lv_getglobal( L, "begin_debug" ); int error = lv_pcall( L, 0, 0, 0 ); if ( error ) { printf( "%s/n", lv_tostring( L, -1 ) ); lv_pop( L, 1 ); } return 0; }
static void gethooktable (lv_State *L) { lv_pushlightuserdata(L, (void *)&KEY_HOOK); lv_rawget(L, LV_REGISTRYINDEX); if (!lv_istable(L, -1)) { lv_pop(L, 1); lv_createtable(L, 0, 1); lv_pushlightuserdata(L, (void *)&KEY_HOOK); lv_pushvalue(L, -2); lv_rawset(L, LV_REGISTRYINDEX); } }
static int getfield (lv_State *L, const char *key, int d) { int res; lv_getfield(L, -1, key); if (lv_isnumber(L, -1)) res = (int)lv_tointeger(L, -1); else { if (d < 0) return lvL_error(L, "field " LV_QS " missing in date table", key); res = d; } lv_pop(L, 1); return res; }
static int db_errorfb (lv_State *L) { int level; int firstpart = 1; /* still before eventual `...' */ int arg; lv_State *L1 = getthread(L, &arg); lv_Debug ar; if (lv_isnumber(L, arg+2)) { level = (int)lv_tointeger(L, arg+2); lv_pop(L, 1); } else level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ if (lv_gettop(L) == arg) lv_pushliteral(L, ""); else if (!lv_isstring(L, arg+1)) return 1; /* message is not a string */ else lv_pushliteral(L, "\n"); lv_pushliteral(L, "调用栈:"); while (lv_getstack(L1, level++, &ar)) { if (level > LEVELS1 && firstpart) { /* no more than `LEVELS2' more levels? */ if (!lv_getstack(L1, level+LEVELS2, &ar)) level--; /* keep going */ else { lv_pushliteral(L, "\n\t..."); /* too many levels */ while (lv_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ level++; } firstpart = 0; continue; } lv_pushliteral(L, "\n\t"); lv_getinfo(L1, "Snl", &ar); lv_pushfstring(L, "%s:", ar.source); if (ar.currentline > 0) lv_pushfstring(L, "%d:", ar.currentline); if (*ar.namewhat != '\0') /* is there a name? */ lv_pushfstring(L, " in function " LV_QS, ar.name); else { if (*ar.what == 'm') /* main? */ lv_pushfstring(L, " in main chunk"); else if (*ar.what == 'C' || *ar.what == 't') lv_pushliteral(L, " ?"); /* C function or tail call */ else lv_pushfstring(L, " in function <%s:%d>", ar.source, ar.linedefined); } lv_concat(L, lv_gettop(L) - arg); } lv_concat(L, lv_gettop(L) - arg); return 1; }
static int sort_comp (lv_State *L, int a, int b) { if (!lv_isnil(L, 2)) { /* function? */ int res; lv_pushvalue(L, 2); lv_pushvalue(L, a-1); /* -1 to compensate function */ lv_pushvalue(L, b-2); /* -2 to compensate function and `a' */ lv_call(L, 2, 1); res = lv_toboolean(L, -1); lv_pop(L, 1); return res; } else /* a < b? */ return lv_lessthan(L, a, b); }
static int maxn (lv_State *L) { lv_clearFirstTableValue(L); lv_Number max = 0; lvL_checktype(L, 1, LV_TTABLE); lv_pushnil(L); /* first key */ while (lv_next(L, 1)) { lv_pop(L, 1); /* remove value */ if (lv_type(L, -1) == LV_TNUMBER) { lv_Number v = lv_tonumber(L, -1); if (v > max) max = v; } } lv_pushnumber(L, max); return 1; }
static int foreach (lv_State *L) { lv_clearFirstTableValue(L); lvL_checktype(L, 1, LV_TTABLE); lvL_checktype(L, 2, LV_TFUNCTION); lv_pushnil(L); /* first key */ while (lv_next(L, 1)) { lv_pushvalue(L, 2); /* function */ lv_pushvalue(L, -3); /* key */ lv_pushvalue(L, -3); /* value */ lv_call(L, 2, 1); if (!lv_isnil(L, -1)) return 1; lv_pop(L, 2); /* remove value and result */ } return 0; }
static int foreachi (lv_State *L) { lv_clearFirstTableValue(L); int i; int n = aux_getn(L, 1); lvL_checktype(L, 2, LV_TFUNCTION); for (i=1; i <= n; i++) { lv_pushvalue(L, 2); /* function */ lv_pushinteger(L, i); /* 1st argument */ lv_rawgeti(L, 1, i); /* 2nd argument */ lv_call(L, 2, 1); if (!lv_isnil(L, -1)) return 1; lv_pop(L, 1); /* remove nil result */ } return 0; }
static int db_sethook (lv_State *L) { int arg, mask, count; lv_Hook func; lv_State *L1 = getthread(L, &arg); if (lv_isnoneornil(L, arg+1)) { lv_settop(L, arg+1); func = NULL; mask = 0; count = 0; /* turn off hooks */ } else { const char *smask = lvL_checkstring(L, arg+2); lvL_checktype(L, arg+1, LV_TFUNCTION); count = lvL_optint(L, arg+3, 0); func = hookf; mask = makemask(smask, count); } gethooktable(L); lv_pushlightuserdata(L, L1); lv_pushvalue(L, arg+1); lv_rawset(L, -3); /* set new hook */ lv_pop(L, 1); /* remove hook table */ lv_sethook(L1, func, mask, count); /* set hooks */ return 0; }
static void auxsort (lv_State *L, int l, int u) { while (l < u) { /* for tail recursion */ int i, j; /* sort elements a[l], a[(l+u)/2] and a[u] */ lv_rawgeti(L, 1, l); lv_rawgeti(L, 1, u); if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ set2(L, l, u); /* swap a[l] - a[u] */ else lv_pop(L, 2); if (u-l == 1) break; /* only 2 elements */ i = (l+u)/2; lv_rawgeti(L, 1, i); lv_rawgeti(L, 1, l); if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ set2(L, i, l); else { lv_pop(L, 1); /* remove a[l] */ lv_rawgeti(L, 1, u); if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ set2(L, i, u); else lv_pop(L, 2); } if (u-l == 2) break; /* only 3 elements */ lv_rawgeti(L, 1, i); /* Pivot */ lv_pushvalue(L, -1); lv_rawgeti(L, 1, u-1); set2(L, i, u-1); /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ i = l; j = u-1; for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ /* repeat ++i until a[i] >= P */ while (lv_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { if (i>u) lvL_error(L, "invalid order function for sorting"); lv_pop(L, 1); /* remove a[i] */ } /* repeat --j until a[j] <= P */ while (lv_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { if (j<l) lvL_error(L, "invalid order function for sorting"); lv_pop(L, 1); /* remove a[j] */ } if (j<i) { lv_pop(L, 3); /* pop pivot, a[i], a[j] */ break; } set2(L, i, j); } lv_rawgeti(L, 1, u-1); lv_rawgeti(L, 1, i); set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ if (i-l < u-i) { j=l; i=i-1; l=i+2; } else { j=i+1; i=u; u=j-2; } auxsort(L, j, i); /* call recursively the smaller one */ } /* repeat the routine for the larger one */ }