This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "uClibc-ng - small C library for embedded systems".
The branch, upstream has been updated via b36422960466777495933ed1eb50befd1c34e9a9 (commit) from 49a67cf67d5a7194214566bc730ee7e28d55bbe1 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit b36422960466777495933ed1eb50befd1c34e9a9 Author: Bernhard Reutner-Fischer rep.dot.nop@gmail.com Date: Tue Nov 18 18:27:47 2014 +0100
locale: Add wcsftime()
Signed-off-by: Bernhard Reutner-Fischer rep.dot.nop@gmail.com
-----------------------------------------------------------------------
Summary of changes: libc/misc/time/time.c | 144 ++++++++++++++++++++++++++++------------------ test/time/Makefile.in | 7 ++- test/time/tst_wcsftime.c | 70 +++++++++++++++------- 3 files changed, 143 insertions(+), 78 deletions(-)
diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c index 347c899..a3fccb2 100644 --- a/libc/misc/time/time.c +++ b/libc/misc/time/time.c @@ -146,8 +146,24 @@ #include <bits/uClibc_uintmaxtostr.h> #include <bits/uClibc_mutex.h>
-#ifdef __UCLIBC_HAS_WCHAR__ +#if defined __UCLIBC_HAS_WCHAR__ && (defined L_wcsftime || defined L_wcsftime_l) #include <wchar.h> +# define CHAR_T wchar_t +# define UCHAR_T unsigned int +# ifdef L_wcsftime +# define strftime wcsftime +# define L_strftime +# if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) +# define strftime_l wcsftime_l +# endif +# endif +# ifdef L_wcsftime_l +# define strftime_l wcsftime_l +# define L_strftime_l +# endif +#else +# define CHAR_T char +# define UCHAR_T unsigned char #endif
#ifndef __isleap @@ -787,12 +803,13 @@ time_t timegm(struct tm *timeptr)
#endif /**********************************************************************/ -#if defined(L_strftime) || defined(L_strftime_l) +#if defined(L_strftime) || defined(L_strftime_l) \ + || defined(L_wcsftime) || defined(L_wcsftime_l)
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
-size_t strftime(char *__restrict s, size_t maxsize, - const char *__restrict format, +size_t strftime(CHAR_T *__restrict s, size_t maxsize, + const CHAR_T *__restrict format, const struct tm *__restrict timeptr) { return strftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE); @@ -990,29 +1007,58 @@ static int load_field(int k, const struct tm *__restrict timeptr) return r; }
+#if defined __UCLIBC_HAS_WCHAR__ && (defined L_wcsftime || defined L_wcsftime_l) +static wchar_t* fmt_to_wc_1(const char *src) +{ + mbstate_t mbstate; + size_t src_len = strlen(src); + wchar_t *dest = (wchar_t *)malloc((src_len + 1) * sizeof(wchar_t)); + if (dest == NULL) + return NULL; + mbstate.__mask = 0; + if (mbsrtowcs(dest, &src, src_len + 1, &mbstate) == (size_t) -1) { + free(dest); + return NULL; + } + return dest; +} +# define fmt_to_wc(dest, src) \ + dest = alloc[++allocno] = fmt_to_wc_1(src) +# define to_wc(dest, src) \ + dest = fmt_to_wc_1(src) +#else +# define fmt_to_wc(dest, src) (dest) = (src) +# define to_wc(dest, src) (dest) = (src) +#endif + #define MAX_PUSH 4
#ifdef __UCLIBC_MJN3_ONLY__ #warning TODO: Check multibyte format string validity. #endif
-size_t __XL_NPP(strftime)(char *__restrict s, size_t maxsize, - const char *__restrict format, +size_t __XL_NPP(strftime)(CHAR_T *__restrict s, size_t maxsize, + const CHAR_T *__restrict format, const struct tm *__restrict timeptr __LOCALE_PARAM ) { long tzo; - register const char *p; - register const char *o; + register const CHAR_T *p; + const CHAR_T *o; + const char *ccp; #ifndef __UCLIBC_HAS_TM_EXTENSIONS__ const rule_struct *rsp; #endif - const char *stack[MAX_PUSH]; + const CHAR_T *stack[MAX_PUSH]; +#if defined __UCLIBC_HAS_WCHAR__ && (defined L_wcsftime || defined L_wcsftime_l) + const CHAR_T *alloc[MAX_PUSH]; + int allocno = -1; +#endif size_t count; size_t o_count; int field_val = 0, i = 0, j, lvl; int x[3]; /* wday, yday, year */ int isofm, days; - char buf[__UIM_BUFLEN_LONG]; + char buf[__UIM_BUFLEN_LONG] = {0,}; unsigned char mod; unsigned char code;
@@ -1037,7 +1083,7 @@ LOOP: }
o_count = 1; - if ((*(o = p) == '%') && (*++p != '%')) { + if ((*(o = (CHAR_T *)p) == '%') && (*++p != '%')) { o_count = 2; mod = ILLEGAL_SPEC; if ((*p == 'O') || (*p == 'E')) { /* modifier */ @@ -1062,31 +1108,33 @@ LOOP: } stack[lvl++] = ++p; if ((code &= 0xf) < 8) { - p = ((const char *) spec) + STACKED_STRINGS_START + code; - p += *((unsigned char *)p); + ccp = (const char *)(spec + STACKED_STRINGS_START + code); + ccp += *ccp; + fmt_to_wc(p, ccp); goto LOOP; } - p = ((const char *) spec) + STACKED_STRINGS_NL_ITEM_START - + (code & 7); + ccp = (const char *)spec + STACKED_STRINGS_NL_ITEM_START + (code & 7); + fmt_to_wc(p, ccp); #ifdef ENABLE_ERA_CODE if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */ - && (*(o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + && (*(ccp = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, (int)(((unsigned char *)p)[4])) __LOCALE_ARG ))) ) { - p = o; + fmt_to_wc(p, ccp); goto LOOP; } #endif - p = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + ccp = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, (int)(*((unsigned char *)p))) __LOCALE_ARG ); + fmt_to_wc(p, ccp); goto LOOP; }
- o = ((const char *) spec) + 26; /* set to "????" */ + ccp = (const char *)(spec + 26); /* set to "????" */ if ((code & MASK_SPEC) == CALC_SPEC) {
if (*p == 's') { @@ -1101,15 +1149,16 @@ LOOP: goto OUTPUT; } #ifdef TIME_T_IS_UNSIGNED - o = _uintmaxtostr(buf + sizeof(buf) - 1, + ccp = _uintmaxtostr(buf + sizeof(buf) - 1, (uintmax_t) t, 10, __UIM_DECIMAL); #else - o = _uintmaxtostr(buf + sizeof(buf) - 1, + ccp = _uintmaxtostr(buf + sizeof(buf) - 1, (uintmax_t) t, -10, __UIM_DECIMAL); #endif o_count = sizeof(buf); + fmt_to_wc(o, ccp); goto OUTPUT; } else if (((*p) | 0x20) == 'z') { /* 'z' or 'Z' */
@@ -1144,7 +1193,7 @@ LOOP: #endif
if (*p == 'Z') { - o = RSP_TZNAME; + ccp = RSP_TZNAME; #ifdef __UCLIBC_HAS_TM_EXTENSIONS__ /* Sigh... blasted glibc extensions. Of course we can't * count on the pointer being valid. Best we can do is @@ -1155,17 +1204,18 @@ LOOP: * case... although it always seems to use the embedded * tm_gmtoff value. What we'll do instead is treat the * timezone name as unknown/invalid and return "???". */ - if (!o) { - o = "???"; + if (!ccp) { + ccp = (const char *)(spec + 27); /* "???" */ } #endif - assert(o != NULL); + assert(ccp != NULL); #if 0 - if (!o) { /* PARANOIA */ - o = spec+30; /* empty string */ + if (!ccp) { /* PARANOIA */ + ccp = spec+30; /* empty string */ } #endif o_count = SIZE_MAX; + fmt_to_wc(o, ccp); #ifdef __UCLIBC_HAS_TM_EXTENSIONS__ goto OUTPUT; #endif @@ -1264,17 +1314,19 @@ ISO_LOOP: if ((code & MASK_SPEC) == STRING_SPEC) { o_count = SIZE_MAX; field_val += spec[STRINGS_NL_ITEM_START + (code & 0xf)]; - o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, field_val) __LOCALE_ARG); + ccp = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, field_val) __LOCALE_ARG); + fmt_to_wc(o, ccp); } else { o_count = ((i >> 1) & 3) + 1; - o = buf + o_count; + ccp = buf + o_count; do { - *(char *)(--o) = '0' + (field_val % 10); + *(char *)(--ccp) = '0' + (field_val % 10); field_val /= 10; - } while (o > buf); + } while (ccp > buf); if (*buf == '0') { *buf = ' ' + (i & 16); } + fmt_to_wc(o, ccp); } }
@@ -1285,6 +1337,10 @@ OUTPUT: --o_count; --count; } +#if defined __UCLIBC_HAS_WCHAR__ && (defined L_wcsftime || defined L_wcsftime_l) + if (allocno >= 0) + free((void *)alloc[allocno--]); +#endif goto LOOP; } # ifdef L_strftime_l @@ -2444,31 +2500,9 @@ DONE:
#endif /**********************************************************************/ -#if defined(L_wcsftime) || defined(L_wcsftime_l) - -#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) - -size_t wcsftime(wchar_t *__restrict s, size_t maxsize, - const wchar_t *__restrict format, - const struct tm *__restrict timeptr) -{ - return wcsftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE); -} - -#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ +#if (defined(L_wcsftime) || defined(L_wcsftime_l))
-size_t __XL_NPP(wcsftime)(wchar_t *__restrict s, size_t maxsize, - const wchar_t *__restrict format, - const struct tm *__restrict timeptr __LOCALE_PARAM ) -{ -#warning wcsftime always fails - return 0; /* always fail */ -} -#ifdef L_wcsftime_l -libc_hidden_def(wcsftime_l) -#endif - -#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ +/* Implemented via strftime / strftime_l wchar_t variants */
#endif /**********************************************************************/ diff --git a/test/time/Makefile.in b/test/time/Makefile.in index 02c8d91..bb11e18 100644 --- a/test/time/Makefile.in +++ b/test/time/Makefile.in @@ -5,8 +5,13 @@ TESTS_DISABLED := bug-asctime bug-asctime_r time tst-mktime2 tst-posixtz \ tst-strftime tst-strptime tst-timezone
ifneq ($(UCLIBC_HAS_XLOCALE),y) -TESTS_DISABLED += tst-ftime_l tst_wcsftime +TESTS_DISABLED += tst-ftime_l +endif + +ifneq ($(UCLIBC_HAS_WCHAR)$(UCLIBC_HAS_LOCALE),yy) +TESTS_DISABLED += tst_wcsftime endif
CFLAGS_tst-strptime2 := -std=c99 DODIFF_futimens1 := 1 +DODIFF_tst_wcsftime := 1 diff --git a/test/time/tst_wcsftime.c b/test/time/tst_wcsftime.c index 6e35f1e..5631d95 100644 --- a/test/time/tst_wcsftime.c +++ b/test/time/tst_wcsftime.c @@ -1,39 +1,65 @@ #include <stdio.h> #include <time.h> #include <features.h> -#ifdef __UCLIBC_HAS_WCHAR__ #include <wchar.h> +#include <locale.h> + +#define NUM_OF_DATES 7 +#define NUM_OF_LOCALES 3 +#define BUF_SIZE 256
int -main (int argc, char *argv[]) +main (void) { - wchar_t buf[200]; - time_t t; + wchar_t buf[BUF_SIZE]; struct tm *tp; - int result = 0; + time_t time_list[NUM_OF_DATES] = { + 500, 68200000, 694223999, + 694224000, 704900000, 705000000, + 705900000 + }; + char *locale_list[NUM_OF_LOCALES] = { + "C", + "fr_FR.ISO-8859-1", + "ja_JP.UTF-8" + }; + int result = 0, ddd, lll; size_t n;
- time (&t); - tp = gmtime (&t); + for (lll = 0; lll < NUM_OF_LOCALES; lll++) { + printf ("\nUsing locale: %s\n", locale_list[lll]); + char* set = setlocale(LC_ALL, locale_list[lll]); + if (set == NULL) { + printf ("FAILED!\n\n"); + continue; + } else + printf ("\n"); + for (ddd = 0; ddd < NUM_OF_DATES; ddd++) { + tp = localtime(&time_list[ddd]); + printf ("%ld corresponds to ", time_list[ddd]);
- n = wcsftime (buf, sizeof (buf) / sizeof (buf[0]), - L"%H:%M:%S %Y-%m-%d\n", tp); - if (n != 21) - result = 1; + n = wcsftime (buf, sizeof (buf) / sizeof (buf[0]), + L"%H:%M:%S %Y-%m-%d%n", tp); + if (n != 21) { + result = 1; + printf ("FAILED!\n"); + }
- wprintf (L"It is now %ls", buf); + printf ("%ls", buf);
- wcsftime (buf, sizeof (buf) / sizeof (buf[0]), L"%A\n", tp); + wcsftime (buf, sizeof (buf) / sizeof (buf[0]), + L"%tor, as %%D %%T: %D %T%n", tp); + printf ("%ls", buf);
- wprintf (L"The weekday is %ls", buf); + wcsftime (buf, sizeof (buf) / sizeof (buf[0]), L"%A (%a)%n", tp); + printf ("The weekday was %ls", buf);
+ wcsftime (buf, sizeof (buf) / sizeof (buf[0]), L"%B (%b) %Y%n", tp); + /* glibc bug? forgets aigu from french february février + * See s/printf (/wprintf (L/g */ + //wprintf (L"Month was %ls", buf); + printf ("Month was %ls", buf); + } + } return result; } - -#else -int main(void) -{ - puts("Test requires WCHAR support; skipping"); - return 0; -} -#endif
hooks/post-receive