Subject: lib/29826: libc missing wcsftime()
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: J.T. Conklin <jtc@acorntoolworks.com>
List: netbsd-bugs
Date: 03/29/2005 17:06:01
>Number: 29826
>Category: lib
>Synopsis: libc missing wcsftime()
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Mar 29 17:06:01 +0000 2005
>Originator: J.T. Conklin
>Release: NetBSD 2.0.1
>Organization:
J.T. Conklin
>Environment:
System: NetBSD orac 2.0.1 NetBSD 2.0.1 (ORAC) #2: Sun Mar 13 22:46:10 PST 2005 jtc@orac:/home/jtc/netbsd/NetBSD-2.0/src/sys/arch/i386/compile/ORAC i386
Architecture: i386
Machine: i386
>Description:
libc is missing wcsftime() --- the wide character version of
strftime().
This is the only function that is actually required for the C++
library to support wide strings (However, libstdc++'s configure script
still thinks it needs the wide character versions of *printf. I'll be
submitting a PR on that shortly).
This enclosed patch adapts Tim Robbins' implementation from FreeBSD.
It converts the wide string to multi-byte strings, calls strftime(),
and then converts the results back to a wide character array. This
may not be the most elegant implementation, but it's consistant with
what we do with wcstod(), etc.
>How-To-Repeat:
>Fix:
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# PATCH
# wcsftime.c
#
echo x - PATCH
sed 's/^X//' >PATCH << 'END-of-PATCH'
XIndex: include/wchar.h
X===================================================================
XRCS file: /cvsroot/src/include/wchar.h,v
Xretrieving revision 1.21
Xdiff -c -r1.21 wchar.h
X*** include/wchar.h 3 Feb 2005 04:39:32 -0000 1.21
X***************
X*** 93,98 ****
X--- 93,100 ----
X #undef _BSD_SIZE_T_
X #endif
X
X+ struct tm;
X+
X __BEGIN_DECLS
X wint_t btowc(int);
X size_t mbrlen(const char * __restrict, size_t, mbstate_t * __restrict);
X***************
X*** 108,113 ****
X--- 110,117 ----
X int wcscoll(const wchar_t *, const wchar_t *);
X wchar_t *wcscpy(wchar_t * __restrict, const wchar_t * __restrict);
X size_t wcscspn(const wchar_t *, const wchar_t *);
X+ size_t wcsftime(wchar_t * __restrict, size_t, const wchar_t * __restrict,
X+ const struct tm * __restrict);
X size_t wcslen(const wchar_t *);
X wchar_t *wcsncat(wchar_t * __restrict, const wchar_t * __restrict, size_t);
X int wcsncmp(const wchar_t *, const wchar_t *, size_t);
XIndex: lib/libc/locale/Makefile.inc
X===================================================================
XRCS file: /cvsroot/src/lib/libc/locale/Makefile.inc,v
Xretrieving revision 1.45
Xdiff -c -r1.45 Makefile.inc
X*** lib/libc/locale/Makefile.inc 11 Mar 2003 09:21:23 -0000 1.45
X***************
X*** 6,12 ****
X
X SRCS+= _def_messages.c _def_monetary.c _def_numeric.c _def_time.c \
X ctypeio.c localeconv.c nl_langinfo.c setlocale.c setlocale1.c \
X! setlocale32.c __mb_cur_max.c wcscoll.c wcstod.c \
X wcstol.c wcstoll.c wcstoimax.c wcstoul.c wcstoull.c wcstoumax.c \
X wcsxfrm.c aliasname.c
X MAN+= nl_langinfo.3 setlocale.3
X--- 6,12 ----
X
X SRCS+= _def_messages.c _def_monetary.c _def_numeric.c _def_time.c \
X ctypeio.c localeconv.c nl_langinfo.c setlocale.c setlocale1.c \
X! setlocale32.c __mb_cur_max.c wcscoll.c wcsftime.c wcstod.c \
X wcstol.c wcstoll.c wcstoimax.c wcstoul.c wcstoull.c wcstoumax.c \
X wcsxfrm.c aliasname.c
X MAN+= nl_langinfo.3 setlocale.3
END-of-PATCH
echo x - wcsftime.c
sed 's/^X//' >wcsftime.c << 'END-of-wcsftime.c'
X/*-
X * Copyright (c) 2002 Tim J. Robbins
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#include <sys/cdefs.h>
X#if defined(LIBC_SCCS) && !defined(lint)
X#if 0
X__FBSDID("$FreeBSD: src/lib/libc/locale/wcsftime.c,v 1.4 2004/04/07 09:47:56 tjr Exp $");
X#else
X__RCSID("$NetBSD: $");
X#endif
X#endif /* LIBC_SCCS and not lint */
X
X#include <errno.h>
X#include <limits.h>
X#include <stdlib.h>
X#include <time.h>
X#include <wchar.h>
X
X/*
X * Convert date and time to a wide-character string.
X *
X * This is the wide-character counterpart of strftime(). So that we do not
X * have to duplicate the code of strftime(), we convert the format string to
X * multibyte, call strftime(), then convert the result back into wide
X * characters.
X *
X * This technique loses in the presence of stateful multibyte encoding if any
X * of the conversions in the format string change conversion state. When
X * stateful encoding is implemented, we will need to reset the state between
X * format specifications in the format string.
X */
Xsize_t
Xwcsftime(wchar_t *wcs, size_t maxsize,
X const wchar_t *format, const struct tm *timeptr)
X{
X static const mbstate_t initial;
X mbstate_t mbs;
X char *dst, *dstp, *sformat;
X size_t n, sflen;
X int sverrno;
X
X sformat = dst = NULL;
X
X /*
X * Convert the supplied format string to a multibyte representation
X * for strftime(), which only handles single-byte characters.
X */
X mbs = initial;
X sflen = wcsrtombs(NULL, &format, 0, &mbs);
X if (sflen == (size_t)-1)
X goto error;
X if ((sformat = malloc(sflen + 1)) == NULL)
X goto error;
X mbs = initial;
X wcsrtombs(sformat, &format, sflen + 1, &mbs);
X
X /*
X * Allocate memory for longest multibyte sequence that will fit
X * into the caller's buffer and call strftime() to fill it.
X * Then, copy and convert the result back into wide characters in
X * the caller's buffer.
X */
X if (SIZE_T_MAX / MB_CUR_MAX <= maxsize) {
X /* maxsize is prepostorously large - avoid int. overflow. */
X errno = EINVAL;
X goto error;
X }
X if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL)
X goto error;
X if (strftime(dst, maxsize, sformat, timeptr) == 0)
X goto error;
X dstp = dst;
X mbs = initial;
X n = mbsrtowcs(wcs, (const char **)&dstp, maxsize, &mbs);
X if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
X goto error;
X
X free(sformat);
X free(dst);
X return (n);
X
Xerror:
X sverrno = errno;
X free(sformat);
X free(dst);
X errno = sverrno;
X return (0);
X}
END-of-wcsftime.c
exit
>Unformatted: