diff options
Diffstat (limited to 'libio')
-rw-r--r-- | libio/Makefile | 4 | ||||
-rw-r--r-- | libio/iofgetws.c | 5 | ||||
-rw-r--r-- | libio/tst-fgetws.c | 185 | ||||
-rw-r--r-- | libio/wfileops.c | 42 |
4 files changed, 208 insertions, 28 deletions
diff --git a/libio/Makefile b/libio/Makefile index f49755eef4..0130234fe0 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -47,7 +47,8 @@ routines := \ libc_fatal fmemopen tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ - tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-fopenloc + tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-fopenloc \ + tst-fgetws test-srcs = test-freopen all: # Make this the default target; it will be defined in Rules. @@ -82,6 +83,7 @@ tst_wprintf2-ARGS = "Some Text" tst-widetext-ENV = LOCPATH=$(common-objpfx)localedata LANGUAGE=C tst-fopenloc-ENV = LOCPATH=$(common-objpfx)localedata \ MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace +tst-fgetws-ENV = LOCPATH=$(common-objpfx)localedata LANGUAGE=C generated = tst-fopenloc.mtrace tst-fopenloc.check diff --git a/libio/iofgetws.c b/libio/iofgetws.c index b7e8352d72..741bb49e6f 100644 --- a/libio/iofgetws.c +++ b/libio/iofgetws.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. +/* Copyright (C) 1993, 95, 96, 97, 98, 99, 2001 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 @@ -50,8 +50,7 @@ fgetws (buf, n, fp) count = _IO_getwline (fp, buf, n - 1, L'\n', 1); /* If we read in some bytes and errno is EAGAIN, that error will be reported for next read. */ - if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN) - && errno != EAGAIN)) + if (count == 0 || (_IO_ferror_unlocked (fp) && errno != EAGAIN)) result = NULL; else { diff --git a/libio/tst-fgetws.c b/libio/tst-fgetws.c new file mode 100644 index 0000000000..88b6261bb8 --- /dev/null +++ b/libio/tst-fgetws.c @@ -0,0 +1,185 @@ +/* Taken from the Li18nux base test suite. */ + +#define _XOPEN_SOURCE 500 +#include <errno.h> +#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <wchar.h> + +#define WIDE_STR_LEN 32 + +int +main (int argc, char *argv[]) +{ + int i; + FILE *fp; + wchar_t *ret, wcs[WIDE_STR_LEN]; + int result = 0; + const char il_str1[] = {0xe3, 0x81, '\0'}; + const char il_str2[] = {'0', '\n', 'A', 'B', 0xe3, 0x81, 'E', '\0'}; + char name1[] = "/tmp/tst-fgetws.out.XXXXXX"; + char name2[] = "/tmp/tst-fgetws.out.XXXXXX"; + int fd; + + puts ("This program runs on de_DE.UTF-8 locale."); + if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL) + { + fprintf (stderr, "Err: Cannot run on the de_DE.UTF-8 locale"); + exit (EXIT_FAILURE); + } + + /* Make a file `il_str1'. */ + fd = mkstemp (name1); + if (fd == -1) + { + printf ("cannot open temp file: %m\n"); + exit (EXIT_FAILURE); + } + if ((fp = fdopen (fd, "w")) == NULL) + { + printf ("Can't open %s.\n", argv[1]); + exit (EXIT_FAILURE); + } + fwrite (il_str1, sizeof (char), sizeof (il_str1), fp); + fclose (fp); + + /* Make a file `il_str2'. */ + fd = mkstemp (name2); + if (fd == -1) + { + printf ("cannot open temp file: %m\n"); + exit (EXIT_FAILURE); + } + if ((fp = fdopen (fd, "w")) == NULL) + { + fprintf (stderr, "Can't open %s.\n", argv[1]); + exit (EXIT_FAILURE); + } + fwrite (il_str2, sizeof (char), sizeof (il_str2), fp); + fclose (fp); + + + /* Test for il_str1. */ + if ((fp = fopen (name1, "r")) == NULL) + { + fprintf (stderr, "Can't open %s.\n", argv[1]); + exit (EXIT_FAILURE); + } + + puts ("--"); + puts ("Read a byte sequence which is invalid as a wide character string."); + puts (" bytes: 0xe3, 0x81, '\\0'"); + + errno = 0; + ret = fgetws (wcs, WIDE_STR_LEN, fp); + + if (ret == NULL) + { + puts ("Return Value: NULL"); + + if (errno == EILSEQ) + puts ("errno = EILSEQ"); + else + { + printf ("errno = %d\n", errno); + result = 1; + } + } + else + { + printf ("Return Value: %p\n", ret); + for (i = 0; i < wcslen (wcs) + 1; i++) + printf (" wcs[%d] = %04x", i, (unsigned int)wcs[i]); + printf ("\n"); + result = 1; + } + + /* Test for il_str2. */ + if ((fp = fopen (name2, "r")) == NULL) + { + fprintf (stderr, "Can't open %s.\n", argv[1]); + exit (EXIT_FAILURE); + } + + puts ("--"); + puts ("Read a byte sequence which is invalid as a wide character string."); + puts (" bytes: '0', '\\n', 'A', 'B', 0xe3, 0x81, 'c', '\\0'"); + + errno = 0; + ret = fgetws (wcs, WIDE_STR_LEN, fp); + + if (ret == NULL) + { + puts ("Return Value: NULL"); + + if (errno == EILSEQ) + puts ("errno = EILSEQ"); + else + printf ("errno = %d\n", errno); + + result = 1; + } + else + { + int i; + + printf ("Return Value: %p\n", ret); + for (i = 0; i < wcslen (wcs) + 1; i++) + printf (" wcs[%d] = 0x%04x", i, (unsigned int)wcs[i]); + printf ("\n"); + + for (i = 0; il_str2[i] != '\n'; ++i) + if ((wchar_t) il_str2[i] != wcs[i]) + { + puts ("read string not correct"); + result = 1; + break; + } + if (il_str2[i] == '\n') + { + if (wcs[i] != L'\n') + { + puts ("newline missing"); + result = 1; + } + else if (wcs[i + 1] != L'\0') + { + puts ("read string not NUL-terminated"); + result = 1; + } + } + } + + puts ("\nsecond line"); + errno = 0; + ret = fgetws (wcs, WIDE_STR_LEN, fp); + + if (ret == NULL) + { + puts ("Return Value: NULL"); + + if (errno == EILSEQ) + puts ("errno = EILSEQ"); + else + { + printf ("errno = %d\n", errno); + result = 1; + } + } + else + { + printf ("Return Value: %p\n", ret); + for (i = 0; i < wcslen (wcs) + 1; i++) + printf (" wcs[%d] = 0x%04x", i, (unsigned int)wcs[i]); + printf ("\n"); + } + + fclose (fp); + + unlink (name1); + unlink (name2); + + return result; +} diff --git a/libio/wfileops.c b/libio/wfileops.c index 04a3f5e64f..e88c0654e5 100644 --- a/libio/wfileops.c +++ b/libio/wfileops.c @@ -157,34 +157,28 @@ _IO_wfile_underflow (fp) /* Maybe there is something left in the external buffer. */ if (fp->_IO_read_ptr < fp->_IO_read_end) { - /* Convert it. */ - size_t avail_bytes = fp->_IO_read_end - fp->_IO_read_ptr; + /* There is more in the external. Convert it. */ + const char *read_stop = (const char *) fp->_IO_read_ptr; - if (avail_bytes >= (*cd->__codecvt_do_max_length) (cd)) - { - /* There is more in the external. */ - const char *read_stop = (const char *) fp->_IO_read_ptr; - - fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; - status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, - fp->_IO_read_ptr, fp->_IO_read_end, - &read_stop, - fp->_wide_data->_IO_read_end, - fp->_wide_data->_IO_buf_end, - &fp->_wide_data->_IO_read_end); + fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; + status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, + fp->_IO_read_ptr, fp->_IO_read_end, + &read_stop, + fp->_wide_data->_IO_read_end, + fp->_wide_data->_IO_buf_end, + &fp->_wide_data->_IO_read_end); - fp->_IO_read_ptr = (char *) read_stop; + fp->_IO_read_ptr = (char *) read_stop; - /* If we managed to generate some text return the next character. */ - if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) - return *fp->_wide_data->_IO_read_ptr; + /* If we managed to generate some text return the next character. */ + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr; - if (status == __codecvt_error) - { - __set_errno (EILSEQ); - fp->_flags |= _IO_ERR_SEEN; - return WEOF; - } + if (status == __codecvt_error) + { + __set_errno (EILSEQ); + fp->_flags |= _IO_ERR_SEEN; + return WEOF; } /* Move the remaining content of the read buffer to the beginning. */ |