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(a)gmail.com>
Date: Tue Nov 18 18:27:47 2014 +0100
locale: Add wcsftime()
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop(a)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
--
uClibc-ng - small C library for embedded systems