diff options
Diffstat (limited to 'apps/plugins/lua/loslib.c')
| -rw-r--r-- | apps/plugins/lua/loslib.c | 223 |
1 files changed, 173 insertions, 50 deletions
diff --git a/apps/plugins/lua/loslib.c b/apps/plugins/lua/loslib.c index 6cb8c05..350e848 100644 --- a/apps/plugins/lua/loslib.c +++ b/apps/plugins/lua/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ +** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -19,31 +19,109 @@ #include "lualib.h" -static int os_pushresult (lua_State *L, int i, const char *filename) { - int en = errno; /* calls to Lua API may change this value */ - if (i) { - lua_pushboolean(L, 1); - return 1; - } +/* +** list of valid conversion specifiers for the 'strftime' function +*/ +#if !defined(LUA_STRFTIMEOPTIONS) + +#if !defined(LUA_USE_POSIX) +#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } +#else +#define LUA_STRFTIMEOPTIONS \ + { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ + "", "E", "cCxXyY", \ + "O", "deHImMSuUVwWy" } +#endif + +#endif + + + +/* +** By default, Lua uses tmpnam except when POSIX is available, where it +** uses mkstemp. +*/ +#if defined(LUA_USE_MKSTEMP) +#include <unistd.h> +#define LUA_TMPNAMBUFSIZE 32 +#define lua_tmpnam(b,e) { \ + strcpy(b, "/tmp/lua_XXXXXX"); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#elif !defined(lua_tmpnam) + +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } + +#endif + + +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ +#if defined(LUA_USE_GMTIME_R) + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#elif !defined(l_gmtime) + +#define l_gmtime(t,r) ((void)r, gmtime(t)) +#define l_localtime(t,r) ((void)r, localtime(t)) + +#endif + + + +static int os_execute (lua_State *L) { + const char *cmd = luaL_optstring(L, 1, NULL); + int stat = -1; + if (cmd != NULL) + return luaL_execresult(L, stat); else { - lua_pushnil(L); - lua_pushfstring(L, "%s: %s", filename, strerror(en)); - lua_pushinteger(L, en); - return 3; + lua_pushboolean(L, stat); /* true if there is a shell */ + return 1; } } static int os_remove (lua_State *L) { const char *filename = luaL_checkstring(L, 1); - return os_pushresult(L, rb->remove(filename) == 0, filename); + return luaL_fileresult(L, rb->remove(filename) == 0, filename); } static int os_rename (lua_State *L) { const char *fromname = luaL_checkstring(L, 1); const char *toname = luaL_checkstring(L, 2); - return os_pushresult(L, rb->rename(fromname, toname) == 0, fromname); + return luaL_fileresult(L, rb->rename(fromname, toname) == 0, NULL); +} + +#if 0 +static int os_tmpname (lua_State *L) { + char buff[LUA_TMPNAMBUFSIZE]; + int err; + lua_tmpnam(buff, err); + if (err) + return luaL_error(L, "unable to generate a unique filename"); + lua_pushstring(L, buff); + return 1; +} +#endif + + +static int os_getenv (lua_State *L) { + lua_pushnil(L); + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, 0); + return 1; } @@ -67,7 +145,6 @@ static void setboolfield (lua_State *L, const char *key, int value) { lua_setfield(L, -2, key); } -#if CONFIG_RTC static int getboolfield (lua_State *L, const char *key) { int res; lua_getfield(L, -1, key); @@ -78,11 +155,10 @@ static int getboolfield (lua_State *L, const char *key) { static int getfield (lua_State *L, const char *key, int d) { - int res; + int res, isnum; lua_getfield(L, -1, key); - if (lua_isnumber(L, -1)) - res = (int)lua_tointeger(L, -1); - else { + res = (int)lua_tointegerx(L, -1, &isnum); + if (!isnum) { if (d < 0) return luaL_error(L, "field " LUA_QS " missing in date table", key); res = d; @@ -90,22 +166,42 @@ static int getfield (lua_State *L, const char *key, int d) { lua_pop(L, 1); return res; } -#endif + + +static const char *checkoption (lua_State *L, const char *conv, char *buff) { + static const char *const options[] = LUA_STRFTIMEOPTIONS; + unsigned int i; + for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { + if (*conv != '\0' && strchr(options[i], *conv) != NULL) { + buff[1] = *conv; + if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ + buff[2] = '\0'; /* end buffer */ + return conv + 1; + } + else if (*(conv + 1) != '\0' && + strchr(options[i + 1], *(conv + 1)) != NULL) { + buff[2] = *(conv + 1); /* valid two-char conversion specifier */ + buff[3] = '\0'; /* end buffer */ + return conv + 2; + } + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ +} static int os_date (lua_State *L) { const char *s = luaL_optstring(L, 1, "%c"); - time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, -#if CONFIG_RTC - rb->mktime(rb->get_time()) -#else - 0 -#endif - ); - struct tm *stm; - if (*s == '!') /* UTC? */ /* Rockbox doesn't support timezones */ + time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); + struct tm tmr, *stm; + if (*s == '!') { /* UTC? */ + stm = l_gmtime(&t, &tmr); s++; /* skip `!' */ - stm = gmtime(&t); + } + else + stm = l_localtime(&t, &tmr); if (stm == NULL) /* invalid date? */ lua_pushnil(L); else if (strcmp(s, "*t") == 0) { @@ -121,17 +217,17 @@ static int os_date (lua_State *L) { setboolfield(L, "isdst", stm->tm_isdst); } else { - char cc[3]; + char cc[4]; luaL_Buffer b; - cc[0] = '%'; cc[2] = '\0'; + cc[0] = '%'; luaL_buffinit(L, &b); - for (; *s; s++) { - if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ - luaL_addchar(&b, *s); + while (*s) { + if (*s != '%') /* no conversion specifier? */ + luaL_addchar(&b, *s++); else { size_t reslen; char buff[200]; /* should be big enough for any conversion result */ - cc[1] = *(++s); + s = checkoption(L, s + 1, cc); reslen = strftime(buff, sizeof(buff), cc, stm); luaL_addlstring(&b, buff, reslen); } @@ -141,11 +237,11 @@ static int os_date (lua_State *L) { return 1; } + static int os_time (lua_State *L) { - time_t t = -1; -#if CONFIG_RTC + time_t t; if (lua_isnoneornil(L, 1)) /* called without args? */ - t = rb->mktime(rb->get_time()); /* get current time */ + t = time(NULL); /* get current time */ else { struct tm ts; luaL_checktype(L, 1, LUA_TTABLE); @@ -157,9 +253,8 @@ static int os_time (lua_State *L) { ts.tm_mon = getfield(L, "month", -1) - 1; ts.tm_year = getfield(L, "year", -1) - 1900; ts.tm_isdst = getboolfield(L, "isdst"); - t = rb->mktime(&ts); + t = mktime(&ts); } -#endif if (t == (time_t)(-1)) lua_pushnil(L); else @@ -168,26 +263,54 @@ static int os_time (lua_State *L) { } +static int os_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + /* }====================================================== */ +#if 0 +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} +#endif + + static int os_exit (lua_State *L) { - exit(luaL_optint(L, 1, EXIT_SUCCESS)); - return EXIT_SUCCESS; /* never reached, surpress warning */ + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = luaL_optint(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; } + static const luaL_Reg syslib[] = { - //{"clock", os_clock}, + {"clock", os_clock}, {"date", os_date}, - //{"difftime", os_difftime}, - //{"execute", os_execute}, + {"difftime", os_difftime}, + {"execute", os_execute}, {"exit", os_exit}, - //{"getenv", os_getenv}, + {"getenv", os_getenv}, {"remove", os_remove}, {"rename", os_rename}, - //{"setlocale", os_setlocale}, + /*{"setlocale", os_setlocale},*/ {"time", os_time}, - //{"tmpname", os_tmpname}, + /*{"tmpname", os_tmpname},*/ {NULL, NULL} }; @@ -195,8 +318,8 @@ static const luaL_Reg syslib[] = { -LUALIB_API int luaopen_os (lua_State *L) { - luaL_register(L, LUA_OSLIBNAME, syslib); +LUAMOD_API int luaopen_os (lua_State *L) { + luaL_newlib(L, syslib); return 1; } |