2000-07-20  Ulrich Drepper  <drepper@redhat.com>

	* libio/Makefile (tests): Add tst_wprintf2.
	(tst_wprintf2-ARGS): Define.
	* libio/tst_wprintf2.c: New file.
	Based on a test case by Yoshito Kawada <KAWADA@jp.ibm.com>.

	* libio/wfiledoalloc.c: Only allocate external buffer if this
	hasn't happened yet.

	* libio/wfileops.c (_IO_wdo_write): Overflow only if there is really
	something in the buffer.  gconv call can write up to end of the
	buffer, not only _IO_write_end.
	(_IO_wfile_overflow): Allocate also external buffer.

	* stdio-common/vfprintf.c (process_string_arg): Handle multibyte
	strings with precision in vfwprintf correctly.
	* stdio-common/vfprintf.c: Fix completely broken handling of
	unbuffered wide character streams.
	Reported by Yoshito Kawada <KAWADA@jp.ibm.com>.
This commit is contained in:
Ulrich Drepper 2000-07-20 08:56:12 +00:00
parent 4e8286acfa
commit 9c38a68999
6 changed files with 179 additions and 10 deletions

View File

@ -1,5 +1,26 @@
2000-07-20 Ulrich Drepper <drepper@redhat.com>
* libio/Makefile (tests): Add tst_wprintf2.
(tst_wprintf2-ARGS): Define.
* libio/tst_wprintf2.c: New file.
Based on a test case by Yoshito Kawada <KAWADA@jp.ibm.com>.
* libio/wfiledoalloc.c: Only allocate external buffer if this
hasn't happened yet.
* libio/wfileops.c (_IO_wdo_write): Overflow only if there is really
something in the buffer. gconv call can write up to end of the
buffer, not only _IO_write_end.
(_IO_wfile_overflow): Allocate also external buffer.
2000-07-19 Ulrich Drepper <drepper@redhat.com> 2000-07-19 Ulrich Drepper <drepper@redhat.com>
* stdio-common/vfprintf.c (process_string_arg): Handle multibyte
strings with precision in vfwprintf correctly.
* stdio-common/vfprintf.c: Fix completely broken handling of
unbuffered wide character streams.
Reported by Yoshito Kawada <KAWADA@jp.ibm.com>.
* resolv/Makefile (distribute): Add README. * resolv/Makefile (distribute): Add README.
* resolv/README: New file. By Mark Kettenis <kettenis@gnu.org>. * resolv/README: New file. By Mark Kettenis <kettenis@gnu.org>.

View File

@ -43,7 +43,8 @@ routines := \
\ \
libc_fatal libc_fatal
tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst_wprintf2
all: # Make this the default target; it will be defined in Rules. all: # Make this the default target; it will be defined in Rules.
@ -65,6 +66,8 @@ endif
CFLAGS-tst_putwc.c = -DOBJPFX=\"$(objpfx)\" CFLAGS-tst_putwc.c = -DOBJPFX=\"$(objpfx)\"
tst_wprintf2-ARGS = "Some Text"
aux := fileops genops stdfiles stdio strops aux := fileops genops stdfiles stdio strops
ifeq ($(versioning),yes) ifeq ($(versioning),yes)

104
libio/tst_wprintf2.c Normal file
View File

@ -0,0 +1,104 @@
/* Test case by Yoshito Kawada <KAWADA@jp.ibm.com>. */
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
int
main (int argc, char *argv[])
{
int a = 3;
int fd;
char name[] = "/tmp/wprintf.out.XXXXXX";
FILE *fp;
char buf[100];
size_t len;
int res = 0;
fd = mkstemp (name);
if (fd == -1)
error (EXIT_FAILURE, errno, "cannot open temporary file");
unlink (name);
setlocale (LC_ALL, "");
fp = fdopen (dup (fd), "w");
if (fp == NULL)
error (EXIT_FAILURE, errno, "fdopen(,\"w\")");
fwprintf (fp, L"test start");
fwprintf (fp, L" int %d\n", a);
/* String with precision. */
fwprintf (fp, L"1[%6.3s]\n", argv[1]);
fclose (fp);
fp = fdopen (dup (fd), "a");
if (fp == NULL)
error (EXIT_FAILURE, errno, "fdopen(,\"a\")");
setvbuf (fp, NULL, _IONBF, 0);
/* fwprintf to unbuffered stream. */
fwprintf (fp, L"hello.\n");
fclose (fp);
/* Now read it back in. This time using multibyte functions. */
lseek (fd, SEEK_SET, 0);
fp = fdopen (fd, "r");
if (fp == NULL)
error (EXIT_FAILURE, errno, "fdopen(,\"r\")");
if (fgets (buf, sizeof buf, fp) != buf)
error (EXIT_FAILURE, errno, "first fgets");
len = strlen (buf);
if (buf[len - 1] == '\n')
--len;
else
{
puts ("newline missing after first line");
res = 1;
}
printf ("1st line: \"%.*s\" -> %s\n", (int) len, buf,
strncmp (buf, "test start int 3", len) == 0 ? "OK" : "FAIL");
res |= strncmp (buf, "test start int 3", len) != 0;
if (fgets (buf, sizeof buf, fp) != buf)
error (EXIT_FAILURE, errno, "second fgets");
len = strlen (buf);
if (buf[len - 1] == '\n')
--len;
else
{
puts ("newline missing after second line");
res = 1;
}
printf ("2nd line: \"%.*s\" -> %s\n", (int) len, buf,
strncmp (buf, "1[ Som]", len) == 0 ? "OK" : "FAIL");
res |= strncmp (buf, "1[ Som]", len) != 0;
if (fgets (buf, sizeof buf, fp) != buf)
error (EXIT_FAILURE, errno, "third fgets");
len = strlen (buf);
if (buf[len - 1] == '\n')
--len;
else
{
puts ("newline missing after third line");
res = 1;
}
printf ("3rd line: \"%.*s\" -> %s\n", (int) len, buf,
strncmp (buf, "hello.", len) == 0 ? "OK" : "FAIL");
res |= strncmp (buf, "hello.", len) != 0;
return res;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1993, 1997, 1999 Free Software Foundation, Inc. /* Copyright (C) 1993, 1997, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU IO Library. This file is part of the GNU IO Library.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
@ -76,6 +76,7 @@ _IO_wfile_doallocate (fp)
struct _G_stat64 st; struct _G_stat64 st;
/* Allocate room for the external buffer. */ /* Allocate room for the external buffer. */
if (fp->_IO_buf_base == NULL)
_IO_file_doallocate (fp); _IO_file_doallocate (fp);
if (fp->_fileno < 0 || _IO_SYSSTAT (fp, &st) < 0) if (fp->_fileno < 0 || _IO_SYSSTAT (fp, &st) < 0)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. /* Copyright (C) 1993, 95, 97, 98, 99, 2000 Free Software Foundation, Inc.
This file is part of the GNU IO Library. This file is part of the GNU IO Library.
Written by Ulrich Drepper <drepper@cygnus.com>. Written by Ulrich Drepper <drepper@cygnus.com>.
Based on the single byte version by Per Bothner <bothner@cygnus.com>. Based on the single byte version by Per Bothner <bothner@cygnus.com>.
@ -67,7 +67,8 @@ _IO_wdo_write (fp, data, to_do)
enum __codecvt_result result; enum __codecvt_result result;
const wchar_t *new_data; const wchar_t *new_data;
if (fp->_IO_write_end == fp->_IO_write_ptr) if (fp->_IO_write_end == fp->_IO_write_ptr
&& fp->_IO_write_end != fp->_IO_write_base)
{ {
_IO_new_file_overflow (fp, EOF); _IO_new_file_overflow (fp, EOF);
assert (fp->_IO_write_end > fp->_IO_write_ptr); assert (fp->_IO_write_end > fp->_IO_write_ptr);
@ -77,7 +78,7 @@ _IO_wdo_write (fp, data, to_do)
result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state, result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state,
data, data + to_do, &new_data, data, data + to_do, &new_data,
fp->_IO_write_ptr, fp->_IO_write_ptr,
fp->_IO_write_end, fp->_IO_buf_end,
&fp->_IO_write_ptr); &fp->_IO_write_ptr);
/* Write out what we produced so far. */ /* Write out what we produced so far. */
@ -289,6 +290,12 @@ _IO_wfile_overflow (f, wch)
_IO_wdoallocbuf (f); _IO_wdoallocbuf (f);
_IO_wsetg (f, f->_wide_data->_IO_buf_base, _IO_wsetg (f, f->_wide_data->_IO_buf_base,
f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base); f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base);
if (f->_IO_write_base == NULL)
{
_IO_doallocbuf (f);
_IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
}
} }
else else
{ {
@ -313,13 +320,18 @@ _IO_wfile_overflow (f, wch)
f->_wide_data->_IO_read_base = f->_wide_data->_IO_read_ptr = f->_wide_data->_IO_read_base = f->_wide_data->_IO_read_ptr =
f->_wide_data->_IO_read_end; f->_wide_data->_IO_read_end;
f->_IO_write_ptr = f->_IO_read_ptr;
f->_IO_write_base = f->_IO_write_ptr;
f->_IO_write_end = f->_IO_buf_end;
f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
f->_flags |= _IO_CURRENTLY_PUTTING; f->_flags |= _IO_CURRENTLY_PUTTING;
if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
f->_wide_data->_IO_write_end = f->_wide_data->_IO_write_ptr; f->_wide_data->_IO_write_end = f->_wide_data->_IO_write_ptr;
} }
if (wch == WEOF) if (wch == WEOF)
return _IO_do_flush (f); return _IO_do_flush (f);
if (f->_wide_data->_IO_write_ptr == f->_wide_data->_IO_buf_end ) if (f->_wide_data->_IO_write_ptr == f->_wide_data->_IO_buf_end)
/* Buffer is really full */ /* Buffer is really full */
if (_IO_do_flush (f) == WEOF) if (_IO_do_flush (f) == WEOF)
return WEOF; return WEOF;

View File

@ -1030,14 +1030,14 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
const char *mbs = (const char *) string; \ const char *mbs = (const char *) string; \
mbstate_t mbstate; \ mbstate_t mbstate; \
\ \
len = prec == -1 ? strnlen (mbs, prec) : strlen (mbs); \ len = prec != -1 ? strnlen (mbs, prec) : strlen (mbs); \
\ \
/* Allocate dynamically an array which definitely is long \ /* Allocate dynamically an array which definitely is long \
enough for the wide character version. */ \ enough for the wide character version. */ \
string = (CHAR_T *) alloca ((len + 1) * sizeof (wchar_t)); \ string = (CHAR_T *) alloca (len * sizeof (wchar_t)); \
\ \
memset (&mbstate, '\0', sizeof (mbstate_t)); \ memset (&mbstate, '\0', sizeof (mbstate_t)); \
len = __mbsrtowcs (string, &mbs, len + 1, &mbstate); \ len = __mbsrtowcs (string, &mbs, len, &mbstate); \
if (len == (size_t) -1) \ if (len == (size_t) -1) \
{ \ { \
/* Illegal multibyte character. */ \ /* Illegal multibyte character. */ \
@ -1919,6 +1919,9 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
struct helper_file struct helper_file
{ {
struct _IO_FILE_plus _f; struct _IO_FILE_plus _f;
#ifdef COMPILE_WPRINTF
struct _IO_wide_data _wide_data;
#endif
_IO_FILE *_put_stream; _IO_FILE *_put_stream;
#ifdef _IO_MTSAFE_IO #ifdef _IO_MTSAFE_IO
_IO_lock_t lock; _IO_lock_t lock;
@ -1948,6 +1951,29 @@ _IO_helper_overflow (_IO_FILE *s, int c)
return PUTC (c, s); return PUTC (c, s);
} }
#ifdef COMPILE_WPRINTF
static const struct _IO_jump_t _IO_helper_jumps =
{
JUMP_INIT_DUMMY,
JUMP_INIT (finish, _IO_wdefault_finish),
JUMP_INIT (overflow, _IO_helper_overflow),
JUMP_INIT (underflow, _IO_default_underflow),
JUMP_INIT (uflow, _IO_default_uflow),
JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
JUMP_INIT (xsputn, _IO_wdefault_xsputn),
JUMP_INIT (xsgetn, _IO_wdefault_xsgetn),
JUMP_INIT (seekoff, _IO_default_seekoff),
JUMP_INIT (seekpos, _IO_default_seekpos),
JUMP_INIT (setbuf,(_IO_setbuf_t) _IO_wdefault_setbuf),
JUMP_INIT (sync, _IO_default_sync),
JUMP_INIT (doallocate, _IO_wdefault_doallocate),
JUMP_INIT (read, _IO_default_read),
JUMP_INIT (write, _IO_default_write),
JUMP_INIT (seek, _IO_default_seek),
JUMP_INIT (close, _IO_default_close),
JUMP_INIT (stat, _IO_default_stat)
};
#else
static const struct _IO_jump_t _IO_helper_jumps = static const struct _IO_jump_t _IO_helper_jumps =
{ {
JUMP_INIT_DUMMY, JUMP_INIT_DUMMY,
@ -1969,6 +1995,7 @@ static const struct _IO_jump_t _IO_helper_jumps =
JUMP_INIT (close, _IO_default_close), JUMP_INIT (close, _IO_default_close),
JUMP_INIT (stat, _IO_default_stat) JUMP_INIT (stat, _IO_default_stat)
}; };
#endif
static int static int
internal_function internal_function
@ -1983,6 +2010,7 @@ buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format,
/* Initialize helper. */ /* Initialize helper. */
helper._put_stream = s; helper._put_stream = s;
#ifdef COMPILE_WPRINTF #ifdef COMPILE_WPRINTF
hp->_wide_data = &helper._wide_data;
_IO_wsetp (hp, buf, buf + sizeof buf / sizeof (CHAR_T)); _IO_wsetp (hp, buf, buf + sizeof buf / sizeof (CHAR_T));
hp->_mode = 1; hp->_mode = 1;
#else #else