This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
%S %C vfprintf contribution
- From: "Artem B. Bityuckiy" <abitytsky at softminecorp dot com>
- To: newlib at sources dot redhat dot com
- Date: Thu, 30 Oct 2003 14:09:59 +0300
- Subject: %S %C vfprintf contribution
- Organization: SoftMine Corporation
- Reply-to: abitytsky at softminecorp dot com
Hello.
Here is the patch that makes vfprintf (and hence, all other vfprintf-based
Xprintf functions) understand ISO C 90 %S (same as %ls) and %C (same as %lc)
format placeholders. Please, review it and give us know if something is
wrong.
This is tested a little bit- it works and it seems should work with any
locale if wcrtomb and wcsrtomb functions work.
--
Best regards,
Artem B. Bityuckiy
SoftMine Corporation, Software Engineer
Tel.: +7(812)329-67-44, +7(812)329-67-45
Mobile: +79112449030
E-mail: abitytsky@softminecorp.com
Web: www.softminecorp.com
164a165
> #include <limits.h>
240c241,246
< #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
---
> #if ((MAXEXP+MAXFRACT+1) > MB_LEN_MAX)
> # define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
> #else
> # define BUF MB_LEN_MAX
> #endif
>
248c254,258
< #define BUF 40
---
> #if (MB_LEN_MAX < 40)
> # define BUF 40
> #else
> # define BUF MB_LEN_MAX
> #endif
271a282
> #define WIDECHARSTR 0x200 /* Widechar string */
523c534,549
< *(cp = buf) = va_arg(ap, int);
---
> case 'C':
> cp = buf;
> if (*fmt == 'C' || (flags & LONGINT))
> {
> mbstate_t ps;
>
> memset((void *)&ps, '\0', sizeof(mbstate_t));
> if ((size = (int)wcrtomb(cp,
> (wchar_t)va_arg(ap, int);, &ps)) == -1)
> goto error;
> }
> else
> {
> *cp = (char)va_arg(ap, int);
> size = 1;
> }
647,648c673,731
< if ((cp = va_arg(ap, char *)) == NULL)
< cp = "(null)";
---
> case 'S':
> sign = '\0';
> cp = va_arg(ap, char *);
>
> if (cp && (ch == 'S' || (flags & LONGINT))) {
> mbstate_t ps;
> _CONST wchar_t *wcp;
>
> wcp = (_CONST wchar_t *)cp;
> size = m = 0;
> memset((void *)&ps, '\0', sizeof(mbstate_t));
>
> /*
> * Count number of bytes needed to store multibyte
> * string that will be produced from widechar
> * string.
> */
> if (prec >= 0) {
> while (1) {
> if (wcp[m] == L'\0')
> break;
> if ((n = wcrtomb(buf, wcp[m], &ps)) == -1)
> goto error;
> if (n + size > prec)
> break;
> m += 1;
> size += n;
> if (size == prec)
> break;
> }
> }
> else {
> size = wcsrtombs(NULL, &wcp, 0, &ps);
> if (size == -1)
> goto error;
> wcp = (_CONST wchar_t *)cp;
> }
>
> if (size == 0)
> break;
>
> if ((cp = (char *)malloc(size + 1)) == NULL)
> goto error;
>
> flags |= WIDECHARSTR;
>
> /*
> * Convert widechar string to multibyte string.
> */
> memset((void *)&ps, '\0', sizeof(mbstate_t));
> if (wcsrtombs(cp, &wcp, size, &ps) != size)
> goto error;
> cp[size] = '\0';
> break;
> }
>
> if (cp == NULL)
> cp = "(null)";
>
665d747
< sign = '\0';
848a931,933
>
> if (flags & WIDECHARSTR)
> free(cp);