diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-02-04 22:36:03 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2009-02-04 22:36:03 +0000 |
commit | 73c5dd45bc405428148ee740cac61a1279fe57d4 (patch) | |
tree | 878555d8c116d7ac9cb716b79e10d240fde946a3 /libio | |
parent | 23a4b43d6a98912d505458daeced44b22830a773 (diff) | |
download | glibc-73c5dd45bc405428148ee740cac61a1279fe57d4.tar glibc-73c5dd45bc405428148ee740cac61a1279fe57d4.tar.gz glibc-73c5dd45bc405428148ee740cac61a1279fe57d4.tar.bz2 glibc-73c5dd45bc405428148ee740cac61a1279fe57d4.zip |
Updated to fedora-glibc-20090204T2135cvs/fedora-glibc-2_9_90-3
Diffstat (limited to 'libio')
-rw-r--r-- | libio/Makefile | 4 | ||||
-rw-r--r-- | libio/tst-fgetwc.c | 52 | ||||
-rw-r--r-- | libio/tst-fgetwc.input | 2 | ||||
-rw-r--r-- | libio/wfileops.c | 48 |
4 files changed, 93 insertions, 13 deletions
diff --git a/libio/Makefile b/libio/Makefile index 385040fb96..b94d047f5a 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-2004,2006,2007,2008 Free Software Foundation, Inc. +# Copyright (C) 1995-2004,2006,2007,2008,2009 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -58,7 +58,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ tst-memstream1 tst-memstream2 \ tst-wmemstream1 tst-wmemstream2 \ bug-memstream1 bug-wmemstream1 \ - tst-setvbuf1 tst-popen1 + tst-setvbuf1 tst-popen1 tst-fgetwc test-srcs = test-freopen all: # Make this the default target; it will be defined in Rules. diff --git a/libio/tst-fgetwc.c b/libio/tst-fgetwc.c new file mode 100644 index 0000000000..9ccfeb1526 --- /dev/null +++ b/libio/tst-fgetwc.c @@ -0,0 +1,52 @@ +#include <locale.h> +#include <stdio.h> +#include <wchar.h> + + +static int +do_test (void) +{ + if (setlocale (LC_ALL, "de_DE.utf8") == NULL) + { + puts ("setlocale failed"); + return 1; + } + + if (setvbuf (stdin, NULL, _IONBF, 0) != 0) + { + puts ("setvbuf failed"); + return 1; + } + + wchar_t buf[100]; + size_t nbuf = 0; + wint_t c; + while ((c = fgetwc (stdin)) != WEOF) + buf[nbuf++] = c; + + if (ferror (stdin)) + { + puts ("error on stdin"); + return 1; + } + + const wchar_t expected[] = + { + 0x00000439, 0x00000446, 0x00000443, 0x0000043a, + 0x00000435, 0x0000043d, 0x0000000a, 0x00000071, + 0x00000077, 0x00000065, 0x00000072, 0x00000074, + 0x00000079, 0x0000000a + }; + + if (nbuf != sizeof (expected) / sizeof (expected[0]) + || wmemcmp (expected, buf, nbuf) != 0) + { + puts ("incorrect result"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/libio/tst-fgetwc.input b/libio/tst-fgetwc.input new file mode 100644 index 0000000000..b1a48dadb8 --- /dev/null +++ b/libio/tst-fgetwc.input @@ -0,0 +1,2 @@ +йцукен +qwerty diff --git a/libio/wfileops.c b/libio/wfileops.c index b930aad067..c5f0eaf6a7 100644 --- a/libio/wfileops.c +++ b/libio/wfileops.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993,1995,1997-2003,2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1993,1995,1997-2004,2006,2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@cygnus.com>. Based on the single byte version by Per Bothner <bothner@cygnus.com>. @@ -123,8 +123,6 @@ _IO_wfile_underflow (fp) struct _IO_codecvt *cd; enum __codecvt_result status; _IO_ssize_t count; - int tries; - const char *read_ptr_copy; if (__builtin_expect (fp->_flags & _IO_NO_READS, 0)) { @@ -236,13 +234,15 @@ _IO_wfile_underflow (fp) fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base; - tries = 0; + const char *read_ptr_copy; + char accbuf[MB_LEN_MAX]; + size_t naccbuf = 0; again: count = _IO_SYSREAD (fp, fp->_IO_read_end, fp->_IO_buf_end - fp->_IO_read_end); if (count <= 0) { - if (count == 0 && tries == 0) + if (count == 0 && naccbuf == 0) fp->_flags |= _IO_EOF_SEEN; else fp->_flags |= _IO_ERR_SEEN, count = 0; @@ -250,7 +250,7 @@ _IO_wfile_underflow (fp) fp->_IO_read_end += count; if (count == 0) { - if (tries != 0) + if (naccbuf != 0) /* There are some bytes in the external buffer but they don't convert to anything. */ __set_errno (EILSEQ); @@ -262,18 +262,31 @@ _IO_wfile_underflow (fp) /* Now convert the read input. */ fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; fp->_IO_read_base = fp->_IO_read_ptr; + const char *from = fp->_IO_read_ptr; + const char *to = fp->_IO_read_end; + size_t to_copy = count; + if (__builtin_expect (naccbuf != 0, 0)) + { + to_copy = MIN (sizeof (accbuf) - naccbuf, count); + to = __mempcpy (&accbuf[naccbuf], from, to_copy); + naccbuf += to_copy; + from = accbuf; + } status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, - fp->_IO_read_ptr, fp->_IO_read_end, - &read_ptr_copy, + from, to, &read_ptr_copy, fp->_wide_data->_IO_read_end, fp->_wide_data->_IO_buf_end, &fp->_wide_data->_IO_read_end); - fp->_IO_read_ptr = (char *) read_ptr_copy; + if (__builtin_expect (naccbuf != 0, 0)) + fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]); + else + fp->_IO_read_ptr = (char *) read_ptr_copy; if (fp->_wide_data->_IO_read_end == fp->_wide_data->_IO_buf_base) { - if (status == __codecvt_error || fp->_IO_read_end == fp->_IO_buf_end) + if (status == __codecvt_error) { + out_eilseq: __set_errno (EILSEQ); fp->_flags |= _IO_ERR_SEEN; return WEOF; @@ -281,7 +294,20 @@ _IO_wfile_underflow (fp) /* The read bytes make no complete character. Try reading again. */ assert (status == __codecvt_partial); - ++tries; + + if (naccbuf == 0) + { + naccbuf = fp->_IO_read_end - fp->_IO_read_ptr; + if (naccbuf >= sizeof (accbuf)) + goto out_eilseq; + + memcpy (accbuf, fp->_IO_read_ptr, naccbuf); + } + else if (naccbuf == sizeof (accbuf)) + goto out_eilseq; + + fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_read_base; + goto again; } |