diff options
-rw-r--r-- | loslib.c | 28 |
1 files changed, 16 insertions, 12 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: loslib.c,v 1.63 2016/02/09 12:16:11 roberto Exp roberto $ | 2 | ** $Id: loslib.c,v 1.64 2016/04/18 13:06:55 roberto Exp $ |
3 | ** Standard Operating System library | 3 | ** Standard Operating System library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -30,16 +30,16 @@ | |||
30 | */ | 30 | */ |
31 | #if !defined(LUA_STRFTIMEOPTIONS) /* { */ | 31 | #if !defined(LUA_STRFTIMEOPTIONS) /* { */ |
32 | 32 | ||
33 | /* options for ANSI C 89 */ | 33 | /* options for ANSI C 89 (only 1-char options) */ |
34 | #define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" | 34 | #define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" |
35 | 35 | ||
36 | /* options for ISO C 99 and POSIX */ | 36 | /* options for ISO C 99 and POSIX */ |
37 | #define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ | 37 | #define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ |
38 | "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" | 38 | "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ |
39 | 39 | ||
40 | /* options for Windows */ | 40 | /* options for Windows */ |
41 | #define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ | 41 | #define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ |
42 | "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" | 42 | "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ |
43 | 43 | ||
44 | #if defined(LUA_USE_WINDOWS) | 44 | #if defined(LUA_USE_WINDOWS) |
45 | #define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN | 45 | #define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN |
@@ -257,12 +257,13 @@ static int getfield (lua_State *L, const char *key, int d, int delta) { | |||
257 | } | 257 | } |
258 | 258 | ||
259 | 259 | ||
260 | static const char *checkoption (lua_State *L, const char *conv, char *buff) { | 260 | static const char *checkoption (lua_State *L, const char *conv, |
261 | const char *option; | 261 | ptrdiff_t convlen, char *buff) { |
262 | int oplen = 1; | 262 | const char *option = LUA_STRFTIMEOPTIONS; |
263 | for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) { | 263 | int oplen = 1; /* length of options being checked */ |
264 | for (; *option != '\0' && oplen <= convlen; option += oplen) { | ||
264 | if (*option == '|') /* next block? */ | 265 | if (*option == '|') /* next block? */ |
265 | oplen++; /* next length */ | 266 | oplen++; /* will check options with next length (+1) */ |
266 | else if (memcmp(conv, option, oplen) == 0) { /* match? */ | 267 | else if (memcmp(conv, option, oplen) == 0) { /* match? */ |
267 | memcpy(buff, conv, oplen); /* copy valid option to buffer */ | 268 | memcpy(buff, conv, oplen); /* copy valid option to buffer */ |
268 | buff[oplen] = '\0'; | 269 | buff[oplen] = '\0'; |
@@ -280,8 +281,10 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) { | |||
280 | 281 | ||
281 | 282 | ||
282 | static int os_date (lua_State *L) { | 283 | static int os_date (lua_State *L) { |
283 | const char *s = luaL_optstring(L, 1, "%c"); | 284 | size_t slen; |
285 | const char *s = luaL_optlstring(L, 1, "%c", &slen); | ||
284 | time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); | 286 | time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); |
287 | const char *se = s + slen; /* 's' end */ | ||
285 | struct tm tmr, *stm; | 288 | struct tm tmr, *stm; |
286 | if (*s == '!') { /* UTC? */ | 289 | if (*s == '!') { /* UTC? */ |
287 | stm = l_gmtime(&t, &tmr); | 290 | stm = l_gmtime(&t, &tmr); |
@@ -300,13 +303,14 @@ static int os_date (lua_State *L) { | |||
300 | luaL_Buffer b; | 303 | luaL_Buffer b; |
301 | cc[0] = '%'; | 304 | cc[0] = '%'; |
302 | luaL_buffinit(L, &b); | 305 | luaL_buffinit(L, &b); |
303 | while (*s) { | 306 | while (s < se) { |
304 | if (*s != '%') /* not a conversion specifier? */ | 307 | if (*s != '%') /* not a conversion specifier? */ |
305 | luaL_addchar(&b, *s++); | 308 | luaL_addchar(&b, *s++); |
306 | else { | 309 | else { |
307 | size_t reslen; | 310 | size_t reslen; |
308 | char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); | 311 | char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); |
309 | s = checkoption(L, s + 1, cc + 1); /* copy specifier to 'cc' */ | 312 | s++; /* skip '%' */ |
313 | s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ | ||
310 | reslen = strftime(buff, SIZETIMEFMT, cc, stm); | 314 | reslen = strftime(buff, SIZETIMEFMT, cc, stm); |
311 | luaL_addsize(&b, reslen); | 315 | luaL_addsize(&b, reslen); |
312 | } | 316 | } |