1
0
Fork 0
forked from len0rd/rockbox

Lua: add support for os library

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21106 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Maurus Cuelenaere 2009-05-27 22:48:50 +00:00
parent 64595105b1
commit b2581e143d
7 changed files with 398 additions and 3 deletions

View file

@ -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

View file

@ -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

58
apps/plugins/lua/gmtime.c Normal file
View file

@ -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;
}

199
apps/plugins/lua/loslib.c Normal file
View file

@ -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;
}

View file

@ -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);

View file

@ -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}
};

130
apps/plugins/lua/strftime.c Normal file
View file

@ -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;
}