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 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 void treatstackoption (lv_State *L, lv_State *L1, const char *fname) { if (L == L1) { lv_pushvalue(L, -2); lv_remove(L, -3); } else lv_xmove(L1, L, 1); lv_setfield(L, -2, fname); }
static int setn (lv_State *L) { lv_clearFirstTableValue(L); lvL_checktype(L, 1, LV_TTABLE); #ifndef lvL_setn lvL_setn(L, 1, lvL_checkint(L, 2)); #else lvL_error(L, LV_QL("setn") " is obsolete"); #endif lv_pushvalue(L, 1); return 1; }
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 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_getinfo (lv_State *L) { lv_Debug ar; int arg; lv_State *L1 = getthread(L, &arg); const char *options = lvL_optstring(L, arg+2, "flnSu"); if (lv_isnumber(L, arg+1)) { if (!lv_getstack(L1, (int)lv_tointeger(L, arg+1), &ar)) { lv_pushnil(L); /* level out of range */ return 1; } } else if (lv_isfunction(L, arg+1)) { lv_pushfstring(L, ">%s", options); options = lv_tostring(L, -1); lv_pushvalue(L, arg+1); lv_xmove(L, L1, 1); } else return lvL_argerror(L, arg+1, "function or level expected"); if (!lv_getinfo(L1, options, &ar)) return lvL_argerror(L, arg+2, "invalid option"); lv_createtable(L, 0, 2); if (strchr(options, 'S')) { 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')) settabsi(L, "currentline", ar.currentline); if (strchr(options, 'u')) settabsi(L, "nups", ar.nups); if (strchr(options, 'n')) { settabss(L, "name", ar.name); settabss(L, "namewhat", ar.namewhat); } if (strchr(options, 'L')) treatstackoption(L, L1, "activelines"); if (strchr(options, 'f')) treatstackoption(L, L1, "func"); return 1; /* return table */ }
static int db_getlocal (lv_State *L) { int arg; lv_State *L1 = getthread(L, &arg); lv_Debug ar; const char *name; if (!lv_getstack(L1, lvL_checkint(L, arg+1), &ar)) /* out of range? */ return lvL_argerror(L, arg+1, "level out of range"); name = lv_getlocal(L1, &ar, lvL_checkint(L, arg+2)); if (name) { lv_xmove(L1, L, 1); lv_pushstring(L, name); lv_pushvalue(L, -2); return 2; } else { lv_pushnil(L); return 1; } }
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 */ }
static int db_getregistry (lv_State *L) { lv_pushvalue(L, LV_REGISTRYINDEX); return 1; }