summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 @@
1The following files are (with slight modifications for Rockbox) from dietlibc 1The following files are (with slight modifications for Rockbox) from dietlibc
2version 0.31 which is licensed under the GPL version 2: 2version 0.31 which is licensed under the GPL version 2:
3 3
4 gmtime.c
4 strcspn.c 5 strcspn.c
6 strftime.c
5 strncat.c 7 strncat.c
6 strpbrk.c 8 strpbrk.c
7 strtol.c 9 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
11lmem.c 11lmem.c
12lobject.c 12lobject.c
13lopcodes.c 13lopcodes.c
14loslib.c
14lparser.c 15lparser.c
15lstate.c 16lstate.c
16lstring.c 17lstring.c
@@ -24,7 +25,9 @@ lzio.c
24rockaux.c 25rockaux.c
25rocklib.c 26rocklib.c
26rockmalloc.c 27rockmalloc.c
28gmtime.c
27strcspn.c 29strcspn.c
30strftime.c
28strncat.c 31strncat.c
29strpbrk.c 32strpbrk.c
30strtoul.c 33strtoul.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 @@
1#include <time.h>
2
3/* seconds per day */
4#define SPD 24*60*60
5
6/* days per month -- nonleap! */
7const short __spm[13] =
8 { 0,
9 (31),
10 (31+28),
11 (31+28+31),
12 (31+28+31+30),
13 (31+28+31+30+31),
14 (31+28+31+30+31+30),
15 (31+28+31+30+31+30+31),
16 (31+28+31+30+31+30+31+31),
17 (31+28+31+30+31+30+31+31+30),
18 (31+28+31+30+31+30+31+31+30+31),
19 (31+28+31+30+31+30+31+31+30+31+30),
20 (31+28+31+30+31+30+31+31+30+31+30+31),
21 };
22
23int __isleap(int year) {
24 /* every fourth year is a leap year except for century years that are
25 * not divisible by 400. */
26/* return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); */
27 return (!(year%4) && ((year%100) || !(year%400)));
28}
29
30struct tm *gmtime(const time_t *timep) {
31 static struct tm r;
32 time_t i;
33 register time_t work=*timep%(SPD);
34 r.tm_sec=work%60; work/=60;
35 r.tm_min=work%60; r.tm_hour=work/60;
36 work=*timep/(SPD);
37 r.tm_wday=(4+work)%7;
38 for (i=1970; ; ++i) {
39 register time_t k=__isleap(i)?366:365;
40 if (work>=k)
41 work-=k;
42 else
43 break;
44 }
45 r.tm_year=i-1900;
46 r.tm_yday=work;
47
48 r.tm_mday=1;
49 if (__isleap(i) && (work>58)) {
50 if (work==59) r.tm_mday=2; /* 29.2. */
51 work-=1;
52 }
53
54 for (i=11; i && (__spm[i]>work); --i) ;
55 r.tm_mon=i;
56 r.tm_mday+=work-__spm[i];
57 return &r;
58}
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 @@
1/*
2** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
3** Standard Operating System library
4** See Copyright Notice in lua.h
5*/
6
7
8#include <errno.h>
9#include <stdlib.h>
10#include <string.h>
11#include <time.h>
12
13#define loslib_c
14#define LUA_LIB
15
16#include "lua.h"
17
18#include "lauxlib.h"
19#include "lualib.h"
20
21
22static int os_pushresult (lua_State *L, int i, const char *filename) {
23 int en = errno; /* calls to Lua API may change this value */
24 if (i) {
25 lua_pushboolean(L, 1);
26 return 1;
27 }
28 else {
29 lua_pushnil(L);
30 lua_pushfstring(L, "%s: %s", filename, strerror(en));
31 lua_pushinteger(L, en);
32 return 3;
33 }
34}
35
36
37static int os_remove (lua_State *L) {
38 const char *filename = luaL_checkstring(L, 1);
39 return os_pushresult(L, rb->remove(filename) == 0, filename);
40}
41
42
43static int os_rename (lua_State *L) {
44 const char *fromname = luaL_checkstring(L, 1);
45 const char *toname = luaL_checkstring(L, 2);
46 return os_pushresult(L, rb->rename(fromname, toname) == 0, fromname);
47}
48
49
50/*
51** {======================================================
52** Time/Date operations
53** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
54** wday=%w+1, yday=%j, isdst=? }
55** =======================================================
56*/
57
58static void setfield (lua_State *L, const char *key, int value) {
59 lua_pushinteger(L, value);
60 lua_setfield(L, -2, key);
61}
62
63static void setboolfield (lua_State *L, const char *key, int value) {
64 if (value < 0) /* undefined? */
65 return; /* does not set field */
66 lua_pushboolean(L, value);
67 lua_setfield(L, -2, key);
68}
69
70static int getboolfield (lua_State *L, const char *key) {
71 int res;
72 lua_getfield(L, -1, key);
73 res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
74 lua_pop(L, 1);
75 return res;
76}
77
78
79static int getfield (lua_State *L, const char *key, int d) {
80 int res;
81 lua_getfield(L, -1, key);
82 if (lua_isnumber(L, -1))
83 res = (int)lua_tointeger(L, -1);
84 else {
85 if (d < 0)
86 return luaL_error(L, "field " LUA_QS " missing in date table", key);
87 res = d;
88 }
89 lua_pop(L, 1);
90 return res;
91}
92
93
94static int os_date (lua_State *L) {
95 const char *s = luaL_optstring(L, 1, "%c");
96 time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2,
97#if CONFIG_RTC
98 rb->mktime(rb->get_time())
99#else
100 0
101#endif
102 );
103 struct tm *stm;
104 if (*s == '!') /* UTC? */ /* Rockbox doesn't support timezones */
105 s++; /* skip `!' */
106 stm = gmtime(&t);
107 if (stm == NULL) /* invalid date? */
108 lua_pushnil(L);
109 else if (strcmp(s, "*t") == 0) {
110 lua_createtable(L, 0, 9); /* 9 = number of fields */
111 setfield(L, "sec", stm->tm_sec);
112 setfield(L, "min", stm->tm_min);
113 setfield(L, "hour", stm->tm_hour);
114 setfield(L, "day", stm->tm_mday);
115 setfield(L, "month", stm->tm_mon+1);
116 setfield(L, "year", stm->tm_year+1900);
117 setfield(L, "wday", stm->tm_wday+1);
118 setfield(L, "yday", stm->tm_yday+1);
119 setboolfield(L, "isdst", stm->tm_isdst);
120 }
121 else {
122 char cc[3];
123 luaL_Buffer b;
124 cc[0] = '%'; cc[2] = '\0';
125 luaL_buffinit(L, &b);
126 for (; *s; s++) {
127 if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
128 luaL_addchar(&b, *s);
129 else {
130 size_t reslen;
131 char buff[200]; /* should be big enough for any conversion result */
132 cc[1] = *(++s);
133 reslen = strftime(buff, sizeof(buff), cc, stm);
134 luaL_addlstring(&b, buff, reslen);
135 }
136 }
137 luaL_pushresult(&b);
138 }
139 return 1;
140}
141
142static int os_time (lua_State *L) {
143 time_t t = -1;
144#if CONFIG_RTC
145 if (lua_isnoneornil(L, 1)) /* called without args? */
146 t = rb->mktime(rb->get_time()); /* get current time */
147 else {
148 struct tm ts;
149 luaL_checktype(L, 1, LUA_TTABLE);
150 lua_settop(L, 1); /* make sure table is at the top */
151 ts.tm_sec = getfield(L, "sec", 0);
152 ts.tm_min = getfield(L, "min", 0);
153 ts.tm_hour = getfield(L, "hour", 12);
154 ts.tm_mday = getfield(L, "day", -1);
155 ts.tm_mon = getfield(L, "month", -1) - 1;
156 ts.tm_year = getfield(L, "year", -1) - 1900;
157 ts.tm_isdst = getboolfield(L, "isdst");
158 t = rb->mktime(&ts);
159 }
160#endif
161 if (t == (time_t)(-1))
162 lua_pushnil(L);
163 else
164 lua_pushnumber(L, (lua_Number)t);
165 return 1;
166}
167
168
169/* }====================================================== */
170
171
172static int os_exit (lua_State *L) {
173 exit(luaL_optint(L, 1, EXIT_SUCCESS));
174}
175
176static const luaL_Reg syslib[] = {
177 //{"clock", os_clock},
178 {"date", os_date},
179 //{"difftime", os_difftime},
180 //{"execute", os_execute},
181 {"exit", os_exit},
182 //{"getenv", os_getenv},
183 {"remove", os_remove},
184 {"rename", os_rename},
185 //{"setlocale", os_setlocale},
186 {"time", os_time},
187 //{"tmpname", os_tmpname},
188 {NULL, NULL}
189};
190
191/* }====================================================== */
192
193
194
195LUALIB_API int luaopen_os (lua_State *L) {
196 luaL_register(L, LUA_OSLIBNAME, syslib);
197 return 1;
198}
199
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 @@
43extern char curpath[MAX_PATH]; 43extern char curpath[MAX_PATH];
44void *dlrealloc(void *ptr, size_t size); 44void *dlrealloc(void *ptr, size_t size);
45void dlfree(void *ptr); 45void dlfree(void *ptr);
46struct tm *gmtime(const time_t *timep);
46long strtol(const char *nptr, char **endptr, int base); 47long strtol(const char *nptr, char **endptr, int base);
47unsigned long strtoul(const char *str, char **endptr, int base); 48unsigned long strtoul(const char *str, char **endptr, int base);
49size_t strftime(char* dst, size_t max, const char* format, const struct tm* tm);
48long floor(long x); 50long floor(long x);
49long pow(long x, long y); 51long pow(long x, long y);
50 52
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 @@
30PLUGIN_HEADER 30PLUGIN_HEADER
31 31
32static const luaL_Reg lualibs[] = { 32static const luaL_Reg lualibs[] = {
33 {"", luaopen_base}, 33 {"", luaopen_base},
34 {LUA_TABLIBNAME, luaopen_table}, 34 {LUA_TABLIBNAME, luaopen_table},
35 {LUA_STRLIBNAME, luaopen_string}, 35 {LUA_STRLIBNAME, luaopen_string},
36 {LUA_OSLIBNAME, luaopen_os},
36 {LUA_ROCKLIBNAME, luaopen_rock}, 37 {LUA_ROCKLIBNAME, luaopen_rock},
37 {NULL, NULL} 38 {NULL, NULL}
38}; 39};
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 @@
1#include <sys/types.h>
2#include <time.h>
3#include "plugin.h"
4
5static const char sweekdays [7] [4] = {
6 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
7};
8static const char weekdays [7] [10] = {
9 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
10};
11static const char smonths [12] [4] = {
12 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
13 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
14};
15static const char* months [12] = {
16 "January", "February", "March", "April", smonths[5-1], "June",
17 "July", "August", "September", "October", "November", "December"
18};
19static const char ampm [4] [3] = {
20 "am", "pm",
21 "AM", "PM"
22};
23
24static void i2a ( char* dest,unsigned long x )
25{
26 int div = 10;
27 *dest++ = x/div + '0';
28 *dest++ = x%div + '0';
29 *dest++ = '\0';
30}
31
32size_t strftime ( char* dst, size_t max, const char* format, const struct tm* tm )
33{
34 char* p = dst;
35 const char* src;
36 unsigned long no;
37 char buf [5];
38
39 if (!max) return 0;
40 for ( ; *format != '\0'; format++ ) {
41 if (*format == '%') {
42 if (*++format == '%') {
43 *p++ = '%';
44 }
45 else
46again:
47 switch (*format) {
48// case '%': *p++ = '%'; break; // reduce size of jump table
49 case 'n': *p++ = '\n'; break;
50 case 't': *p++ = '\t'; break;
51 case 'O': case 'E': ++format; goto again;
52 case 'c': src = "%b %a %d %k:%M:%S %Z %Y"; goto _strf;
53 case 'r': src = "%I:%M:%S %p"; goto _strf;
54 case 'R': src = "%H:%M"; goto _strf;
55 case 'x': src = "%b %a %d"; goto _strf;
56 case 'X': src = "%k:%M:%S"; goto _strf;
57 case 'D': src = "%m/%d/%y"; goto _strf;
58 case 'T': src = "%H:%M:%S";
59 _strf: p += strftime (p, (size_t)(dst+max-p), src, tm); break;
60 case 'a': src = sweekdays [tm->tm_wday]; goto _str;
61 case 'A': src = weekdays [tm->tm_wday]; goto _str;
62 case 'h':
63 case 'b': src = smonths [tm->tm_mon]; goto _str;
64 case 'B': src = months [tm->tm_mon]; goto _str;
65 case 'p': src = ampm [tm->tm_hour > 12 ? 3 : 2]; goto _str;
66 case 'P': src = ampm [tm->tm_hour > 12 ? 1 : 0]; goto _str;
67 case 'C': no = tm->tm_year/100 + 19; goto _no;
68 case 'd': no = tm->tm_mday; goto _no;
69 case 'e': no = tm->tm_mday; goto _nos;
70 case 'H': no = tm->tm_hour; goto _no;
71 case 'I': no = tm->tm_hour % 12; goto _no;
72 case 'j': no = tm->tm_yday; goto _no;
73 case 'k': no = tm->tm_hour; goto _nos;
74 case 'l': no = tm->tm_hour % 12; goto _nos;
75 case 'm': no = tm->tm_mon + 1; goto _no;
76 case 'M': no = tm->tm_min; goto _no;
77 case 'S': no = tm->tm_sec; goto _no;
78 case 'u': no = tm->tm_wday ? tm->tm_wday : 7; goto _no;
79 case 'w': no = tm->tm_wday; goto _no;
80 case 'U': no = (tm->tm_yday - tm->tm_wday + 7) / 7; goto _no;
81 case 'W': no = (tm->tm_yday - (tm->tm_wday - 1 + 7) % 7 + 7) / 7; goto _no;
82 case 's': {
83 time_t t = rb->mktime((struct tm*)tm);
84 char buf[101];
85 char* c;
86 buf[100]=0;
87 for (c=buf+99; c>buf; --c) {
88 *c=(t%10)+'0';
89 t/=10;
90 if (!t) break;
91 }
92 src=c;
93 goto _str;
94 }
95 case 'Z':
96#ifdef WANT_TZFILE_PARSER
97 tzset(); src = tzname[0];
98#else
99 src = "[unknown timezone]";
100#endif
101 goto _str;
102 case 'Y': i2a ( buf+0, (unsigned int)(tm->tm_year / 100 + 19) );
103 i2a ( buf+2, (unsigned int)(tm->tm_year % 100) );
104 src = buf;
105 goto _str;
106 case 'y': no = tm->tm_year % 100; goto _no;
107 _no: i2a ( buf, no ); /* append number 'no' */
108 src = buf;
109 goto _str;
110 _nos: i2a ( buf, no ); /* the same, but '0'->' ' */
111 if (buf[0] == '0')
112 buf[0] = ' ';
113 src = buf;
114 _str: while (*src && p < dst+max) /* append string */
115 *p++ = *src++;
116 break;
117 };
118 } else {
119 *p++ = *format;
120 }
121
122 if (p >= dst+max)
123 break;
124 }
125
126 *p = '\0';
127 return p - dst;
128}
129
130