From 40a982a9e1b825b175be7bc7c7199c6bdf363e4b Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 9 Aug 2001 08:50:50 +0000 Subject: Update. 2001-08-09 Ulrich Drepper * libio/wfileops.c (_IO_wfile_seekoff): Don't even try to handle seeking with backup buffer present. Correct determining of internal buffer position. Reset also wide buffers if we reset the internal buffers. * libio/iofwide.c (_IO_fwide): Always determine file offset for wide streams. * libio/ioseekoff.c: Catch one unimplemented case. * libio/ftello.c: Don't abort if the wide stream has backup buffer. * libio/ftello64.c: Likewise. * libio/iofgetpos.c: Likewise. * libio/iofgetpos64.c: Likewise. * libio/ftell.c: Likewise. * libio/Makefile (tests): Add tst-ungetwc2. * libio/tst-ungetwc2.c: New file. --- ChangeLog | 17 +++++++++++ libio/Makefile | 3 +- libio/ftello.c | 5 +--- libio/ftello64.c | 4 +-- libio/iofgetpos.c | 5 +--- libio/iofgetpos64.c | 7 +++-- libio/ioftell.c | 5 +--- libio/iofwide.c | 6 ++++ libio/ioseekoff.c | 10 +++++-- libio/tst-ungetwc2.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libio/wfileops.c | 32 +++++++++++++++++++-- 11 files changed, 152 insertions(+), 23 deletions(-) create mode 100644 libio/tst-ungetwc2.c diff --git a/ChangeLog b/ChangeLog index 10d448bb8d..9564547127 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2001-08-09 Ulrich Drepper + + * libio/wfileops.c (_IO_wfile_seekoff): Don't even try to handle + seeking with backup buffer present. + Correct determining of internal buffer position. + Reset also wide buffers if we reset the internal buffers. + * libio/iofwide.c (_IO_fwide): Always determine file offset for wide + streams. + * libio/ioseekoff.c: Catch one unimplemented case. + * libio/ftello.c: Don't abort if the wide stream has backup buffer. + * libio/ftello64.c: Likewise. + * libio/iofgetpos.c: Likewise. + * libio/iofgetpos64.c: Likewise. + * libio/ftell.c: Likewise. + * libio/Makefile (tests): Add tst-ungetwc2. + * libio/tst-ungetwc2.c: New file. + 2001-08-08 Ulrich Drepper * locale/elem-hash.h (elem_hash): Correct stupid mistake and diff --git a/libio/Makefile b/libio/Makefile index 97a8f73e13..14eaefcf90 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -48,7 +48,7 @@ routines := \ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-fopenloc \ - tst-fgetws tst-ungetwc1 + tst-fgetws tst-ungetwc1 tst-ungetwc2 test-srcs = test-freopen all: # Make this the default target; it will be defined in Rules. @@ -85,6 +85,7 @@ tst-fopenloc-ENV = LOCPATH=$(common-objpfx)localedata \ MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace tst-fgetws-ENV = LOCPATH=$(common-objpfx)localedata tst-ungetwc1-ENV = LOCPATH=$(common-objpfx)localedata +tst-ungetwc2-ENV = LOCPATH=$(common-objpfx)localedata generated = tst-fopenloc.mtrace tst-fopenloc.check diff --git a/libio/ftello.c b/libio/ftello.c index 1d030511dd..6c1f1a670f 100644 --- a/libio/ftello.c +++ b/libio/ftello.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2000, 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 @@ -44,9 +44,6 @@ ftello (fp) { if (fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; - else - /* XXX Not done yet. */ - abort (); } _IO_funlockfile (fp); _IO_cleanup_region_end (0); diff --git a/libio/ftello64.c b/libio/ftello64.c index adc1385e1b..cd0670f1f4 100644 --- a/libio/ftello64.c +++ b/libio/ftello64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2000, 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 @@ -45,8 +45,6 @@ ftello64 (fp) { if (fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; - else - abort (); } _IO_funlockfile (fp); _IO_cleanup_region_end (0); diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c index b8b2f874a3..cc7d9e9755 100644 --- a/libio/iofgetpos.c +++ b/libio/iofgetpos.c @@ -43,11 +43,8 @@ _IO_new_fgetpos (fp, posp) pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); if (_IO_in_backup (fp)) { - if (fp->_vtable_offset != 0 || fp->_mode <= 0) + if (fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; - else - /* XXX For now. */ - abort (); } if (pos == _IO_pos_BAD) { diff --git a/libio/iofgetpos64.c b/libio/iofgetpos64.c index 3f29337c7d..179071894e 100644 --- a/libio/iofgetpos64.c +++ b/libio/iofgetpos64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2000, 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 @@ -42,7 +42,10 @@ _IO_new_fgetpos64 (fp, posp) _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); if (_IO_in_backup (fp)) - pos -= fp->_IO_save_end - fp->_IO_save_base; + { + if (fp->_mode <= 0) + pos -= fp->_IO_save_end - fp->_IO_save_base; + } _IO_funlockfile (fp); _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) diff --git a/libio/ioftell.c b/libio/ioftell.c index 59c8288043..f2abd62ad8 100644 --- a/libio/ioftell.c +++ b/libio/ioftell.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995-2000, 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 @@ -43,9 +43,6 @@ _IO_ftell (fp) { if (fp->_vtable_offset != 0 || fp->_mode <= 0) pos -= fp->_IO_save_end - fp->_IO_save_base; - else - /* XXX For now. */ - abort (); } _IO_funlockfile (fp); _IO_cleanup_region_end (0); diff --git a/libio/iofwide.c b/libio/iofwide.c index aa314fe671..88d2d5e563 100644 --- a/libio/iofwide.c +++ b/libio/iofwide.c @@ -201,6 +201,12 @@ _IO_fwide (fp, mode) /* From now on use the wide character callback functions. */ ((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable; + + /* One last twist: we get the current stream position. The wide + char streams have much more problems with not knowing the + current position and so we should disable the optimization + which allows the functions without knowing the position. */ + fp->_offset = _IO_SYSSEEK (fp, 0, 0); } /* Set the mode now. */ diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c index 60249694c0..2111bec745 100644 --- a/libio/ioseekoff.c +++ b/libio/ioseekoff.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998, 1999, 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 @@ -25,6 +25,7 @@ This exception applies to code released by its copyright holders in files containing the exception. */ +#include #include #include #ifndef errno @@ -58,7 +59,12 @@ _IO_seekoff (fp, offset, dir, mode) if (mode != 0 && _IO_have_backup (fp)) { if (dir == _IO_seek_cur && _IO_in_backup (fp)) - offset -= fp->_IO_read_end - fp->_IO_read_ptr; + { + if (fp->_vtable_offset != 0 || fp->_mode <= 0) + offset -= fp->_IO_read_end - fp->_IO_read_ptr; + else + abort (); + } _IO_free_backup_area (fp); } diff --git a/libio/tst-ungetwc2.c b/libio/tst-ungetwc2.c new file mode 100644 index 0000000000..9064427532 --- /dev/null +++ b/libio/tst-ungetwc2.c @@ -0,0 +1,81 @@ +/* Taken from the Li18nux base test suite. */ + +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include + +int +main (void) +{ + FILE *fp; + char *str = "abcdef"; + wint_t ret, wc; + char fname[] = "/tmp/tst-ungetwc2.out.XXXXXX"; + int fd; + long int pos; + int result = 0; + + puts ("This program runs on en_US.UTF-8 locale."); + if (setlocale (LC_ALL, "en_US.UTF-8") == NULL) + { + fprintf (stderr, "Err: Cannot run on the en_US.UTF-8 locale\n"); + exit (EXIT_FAILURE); + } + + /* Write some characters to `testfile'. */ + fd = mkstemp (fname); + if (fd == -1) + { + printf ("cannot open temp file: %m\n"); + exit (EXIT_FAILURE); + } + if ((fp = fdopen (fd, "w")) == NULL) + { + fprintf (stderr, "Cannot open 'testfile'.\n"); + exit (EXIT_FAILURE); + } + fputs (str, fp); + fclose (fp); + + /* Open `testfile'. */ + if ((fp = fopen (fname, "r")) == NULL) + { + fprintf (stderr, "Cannot open 'testfile'."); + exit (EXIT_FAILURE); + } + + /* Get a character. */ + wc = getwc (fp); + pos = ftell (fp); + printf ("After get a character: %ld\n", pos); + if (pos != 1) + result = 1; + + /* Unget a character. */ + ret = ungetwc (wc, fp); + if (ret == WEOF) + { + fprintf (stderr, "ungetwc() returns NULL."); + exit (EXIT_FAILURE); + } + pos = ftell (fp); + printf ("After unget a character: %ld\n", pos); + if (pos != 0) + result = 1; + + /* Reget a character. */ + wc = getwc (fp); + pos = ftell (fp); + printf ("After reget a character: %ld\n", pos); + if (pos != 1) + result = 1; + + fclose (fp); + + unlink (fname); + + return result; +} diff --git a/libio/wfileops.c b/libio/wfileops.c index e88c0654e5..92d1a08190 100644 --- a/libio/wfileops.c +++ b/libio/wfileops.c @@ -458,7 +458,28 @@ _IO_wfile_seekoff (fp, offset, dir, mode) == fp->_wide_data->_IO_write_ptr)); if (mode == 0) - dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */ + { + /* XXX For wide stream with backup store it is not very + reasonable to determine the offset. The pushed-back + character might require a state change and we need not be + able to compute the initial state by reverse transformation + since there is no guarantee of symmetry. So we don't even + try and return an error. */ + if (_IO_in_backup (fp)) + { + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + { + __set_errno (EINVAL); + return -1; + } + + /* There is no more data in the backup buffer. We can + switch back. */ + _IO_switch_to_main_wget_area (fp); + } + + dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */ + } /* Flush unwritten characters. (This may do an unneeded write if we seek within the buffer. @@ -466,7 +487,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode) egptr to ptr. That can't be done in the current design, which assumes file_ptr() is eGptr. Anyway, since we probably end up flushing when we close(), it doesn't make much difference.) - FIXME: simulate mem-papped files. */ + FIXME: simulate mem-mapped files. */ if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base || _IO_in_put_mode (fp)) @@ -509,12 +530,13 @@ _IO_wfile_seekoff (fp, offset, dir, mode) { int nread; - delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end; + delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base; fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state, fp->_IO_read_base, fp->_IO_read_end, delta); fp->_IO_read_ptr = fp->_IO_read_base + nread; + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr; offset -= fp->_IO_read_end - fp->_IO_read_base - nread; } @@ -651,6 +673,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode) fp->_offset = result; _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); + _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, + fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base); + _IO_wsetp (fp, fp->_wide_data->_IO_buf_base, + fp->_wide_data->_IO_buf_base); } return result; -- cgit 1.4.1