This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch master updated. glibc-2.16-ports-merge-383-gadb26fa


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  adb26faefe47b7d34c941cbfc193ca7a5fde8e3f (commit)
       via  4573c6b09884a93fffa3a754678ef881cadebfb3 (commit)
      from  784421e72b926d027398ee93c6c2f1ddad549c6a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=adb26faefe47b7d34c941cbfc193ca7a5fde8e3f

commit adb26faefe47b7d34c941cbfc193ca7a5fde8e3f
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Fri Sep 28 18:37:23 2012 +0530

    Don't flush write buffer for ftell
    
    [BZ #5298]
    Use write pointer state along with the file offset and/or the read
    pointers to get the current file position.

diff --git a/ChangeLog b/ChangeLog
index 255e075..7010a8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2012-09-28  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
+	[BZ #5298]
+	* libio/fileops.c (_IO_new_file_seekoff): Don't flush buffer
+	for ftell.  Compute offsets from write pointers instead.
+	* libio/wfileops.c (_IO_wfile_seekoff): Likewise.
+
+2012-09-28  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
 	[BZ #14543]
 	* libio/Makefile (tests): New test case tst-fseek.
 	* libio/tst-fseek.c: New test case to verify that fseek/ftell
diff --git a/NEWS b/NEWS
index 70ddcbe..b8a01ef 100644
--- a/NEWS
+++ b/NEWS
@@ -9,12 +9,13 @@ Version 2.17
 
 * The following bugs are resolved with this release:
 
-  1349, 3479, 5044, 5400, 6778, 6808, 9685, 9914, 10014, 10038, 11607,
-  13412, 13542, 13629, 13679, 13696, 13717, 13741, 13939, 13966, 14042,
-  14090, 14150, 14151, 14154, 14157, 14166, 14173, 14195, 14237, 14252,
-  14283, 14298, 14303, 14307, 14328, 14331, 14336, 14337, 14347, 14349,
-  14376, 14459, 14476, 14505, 14510, 14516, 14518, 14519, 14530, 14532,
-  14538, 14543, 14544, 14545, 14562, 14576, 14579, 14583, 14587, 14621.
+  1349, 3479, 5044, 5298, 5400, 6778, 6808, 9685, 9914, 10014, 10038,
+  11607, 13412, 13542, 13629, 13679, 13696, 13717, 13741, 13939, 13966,
+  14042, 14090, 14150, 14151, 14154, 14157, 14166, 14173, 14195, 14237,
+  14252, 14283, 14298, 14303, 14307, 14328, 14331, 14336, 14337, 14347,
+  14349, 14376, 14459, 14476, 14505, 14510, 14516, 14518, 14519, 14530,
+  14532, 14538, 14543, 14544, 14545, 14562, 14576, 14579, 14583, 14587,
+  14621.
 
 * Support for STT_GNU_IFUNC symbols added for s390 and s390x.
   Optimized versions of memcpy, memset, and memcmp added for System z10 and
diff --git a/libio/fileops.c b/libio/fileops.c
index e22efde..173091c 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -978,6 +978,9 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
   int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
 		       && fp->_IO_write_base == fp->_IO_write_ptr);
 
+  bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
+		      || _IO_in_put_mode (fp));
+
   if (mode == 0)
     dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
 
@@ -988,10 +991,8 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
      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-mapped files. */
-
-  if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
-    if (_IO_switch_to_get_mode (fp))
-      return EOF;
+  else if (was_writing && _IO_switch_to_get_mode (fp))
+    return EOF;
 
   if (fp->_IO_buf_base == NULL)
     {
@@ -1010,7 +1011,17 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
     {
     case _IO_seek_cur:
       /* Adjust for read-ahead (bytes is buffer). */
-      offset -= fp->_IO_read_end - fp->_IO_read_ptr;
+      if (mode != 0 || !was_writing)
+	offset -= fp->_IO_read_end - fp->_IO_read_ptr;
+      else
+	{
+	  /* _IO_read_end coincides with fp._offset, so the actual file position
+	     is fp._offset - (_IO_read_end - new_write_ptr).  This is fine
+	     even if fp._offset is not set, since fp->_IO_read_end is then at
+	     _IO_buf_base and this adjustment is for unbuffered output.  */
+	  offset -= fp->_IO_read_end - fp->_IO_write_ptr;
+	}
+
       if (fp->_offset == _IO_pos_BAD)
 	{
 	  if (mode != 0)
diff --git a/libio/wfileops.c b/libio/wfileops.c
index d3f46b2..1087e8d 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -613,6 +613,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
 		       && (fp->_wide_data->_IO_write_base
 			   == fp->_wide_data->_IO_write_ptr));
 
+  bool was_writing = ((fp->_wide_data->_IO_write_ptr
+		       > fp->_wide_data->_IO_write_base)
+		      || _IO_in_put_mode (fp));
+
   if (mode == 0)
     {
       /* XXX For wide stream with backup store it is not very
@@ -644,11 +648,8 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
      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-mapped files. */
-
-  if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
-      || _IO_in_put_mode (fp))
-    if (_IO_switch_to_wget_mode (fp))
-      return WEOF;
+  else if (was_writing && _IO_switch_to_wget_mode (fp))
+    return WEOF;
 
   if (fp->_wide_data->_IO_buf_base == NULL)
     {
@@ -679,29 +680,104 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
       cv = fp->_codecvt;
       clen = (*cv->__codecvt_do_encoding) (cv);
 
-      if (clen > 0)
+      if (mode != 0 || !was_writing)
 	{
-	  offset -= (fp->_wide_data->_IO_read_end
-		     - fp->_wide_data->_IO_read_ptr) * clen;
-	  /* Adjust by readahead in external buffer.  */
-	  offset -= fp->_IO_read_end - fp->_IO_read_ptr;
+	  if (clen > 0)
+	    {
+	      offset -= (fp->_wide_data->_IO_read_end
+			 - fp->_wide_data->_IO_read_ptr) * clen;
+	      /* Adjust by readahead in external buffer.  */
+	      offset -= fp->_IO_read_end - fp->_IO_read_ptr;
+	    }
+	  else
+	    {
+	      int nread;
+
+	    flushed:
+	      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;
+	    }
 	}
       else
 	{
-	  int nread;
+	  char *new_write_ptr = fp->_IO_write_ptr;
 
-	  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;
+	  if (clen > 0)
+	    offset += (fp->_wide_data->_IO_write_ptr
+		       - fp->_wide_data->_IO_write_base) / clen;
+	  else
+	    {
+	      enum __codecvt_result status;
+	      delta = (fp->_wide_data->_IO_write_ptr
+		       - fp->_wide_data->_IO_write_base);
+	      const wchar_t *write_base = fp->_wide_data->_IO_write_base;
+
+	      /* FIXME: This actually ends up in two iterations of conversion,
+		 one here and the next when the buffer actually gets flushed.
+		 It may be possible to optimize this in future so that
+		 wdo_write identifies already converted content and does not
+		 redo it.  In any case, this is much better than having to
+		 flush buffers for every ftell.  */
+	      do
+		{
+		  /* Ugh, no point trying to avoid the flush.  Just do it
+		     and go back to how it was with the read mode.  */
+		  if (delta > 0 && new_write_ptr == fp->_IO_buf_end)
+		    {
+		      if (_IO_switch_to_wget_mode (fp))
+			return WEOF;
+		      goto flushed;
+		    }
+
+		  const wchar_t *new_wbase = fp->_wide_data->_IO_write_base;
+		  fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
+		  status = (*cv->__codecvt_do_out) (cv,
+						    &fp->_wide_data->_IO_state,
+						    write_base,
+						    write_base + delta,
+						    &new_wbase,
+						    new_write_ptr,
+						    fp->_IO_buf_end,
+						    &new_write_ptr);
+
+		  delta -= new_wbase - write_base;
+
+		  /* If there was an error, then return WEOF.
+		     TODO: set buffer state.  */
+		  if (__builtin_expect (status == __codecvt_error, 0))
+		      return WEOF;
+		}
+	      while (delta > 0);
+	    }
+
+	  /* _IO_read_end coincides with fp._offset, so the actual file position
+	     is fp._offset - (_IO_read_end - new_write_ptr).  This is fine
+	     even if fp._offset is not set, since fp->_IO_read_end is then at
+	     _IO_buf_base and this adjustment is for unbuffered output.  */
+	  offset -= fp->_IO_read_end - new_write_ptr;
 	}
 
       if (fp->_offset == _IO_pos_BAD)
-	goto dumb;
+	{
+	  if (mode != 0)
+	    goto dumb;
+	  else
+	    {
+	      result = _IO_SYSSEEK (fp, 0, dir);
+	      if (result == EOF)
+		return result;
+	      fp->_offset = result;
+	    }
+	}
+
       /* Make offset absolute, assuming current pointer is file_ptr(). */
       offset += fp->_offset;
 

http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4573c6b09884a93fffa3a754678ef881cadebfb3

commit 4573c6b09884a93fffa3a754678ef881cadebfb3
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Fri Sep 28 18:20:40 2012 +0530

    Adjust wide data buffer pointers during fseek and ftell
    
    [BZ #14543]
    Set the internal buffer state correctly whenever the external buffer
    state is modified by fseek by either computing the current
    _IO_read_ptr/end for the internal buffer based on the new _IO_read_ptr
    in the external buffer or converting the content read into the
    external buffer, up to the extent of the requested fseek offset.

diff --git a/ChangeLog b/ChangeLog
index 3004989..255e075 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2012-09-28  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[BZ #14543]
+	* libio/Makefile (tests): New test case tst-fseek.
+	* libio/tst-fseek.c: New test case to verify that fseek/ftell
+	combination works in wide mode.
+	* libio/wfileops.c (_IO_wfile_seekoff): Adjust internal buffer
+	state when the external buffer state changes.
+
 2012-09-27  David S. Miller  <davem@davemloft.net>
 
 	[BZ #14376]
diff --git a/NEWS b/NEWS
index c0a671d..70ddcbe 100644
--- a/NEWS
+++ b/NEWS
@@ -14,7 +14,7 @@ Version 2.17
   14090, 14150, 14151, 14154, 14157, 14166, 14173, 14195, 14237, 14252,
   14283, 14298, 14303, 14307, 14328, 14331, 14336, 14337, 14347, 14349,
   14376, 14459, 14476, 14505, 14510, 14516, 14518, 14519, 14530, 14532,
-  14538, 14544, 14545, 14562, 14576, 14579, 14583, 14587, 14621.
+  14538, 14543, 14544, 14545, 14562, 14576, 14579, 14583, 14587, 14621.
 
 * Support for STT_GNU_IFUNC symbols added for s390 and s390x.
   Optimized versions of memcpy, memset, and memcmp added for System z10 and
diff --git a/libio/Makefile b/libio/Makefile
index e2a7efd..0d28cea 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -59,7 +59,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-fgetwc bug-wsetpos bug-fclose1
+	tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos bug-fclose1 tst-fseek
 ifeq (yes,$(build-shared))
 # Add test-fopenloc only if shared library is enabled since it depends on
 # shared localedata objects.
@@ -158,6 +158,7 @@ bug-ungetwc2-ENV = LOCPATH=$(common-objpfx)localedata
 tst-swscanf-ENV = LOCPATH=$(common-objpfx)localedata
 bug-ftell-ENV = LOCPATH=$(common-objpfx)localedata
 tst-fgetwc-ENV = LOCPATH=$(common-objpfx)localedata
+tst-fseek-ENV = LOCPATH=$(common-objpfx)localedata
 
 generated = tst-fopenloc.mtrace tst-fopenloc.check
 
diff --git a/libio/tst-fseek.c b/libio/tst-fseek.c
new file mode 100644
index 0000000..457a087
--- /dev/null
+++ b/libio/tst-fseek.c
@@ -0,0 +1,173 @@
+/* Verify that fseek/ftell combination works for wide chars.
+   Copyright (C) 2012 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <errno.h>
+#include <wchar.h>
+#include <unistd.h>
+#include <string.h>
+
+/* Defined in test-skeleton.c.  */
+static int create_temp_file (const char *base, char **filename);
+
+
+static int
+do_seek_end (FILE *fp)
+{
+  long save;
+
+  if (fputws (L"abc\n", fp) == -1)
+    {
+      printf ("do_seek_end: fputws: %s\n", strerror (errno));
+      return 1;
+    }
+
+  save = ftell (fp);
+  rewind (fp);
+
+  if (fseek (fp, 0, SEEK_END) == -1)
+    {
+      printf ("do_seek_end: fseek: %s\n", strerror (errno));
+      return 1;
+    }
+
+  if (save != ftell (fp))
+    {
+      printf ("save = %ld, ftell = %ld\n", save, ftell (fp));
+      return 1;
+    }
+
+  return 0;
+}
+
+int
+do_seek_set (FILE *fp)
+{
+  long save1, save2;
+
+  if (fputws (L"ã??ã??\n", fp) == -1)
+    {
+      printf ("seek_set: fputws(1): %s\n", strerror (errno));
+      return 1;
+    }
+
+  save1 = ftell (fp);
+
+  if (fputws (L"ã??ã??\n", fp) == -1)
+    {
+      printf ("seek_set: fputws(2): %s\n", strerror (errno));
+      return 1;
+    }
+
+  save2 = ftell (fp);
+
+  if (fputws (L"ã??ã??\n", fp) == -1)
+    {
+      printf ("seek_set: fputws(3): %s\n", strerror (errno));
+      return 1;
+    }
+
+  if (fseek (fp, save1, SEEK_SET) == -1)
+    {
+      printf ("seek_set: fseek(1): %s\n", strerror (errno));
+      return 1;
+    }
+
+  if (save1 != ftell (fp))
+    {
+      printf ("save1 = %ld, ftell = %ld\n", save1, ftell (fp));
+      return 1;
+    }
+
+  if (fseek (fp, save2, SEEK_SET) == -1)
+    {
+      printf ("seek_set: fseek(2): %s\n", strerror (errno));
+      return 1;
+    }
+
+  if (save2 != ftell (fp))
+    {
+      printf ("save2 = %ld, ftell = %ld\n", save2, ftell (fp));
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  if (setlocale (LC_ALL, "ja_JP.UTF-8") == NULL)
+    {
+      printf ("Cannot set ja_JP.UTF-8 locale.\n");
+      exit (1);
+    }
+
+  /* Retain messages in English.  */
+  if (setlocale (LC_MESSAGES, "en_US.ISO-8859-1") == NULL)
+    {
+      printf ("Cannot set LC_MESSAGES to en_US.ISO-8859-1 locale.\n");
+      exit (1);
+    }
+
+  int ret = 0;
+  char *filename;
+  int fd = create_temp_file ("tst-fseek.out", &filename);
+
+  if (fd == -1)
+    return 1;
+
+  FILE *fp = fdopen (fd, "w+");
+  if (fp == NULL)
+    {
+      printf ("seek_set: fopen: %s\n", strerror (errno));
+      close (fd);
+      return 1;
+    }
+
+  if (do_seek_set (fp))
+    {
+      printf ("SEEK_SET test failed\n");
+      ret = 1;
+    }
+
+  /* Reopen the file.  */
+  fclose (fp);
+  fp = fopen (filename, "w+");
+  if (fp == NULL)
+    {
+      printf ("seek_end: fopen: %s\n", strerror (errno));
+      return 1;
+    }
+
+  if (do_seek_end (fp))
+    {
+      printf ("SEEK_END test failed\n");
+      ret = 1;
+    }
+
+  fclose (fp);
+
+  return ret;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libio/wfileops.c b/libio/wfileops.c
index b790029..d3f46b2 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -545,6 +545,57 @@ _IO_wfile_sync (fp)
 }
 libc_hidden_def (_IO_wfile_sync)
 
+/* Adjust the internal buffer pointers to reflect the state in the external
+   buffer.  The content between fp->_IO_read_base and fp->_IO_read_ptr is
+   assumed to be converted and available in the range
+   fp->_wide_data->_IO_read_base and fp->_wide_data->_IO_read_end.
+
+   Returns 0 on success and -1 on error with the _IO_ERR_SEEN flag set.  */
+static inline int
+adjust_wide_data (_IO_FILE *fp, bool do_convert)
+{
+  struct _IO_codecvt *cv = fp->_codecvt;
+
+  int clen = (*cv->__codecvt_do_encoding) (cv);
+
+  /* Take the easy way out for constant length encodings if we don't need to
+     convert.  */
+  if (!do_convert && clen > 0)
+    {
+      fp->_wide_data->_IO_read_end += ((fp->_IO_read_ptr - fp->_IO_read_base)
+				       / clen);
+      goto done;
+    }
+
+  enum __codecvt_result status;
+  const char *read_stop = (const char *) fp->_IO_read_base;
+  do
+    {
+
+      fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
+      status = (*cv->__codecvt_do_in) (cv, &fp->_wide_data->_IO_state,
+				       fp->_IO_read_base, fp->_IO_read_ptr,
+				       &read_stop,
+				       fp->_wide_data->_IO_read_base,
+				       fp->_wide_data->_IO_buf_end,
+				       &fp->_wide_data->_IO_read_end);
+
+      /* Should we return EILSEQ?  */
+      if (__builtin_expect (status == __codecvt_error, 0))
+	{
+	  fp->_flags |= _IO_ERR_SEEN;
+	  return -1;
+	}
+    }
+  while (__builtin_expect (status == __codecvt_partial, 0));
+
+done:
+  /* Now seek to _IO_read_end to behave as if we have read it all in.  */
+  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
+
+  return 0;
+}
+
 _IO_off64_t
 _IO_wfile_seekoff (fp, offset, dir, mode)
      _IO_FILE *fp;
@@ -693,6 +744,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
 		     fp->_wide_data->_IO_buf_base);
 	  _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
 		     fp->_wide_data->_IO_buf_base);
+
+	  if (adjust_wide_data (fp, false))
+	    goto dumb;
+
 	  _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
 	  goto resync;
 	}
@@ -733,6 +788,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
   _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);
+
+  if (adjust_wide_data (fp, true))
+    goto dumb;
+
   fp->_offset = result + count;
   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
   return offset;

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog         |   16 +++++
 NEWS              |   13 ++--
 libio/Makefile    |    3 +-
 libio/fileops.c   |   21 +++++--
 libio/tst-fseek.c |  173 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 libio/wfileops.c  |  175 +++++++++++++++++++++++++++++++++++++++++++++++------
 6 files changed, 369 insertions(+), 32 deletions(-)
 create mode 100644 libio/tst-fseek.c


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]