static int db_getmetatable (lv_State *L) { lvL_checkany(L, 1); if (!lv_getmetatable(L, 1)) { lv_pushnil(L); /* no metatable */ } return 1; }
static int os_pushresult (lv_State *L, int i, const char *filename) { int en = errno; /* calls to [L u a] API may change this value */ if (i) { lv_pushboolean(L, 1); return 1; } else { lv_pushnil(L); lv_pushfstring(L, "%s: %s", filename, strerror(en)); lv_pushinteger(L, en); return 3; } }
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 tremove (lv_State *L) { lv_clearFirstTableValue(L); int e = aux_getn(L, 1); int pos = lvL_optint(L, 2, e); if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ return 0; /* nothing to remove */ lvL_setn(L, 1, e - 1); /* t.n = n-1 */ lv_rawgeti(L, 1, pos); /* result = t[pos] */ for ( ; pos<e; pos++) { lv_rawgeti(L, 1, pos+1); lv_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ } lv_pushnil(L); lv_rawseti(L, 1, e); /* t[e] = nil */ return 1; }
static void hookf (lv_State *L, lv_Debug *ar) { static const char *const hooknames[] = {"call", "return", "line", "count", "tail return"}; lv_pushlightuserdata(L, (void *)&KEY_HOOK); lv_rawget(L, LV_REGISTRYINDEX); lv_pushlightuserdata(L, L); lv_rawget(L, -2); if (lv_isfunction(L, -1)) { lv_pushstring(L, hooknames[(int)ar->event]); if (ar->currentline >= 0) lv_pushinteger(L, ar->currentline); else lv_pushnil(L); lv_assert(lv_getinfo(L, "lS", ar)); lv_call(L, 2, 0); } }
static int os_date (lv_State *L) { const char *s = lvL_optstring(L, 1, "%c"); time_t t = lvL_opt(L, (time_t)lvL_checknumber, 2, time(NULL)); struct tm *stm; if (*s == '!') { /* UTC? */ stm = gmtime(&t); s++; /* skip `!' */ } else stm = localtime(&t); if (stm == NULL) /* invalid date? */ lv_pushnil(L); else if (strcmp(s, "*t") == 0) { lv_createtable(L, 0, 9); /* 9 = number of fields */ setfield(L, "sec", stm->tm_sec); setfield(L, "min", stm->tm_min); setfield(L, "hour", stm->tm_hour); setfield(L, "day", stm->tm_mday); setfield(L, "month", stm->tm_mon+1); setfield(L, "year", stm->tm_year+1900); setfield(L, "wday", stm->tm_wday+1); setfield(L, "yday", stm->tm_yday+1); setboolfield(L, "isdst", stm->tm_isdst); } else { char cc[3]; lvL_Buffer b; cc[0] = '%'; cc[2] = '\0'; lvL_buffinit(L, &b); for (; *s; s++) { if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ lvL_addchar(&b, *s); else { size_t reslen; char buff[200]; /* should be big enough for any conversion result */ cc[1] = *(++s); reslen = strftime(buff, sizeof(buff), cc, stm); lvL_addlstring(&b, buff, reslen); } } lvL_pushresult(&b); } return 1; }
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 os_time (lv_State *L) { time_t t; if (lv_isnoneornil(L, 1)) /* called without args? */ t = time(NULL); /* get current time */ else { struct tm ts; lvL_checktype(L, 1, LV_TTABLE); lv_settop(L, 1); /* make sure table is at the top */ ts.tm_sec = getfield(L, "sec", 0); ts.tm_min = getfield(L, "min", 0); ts.tm_hour = getfield(L, "hour", 12); ts.tm_mday = getfield(L, "day", -1); ts.tm_mon = getfield(L, "month", -1) - 1; ts.tm_year = getfield(L, "year", -1) - 1900; ts.tm_isdst = getboolfield(L, "isdst"); t = mktime(&ts); } if (t == (time_t)(-1)) lv_pushnil(L); else lv_pushnumber(L, (lv_Number)t); return 1; }