This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: [BUG] wprintf(L"%s", str) expects str to be wide
On Jan 11 16:37, Corinna Vinschen wrote:
> [Can we please not use top-posting here? Thanks]
>
> On Jan 11 10:20, Craig Howland wrote:
> > On 01/11/2013 10:07 AM, Corinna Vinschen wrote:
> > >On Jan 11 09:52, Craig Howland wrote:
> > >>Corinna:
> > >> It appears, taking a quick glance at the source, that the string
> > >>is only treated as regular characters if _MB_CAPABLE is
> > >>defined--otherwise it falls into a wide-character-only case. This
> > >>could perhaps explain the differing results.
> > >> Craig
> > >The _MB_CAPABLE code only handles the case which converts wide chars
> > >into multibyte chars. The default code right after the #endif handles
> > >the incoming string as plain byte string.
> > >
> > Corinna:
> > Are we looking at the same place? Lines 1200-1217 of
> > libc/stdio/vfwprintf.c version 1.10 are what I looked at. I only
> > see wide functions there. I'll quote from line 1199 to get the
> > #endif:
> > [...]
> > Craig
>
> No, we're not looking at the same code. I was accidentally looking
> into vfprintf.c. Sorry.
>
> Looking into the right spot now, I don't see how this could be fixed
> easily. _MB_CAPABLE is required to define the conversion functions.
> As a fallback we could assume ASCII (or rather ISO-8859-1) and create an
> array of UTF wide chars by allocating a temporary wide char array and
> fill it with the single byte chars 1:1, but other than that I don't see
> a chance.
Here's a matching patch. I tested it under Cygwin by disabling
_MB_CAPABLE when building vfwprintf.c. Please review. If that's ok,
I'll check it in.
Thanks,
Corinna
* vfwprintf.c (_VFWPRINTF_R): Add code to correctly handle 's'
format specifier on not _MB_CAPABLE targets. Fix a formatting
glitch in _MB_CAPABLE enabled code. Add a missing 'L' specifier.
Index: libc/stdio/vfwprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfwprintf.c,v
retrieving revision 1.10
diff -u -p -r1.10 vfwprintf.c
--- libc/stdio/vfwprintf.c 10 Aug 2012 09:37:32 -0000 1.10
+++ libc/stdio/vfwprintf.c 11 Jan 2013 16:10:34 -0000
@@ -1171,11 +1171,11 @@ string:
insize = strlen(arg);
if (insize >= BUF) {
if ((malloc_buf = (wchar_t *) _malloc_r (data, (insize + 1) * sizeof (wchar_t)))
- == NULL) {
- fp->_flags |= __SERR;
- goto error;
- }
- cp = malloc_buf;
+ == NULL) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ cp = malloc_buf;
} else
cp = buf;
memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
@@ -1195,9 +1195,31 @@ string:
*p = L'\0';
size = p - cp;
}
- else
+#else
+ if (ch != L'S' && !(flags & LONGINT)) {
+ char *arg = (char *) cp;
+ size_t insize = 0;
+
+ if (prec >= 0) {
+ char *p = memchr (arg, '\0', prec);
+ insize = p ? p - arg : prec;
+ } else
+ insize = strlen (arg);
+ if (insize >= BUF) {
+ if ((malloc_buf = (wchar_t *) _malloc_r (data, (insize + 1) * sizeof (wchar_t)))
+ == NULL) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ cp = malloc_buf;
+ } else
+ cp = buf;
+ for (size = 0; size < insize; ++size)
+ cp[size] = arg[size];
+ cp[size] = L'\0';
+ }
#endif /* _MB_CAPABLE */
- if (prec >= 0) {
+ else if (prec >= 0) {
/*
* can't use wcslen; can only look for the
* NUL in the first `prec' characters, and
@@ -1222,7 +1244,7 @@ string:
case L'X':
xdigs = L"0123456789ABCDEF";
goto hex;
- case 'x':
+ case L'x':
xdigs = L"0123456789abcdef";
hex: _uquad = UARG ();
base = HEX;
--
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat