From 9c38a6899957746cbf2c0c04d110626a9271d51a Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 20 Jul 2000 08:56:12 +0000 Subject: Update. 2000-07-20 Ulrich Drepper * libio/Makefile (tests): Add tst_wprintf2. (tst_wprintf2-ARGS): Define. * libio/tst_wprintf2.c: New file. Based on a test case by Yoshito Kawada . * 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 . --- ChangeLog | 21 ++++++++++ libio/Makefile | 5 ++- libio/tst_wprintf2.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ libio/wfiledoalloc.c | 5 ++- libio/wfileops.c | 20 ++++++++-- stdio-common/vfprintf.c | 34 ++++++++++++++-- 6 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 libio/tst_wprintf2.c diff --git a/ChangeLog b/ChangeLog index 633a4efcbb..ac87df4c68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,26 @@ +2000-07-20 Ulrich Drepper + + * libio/Makefile (tests): Add tst_wprintf2. + (tst_wprintf2-ARGS): Define. + * libio/tst_wprintf2.c: New file. + Based on a test case by Yoshito Kawada . + + * 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 + * 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 . + * resolv/Makefile (distribute): Add README. * resolv/README: New file. By Mark Kettenis . diff --git a/libio/Makefile b/libio/Makefile index e636c19c82..ffc6958ae9 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -43,7 +43,8 @@ routines := \ \ 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. @@ -65,6 +66,8 @@ endif CFLAGS-tst_putwc.c = -DOBJPFX=\"$(objpfx)\" +tst_wprintf2-ARGS = "Some Text" + aux := fileops genops stdfiles stdio strops ifeq ($(versioning),yes) diff --git a/libio/tst_wprintf2.c b/libio/tst_wprintf2.c new file mode 100644 index 0000000000..be0f29f53f --- /dev/null +++ b/libio/tst_wprintf2.c @@ -0,0 +1,104 @@ +/* Test case by Yoshito Kawada . */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/libio/wfiledoalloc.c b/libio/wfiledoalloc.c index 7f5cb7f960..76226e9846 100644 --- a/libio/wfiledoalloc.c +++ b/libio/wfiledoalloc.c @@ -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 library is free software; you can redistribute it and/or @@ -76,7 +76,8 @@ _IO_wfile_doallocate (fp) struct _G_stat64 st; /* Allocate room for the external buffer. */ - _IO_file_doallocate (fp); + if (fp->_IO_buf_base == NULL) + _IO_file_doallocate (fp); if (fp->_fileno < 0 || _IO_SYSSTAT (fp, &st) < 0) { diff --git a/libio/wfileops.c b/libio/wfileops.c index 3489b36fb1..94c14c9151 100644 --- a/libio/wfileops.c +++ b/libio/wfileops.c @@ -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. Written by Ulrich Drepper . Based on the single byte version by Per Bothner . @@ -67,7 +67,8 @@ _IO_wdo_write (fp, data, to_do) enum __codecvt_result result; 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); 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, data, data + to_do, &new_data, fp->_IO_write_ptr, - fp->_IO_write_end, + fp->_IO_buf_end, &fp->_IO_write_ptr); /* Write out what we produced so far. */ @@ -289,6 +290,12 @@ _IO_wfile_overflow (f, wch) _IO_wdoallocbuf (f); _IO_wsetg (f, 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 { @@ -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_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; if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) f->_wide_data->_IO_write_end = f->_wide_data->_IO_write_ptr; } if (wch == WEOF) 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 */ if (_IO_do_flush (f) == WEOF) return WEOF; diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 32ad9d85ab..23981d18cd 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -1030,14 +1030,14 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) const char *mbs = (const char *) string; \ 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 \ 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)); \ - len = __mbsrtowcs (string, &mbs, len + 1, &mbstate); \ + len = __mbsrtowcs (string, &mbs, len, &mbstate); \ if (len == (size_t) -1) \ { \ /* Illegal multibyte character. */ \ @@ -1919,6 +1919,9 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping, struct helper_file { struct _IO_FILE_plus _f; +#ifdef COMPILE_WPRINTF + struct _IO_wide_data _wide_data; +#endif _IO_FILE *_put_stream; #ifdef _IO_MTSAFE_IO _IO_lock_t lock; @@ -1948,6 +1951,29 @@ _IO_helper_overflow (_IO_FILE *s, int c) 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 = { JUMP_INIT_DUMMY, @@ -1969,6 +1995,7 @@ static const struct _IO_jump_t _IO_helper_jumps = JUMP_INIT (close, _IO_default_close), JUMP_INIT (stat, _IO_default_stat) }; +#endif static int internal_function @@ -1983,6 +2010,7 @@ buffered_vfprintf (register _IO_FILE *s, const CHAR_T *format, /* Initialize helper. */ helper._put_stream = s; #ifdef COMPILE_WPRINTF + hp->_wide_data = &helper._wide_data; _IO_wsetp (hp, buf, buf + sizeof buf / sizeof (CHAR_T)); hp->_mode = 1; #else -- cgit v1.2.3