summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2009-05-27 22:48:50 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2009-05-27 22:48:50 +0000
commitb2581e143d7c9a564026fbe3bf4f471b2260fd0f (patch)
treef6a25e4d6626fa986da215db75f781b1d85bc2cc /apps
parent64595105b1e63eedcd0c47290cf6c0d5e7e4cd46 (diff)
downloadrockbox-b2581e143d7c9a564026fbe3bf4f471b2260fd0f.tar.gz
rockbox-b2581e143d7c9a564026fbe3bf4f471b2260fd0f.tar.bz2
rockbox-b2581e143d7c9a564026fbe3bf4f471b2260fd0f.zip
Lua: add support for os library
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21106 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/lua/README2
-rw-r--r--apps/plugins/lua/SOURCES3
-rw-r--r--apps/plugins/lua/gmtime.c58
-rw-r--r--apps/plugins/lua/loslib.c199
-rw-r--r--apps/plugins/lua/rockconf.h2
-rw-r--r--apps/plugins/lua/rocklua.c7
-rw-r--r--apps/plugins/lua/strftime.c130
7 files changed, 398 insertions, 3 deletions
diff --git a/apps/plugins/lua/README b/apps/plugins/lua/README
index 593aad2ee7..db6933f517 100644
--- a/apps/plugins/lua/README
+++ b/apps/plugins/lua/README
@@ -1,7 +1,9 @@
The following files are (with slight modifications for Rockbox) from dietlibc
version 0.31 which is licensed under the GPL version 2:
+ gmtime.c
strcspn.c
+ strftime.c
strncat.c
strpbrk.c
strtol.c
diff --git a/apps/plugins/lua/SOURCES b/apps/plugins/lua/SOURCES
index 3b9f9348bd..058b991417 100644
--- a/apps/plugins/lua/SOURCES
+++ b/apps/plugins/lua/SOURCES
@@ -11,6 +11,7 @@ llex.c
lmem.c
lobject.c
lopcodes.c
+loslib.c
lparser.c
lstate.c
lstring.c
@@ -24,7 +25,9 @@ lzio.c
rockaux.c
rocklib.c
rockmalloc.c
+gmtime.c
strcspn.c
+strftime.c
strncat.c
strpbrk.c
strtoul.c
diff --git a/apps/plugins/lua/gmtime.c b/apps/plugins/lua/gmtime.c
new file mode 100644
index 0000000000..f13c855de8
--- /dev/null
+++ b/apps/plugins/lua/gmtime.c
@@ -0,0 +1,58 @@
+#include <time.h>
+
+/* seconds per day */
+#define SPD 24*60*60
+
+/* days per month -- nonleap! */
+const short __spm[13] =
+ { 0,
+ (31),
+ (31+28),
+ (31+28+31),
+ (31+28+31+30),
+ (31+28+31+30+31),
+ (31+28+31+30+31+30),
+ (31+28+31+30+31+30+31),
+ (31+28+31+30+31+30+31+31),
+ (31+28+31+30+31+30+31+31+30),
+ (31+28+31+30+31+30+31+31+30+31),
+ (31+28+31+30+31+30+31+31+30+31+30),
+ (31+28+31+30+31+30+31+31+30+31+30+31),
+ };
+
+int __isleap(int year) {
+ /* every fourth year is a leap year except for century years that are
+ * not divisible by 400. */
+/* return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); */
+ return (!(year%4) && ((year%100) || !(year%400)));
+}
+
+struct tm *gmtime(const time_t *timep) {
+ static struct tm r;
+ time_t i;
+ register time_t work=*timep%(SPD);
+ r.tm_sec=work%60; work/=60;
+ r.tm_min=work%60; r.tm_hour=work/60;
+ work=*timep/(SPD);
+ r.tm_wday=(4+work)%7;
+ for (i=1970; ; ++i) {
+ register time_t k=__isleap(i)?366:365;
+ if (work>=k)
+ work-=k;
+ else
+ break;
+ }
+ r.tm_year=i-1900;
+ r.tm_yday=work;
+
+ r.tm_mday=1;
+ if (__isleap(i) && (work>58)) {
+ if (work==59) r.tm_mday=2; /* 29.2. */
+ work-=1;
+ }
+
+ for (i=11; i && (__spm[i]>work); --i) ;
+ r.tm_mon=i;
+ r.tm_mday+=work-__spm[i];
+ return &r;
+}
diff --git a/apps/plugins/lua/loslib.c b/apps/plugins/lua/loslib.c
new file mode 100644
index 0000000000..9d29e905e1
--- /dev/null
+++ b/apps/plugins/lua/loslib.c
@@ -0,0 +1,199 @@
+/*
+** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
+** Standard Operating System library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define loslib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#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;
+ }
+ else {
+ lua_pushnil(L);
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
+ lua_pushinteger(L, en);
+ return 3;
+ }
+}
+
+
+static int os_remove (lua_State *L) {
+ const char *filename = luaL_checkstring(L, 1);
+ return os_pushresult(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);
+}
+
+
+/*
+** {======================================================
+** Time/Date operations
+** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
+** wday=%w+1, yday=%j, isdst=? }
+** =======================================================
+*/
+
+static void setfield (lua_State *L, const char *key, int value) {
+ lua_pushinteger(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static void setboolfield (lua_State *L, const char *key, int value) {
+ if (value < 0) /* undefined? */
+ return; /* does not set field */
+ lua_pushboolean(L, value);
+ lua_setfield(L, -2, key);
+}
+
+static int getboolfield (lua_State *L, const char *key) {
+ int res;
+ lua_getfield(L, -1, key);
+ res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ return res;
+}
+
+
+static int getfield (lua_State *L, const char *key, int d) {
+ int res;
+ lua_getfield(L, -1, key);
+ if (lua_isnumber(L, -1))
+ res = (int)lua_tointeger(L, -1);
+ else {
+ if (d < 0)
+ return luaL_error(L, "field " LUA_QS " missing in date table", key);
+ res = d;
+ }
+ lua_pop(L, 1);
+ return res;
+}
+
+
+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 */
+ s++; /* skip `!' */
+ stm = gmtime(&t);
+ if (stm == NULL) /* invalid date? */
+ lua_pushnil(L);
+ else if (strcmp(s, "*t") == 0) {
+ lua_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];
+ luaL_Buffer b;
+ cc[0] = '%'; cc[2] = '\0';
+ luaL_buffinit(L, &b);
+ for (; *s; s++) {
+ if (*s != '%' || *(s + 1) == '\0') /* 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);
+ reslen = strftime(buff, sizeof(buff), cc, stm);
+ luaL_addlstring(&b, buff, reslen);
+ }
+ }
+ luaL_pushresult(&b);
+ }
+ return 1;
+}
+
+static int os_time (lua_State *L) {
+ time_t t = -1;
+#if CONFIG_RTC
+ if (lua_isnoneornil(L, 1)) /* called without args? */
+ t = rb->mktime(rb->get_time()); /* get current time */
+ else {
+ struct tm ts;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_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 = rb->mktime(&ts);
+ }
+#endif
+ if (t == (time_t)(-1))
+ lua_pushnil(L);
+ else
+ lua_pushnumber(L, (lua_Number)t);
+ return 1;
+}
+
+
+/* }====================================================== */
+
+
+static int os_exit (lua_State *L) {
+ exit(luaL_optint(L, 1, EXIT_SUCCESS));
+}
+
+static const luaL_Reg syslib[] = {
+ //{"clock", os_clock},
+ {"date", os_date},
+ //{"difftime", os_difftime},
+ //{"execute", os_execute},
+ {"exit", os_exit},
+ //{"getenv", os_getenv},
+ {"remove", os_remove},
+ {"rename", os_rename},
+ //{"setlocale", os_setlocale},
+ {"time", os_time},
+ //{"tmpname", os_tmpname},
+ {NULL, NULL}
+};
+
+/* }====================================================== */
+
+
+
+LUALIB_API int luaopen_os (lua_State *L) {
+ luaL_register(L, LUA_OSLIBNAME, syslib);
+ return 1;
+}
+
diff --git a/apps/plugins/lua/rockconf.h b/apps/plugins/lua/rockconf.h
index 7ae2245c3a..1b267c78e6 100644
--- a/apps/plugins/lua/rockconf.h
+++ b/apps/plugins/lua/rockconf.h
@@ -43,8 +43,10 @@
extern char curpath[MAX_PATH];
void *dlrealloc(void *ptr, size_t size);
void dlfree(void *ptr);
+struct tm *gmtime(const time_t *timep);
long strtol(const char *nptr, char **endptr, int base);
unsigned long strtoul(const char *str, char **endptr, int base);
+size_t strftime(char* dst, size_t max, const char* format, const struct tm* tm);
long floor(long x);
long pow(long x, long y);
diff --git a/apps/plugins/lua/rocklua.c b/apps/plugins/lua/rocklua.c
index 5360090cab..1162c026d1 100644
--- a/apps/plugins/lua/rocklua.c
+++ b/apps/plugins/lua/rocklua.c
@@ -30,9 +30,10 @@
PLUGIN_HEADER
static const luaL_Reg lualibs[] = {
- {"", luaopen_base},
- {LUA_TABLIBNAME, luaopen_table},
- {LUA_STRLIBNAME, luaopen_string},
+ {"", luaopen_base},
+ {LUA_TABLIBNAME, luaopen_table},
+ {LUA_STRLIBNAME, luaopen_string},
+ {LUA_OSLIBNAME, luaopen_os},
{LUA_ROCKLIBNAME, luaopen_rock},
{NULL, NULL}
};
diff --git a/apps/plugins/lua/strftime.c b/apps/plugins/lua/strftime.c
new file mode 100644
index 0000000000..df230f7bd0
--- /dev/null
+++ b/apps/plugins/lua/strftime.c
@@ -0,0 +1,130 @@
+#include <sys/types.h>
+#include <time.h>
+#include "plugin.h"
+
+static const char sweekdays [7] [4] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+static const char weekdays [7] [10] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+};
+static const char smonths [12] [4] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+static const char* months [12] = {
+ "January", "February", "March", "April", smonths[5-1], "June",
+ "July", "August", "September", "October", "November", "December"
+};
+static const char ampm [4] [3] = {
+ "am", "pm",
+ "AM", "PM"
+};
+
+static void i2a ( char* dest,unsigned long x )
+{
+ int div = 10;
+ *dest++ = x/div + '0';
+ *dest++ = x%div + '0';
+ *dest++ = '\0';
+}
+
+size_t strftime ( char* dst, size_t max, const char* format, const struct tm* tm )
+{
+ char* p = dst;
+ const char* src;
+ unsigned long no;
+ char buf [5];
+
+ if (!max) return 0;
+ for ( ; *format != '\0'; format++ ) {
+ if (*format == '%') {
+ if (*++format == '%') {
+ *p++ = '%';
+ }
+ else
+again:
+ switch (*format) {
+// case '%': *p++ = '%'; break; // reduce size of jump table
+ case 'n': *p++ = '\n'; break;
+ case 't': *p++ = '\t'; break;
+ case 'O': case 'E': ++format; goto again;
+ case 'c': src = "%b %a %d %k:%M:%S %Z %Y"; goto _strf;
+ case 'r': src = "%I:%M:%S %p"; goto _strf;
+ case 'R': src = "%H:%M"; goto _strf;
+ case 'x': src = "%b %a %d"; goto _strf;
+ case 'X': src = "%k:%M:%S"; goto _strf;
+ case 'D': src = "%m/%d/%y"; goto _strf;
+ case 'T': src = "%H:%M:%S";
+ _strf: p += strftime (p, (size_t)(dst+max-p), src, tm); break;
+ case 'a': src = sweekdays [tm->tm_wday]; goto _str;
+ case 'A': src = weekdays [tm->tm_wday]; goto _str;
+ case 'h':
+ case 'b': src = smonths [tm->tm_mon]; goto _str;
+ case 'B': src = months [tm->tm_mon]; goto _str;
+ case 'p': src = ampm [tm->tm_hour > 12 ? 3 : 2]; goto _str;
+ case 'P': src = ampm [tm->tm_hour > 12 ? 1 : 0]; goto _str;
+ case 'C': no = tm->tm_year/100 + 19; goto _no;
+ case 'd': no = tm->tm_mday; goto _no;
+ case 'e': no = tm->tm_mday; goto _nos;
+ case 'H': no = tm->tm_hour; goto _no;
+ case 'I': no = tm->tm_hour % 12; goto _no;
+ case 'j': no = tm->tm_yday; goto _no;
+ case 'k': no = tm->tm_hour; goto _nos;
+ case 'l': no = tm->tm_hour % 12; goto _nos;
+ case 'm': no = tm->tm_mon + 1; goto _no;
+ case 'M': no = tm->tm_min; goto _no;
+ case 'S': no = tm->tm_sec; goto _no;
+ case 'u': no = tm->tm_wday ? tm->tm_wday : 7; goto _no;
+ case 'w': no = tm->tm_wday; goto _no;
+ case 'U': no = (tm->tm_yday - tm->tm_wday + 7) / 7; goto _no;
+ case 'W': no = (tm->tm_yday - (tm->tm_wday - 1 + 7) % 7 + 7) / 7; goto _no;
+ case 's': {
+ time_t t = rb->mktime((struct tm*)tm);
+ char buf[101];
+ char* c;
+ buf[100]=0;
+ for (c=buf+99; c>buf; --c) {
+ *c=(t%10)+'0';
+ t/=10;
+ if (!t) break;
+ }
+ src=c;
+ goto _str;
+ }
+ case 'Z':
+#ifdef WANT_TZFILE_PARSER
+ tzset(); src = tzname[0];
+#else
+ src = "[unknown timezone]";
+#endif
+ goto _str;
+ case 'Y': i2a ( buf+0, (unsigned int)(tm->tm_year / 100 + 19) );
+ i2a ( buf+2, (unsigned int)(tm->tm_year % 100) );
+ src = buf;
+ goto _str;
+ case 'y': no = tm->tm_year % 100; goto _no;
+ _no: i2a ( buf, no ); /* append number 'no' */
+ src = buf;
+ goto _str;
+ _nos: i2a ( buf, no ); /* the same, but '0'->' ' */
+ if (buf[0] == '0')
+ buf[0] = ' ';
+ src = buf;
+ _str: while (*src && p < dst+max) /* append string */
+ *p++ = *src++;
+ break;
+ };
+ } else {
+ *p++ = *format;
+ }
+
+ if (p >= dst+max)
+ break;
+ }
+
+ *p = '\0';
+ return p - dst;
+}
+
+