This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

Re: Weak functions on powerpc64-linux


On Tue, Feb 26, 2002 at 03:57:56PM -0800, Richard Henderson wrote:
> On Tue, Feb 26, 2002 at 09:51:21PM +1030, Alan Modra wrote:
> >  struct weak_syms
> >  {
> >    struct weak_syms * next;
> > +  const tree decl;
> 
> Generally ok, but you're going to need to mark this for
> garbage collection.

Thanks for the tip.  Here's a revised diff, which also takes note of
David's suggestion regarding moving ASM_WEAKEN_DECL to rs6000.h.

	* doc/tm.texi (ASM_WEAKEN_DECL): Document.
	(ASM_WEAKEN_LABEL): Mention ASM_WEAKEN_DECL.
	(SUPPORTS_WEAK): Likewise.
	* output.h (add_weak): Add tree param.
	* varasm.c (add_weak): Likewise.  Save decl.
	(struct weak_syms): Add decl field.
	(mark_weak_decls): New function.
	(init_varasm_once): ggc_add_root mark_weak_decls.
	(assemble_start_function): Use ASM_WEAKEN_DECL.
	(assemble_variable): Likewise.
	(assemble_alias): Likewise.
	(declare_weak): Pass decl to add_weak.
	(weak_finish): Use ASM_WEAKEN_DECL. Try to find decl.
	(remove_from_pending_weak_list): Declare and define for
	ASM_WEAKEN_DECL.
	* c-pragma.c (handle_pragma_weak): Adjust add_weak call.
	* c-pragma.h (HANDLE_PRAGMA_WEAK): Define if ASM_WEAKEN_DECL too.
	* defaults.h (SUPPORTS_WEAK): Likewise.
	* config/rs6000/linux64.h (ASM_DECLARE_FUNCTION_NAME): Don't emit
	.weak for code sym.  Do emit .size for descriptor sym.
	(ASM_DECLARE_FUNCTION_SIZE): Define.
	(ASM_OUTPUT_DEF_FROM_DECLS): Define.
	* config/rs6000/rs6000.h (ASM_WEAKEN_DECL): Define.
	(ASM_OUTPUT_DEF_FROM_DECLS): Constify name.  Don't emit .weak here.

Tested on powerpc64-linux.  powerpc-linux bootstrap in progress.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/doc/tm.texi gcc-ppc64-31/gcc/doc/tm.texi
--- gcc-ppc64-31.orig/gcc/doc/tm.texi	Mon Feb 18 15:29:55 2002
+++ gcc-ppc64-31/gcc/doc/tm.texi	Thu Feb 28 00:19:05 2002
@@ -6174,7 +6174,7 @@ itself; before and after that, output th
 for making that name global, and a newline.
 
 @findex ASM_WEAKEN_LABEL
-@item ASM_WEAKEN_LABEL
+@item ASM_WEAKEN_LABEL (@var{stream}, @var{name})
 A C statement (sans semicolon) to output to the stdio stream
 @var{stream} some commands that will make the label @var{name} weak;
 that is, available for reference from other files but only used if
@@ -6183,18 +6183,29 @@ no other definition is available.  Use t
 itself; before and after that, output the additional assembler syntax
 for making that name weak, and a newline.
 
-If you don't define this macro, GCC will not support weak
-symbols and you should not define the @code{SUPPORTS_WEAK} macro.
+If you don't define this macro or @code{ASM_WEAKEN_DECL}, GCC will not
+support weak symbols and you should not define the @code{SUPPORTS_WEAK}
+macro.
+
+@findex ASM_WEAKEN_DECL
+@item ASM_WEAKEN_DECL (@var{stream}, @var{decl}, @var{name}, @var{value})
+Combines (and replaces) the function of @code{ASM_WEAKEN_LABEL} and
+@code{ASM_OUTPUT_WEAK_ALIAS}, allowing access to the associated function
+or variable decl.  If @var{value} is not @code{NULL}, this C statement
+should output to the stdio stream @var{stream} assembler code which
+defines (equates) the weak symbol @var{name} to have the value
+@var{value}.  If @var{value} is @code{NULL}, it should output commands
+to make @var{name} weak.
 
 @findex SUPPORTS_WEAK
 @item SUPPORTS_WEAK
 A C expression which evaluates to true if the target supports weak symbols.
 
 If you don't define this macro, @file{defaults.h} provides a default
-definition.  If @code{ASM_WEAKEN_LABEL} is defined, the default
-definition is @samp{1}; otherwise, it is @samp{0}.  Define this macro if
-you want to control weak symbol support with a compiler flag such as
-@option{-melf}.
+definition.  If either @code{ASM_WEAKEN_LABEL} or @code{ASM_WEAKEN_DECL}
+is defined, the default definition is @samp{1}; otherwise, it is
+@samp{0}.  Define this macro if you want to control weak symbol support
+with a compiler flag such as @option{-melf}.
 
 @findex MAKE_DECL_ONE_ONLY (@var{decl})
 @item MAKE_DECL_ONE_ONLY
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/c-pragma.c gcc-ppc64-31/gcc/c-pragma.c
--- gcc-ppc64-31.orig/gcc/c-pragma.c	Thu Nov 15 22:39:42 2001
+++ gcc-ppc64-31/gcc/c-pragma.c	Tue Feb 26 18:44:39 2002
@@ -298,7 +298,8 @@ handle_pragma_weak (dummy)
   if (t != CPP_EOF)
     warning ("junk at end of #pragma weak");
 
-  add_weak (IDENTIFIER_POINTER (name), value ? IDENTIFIER_POINTER (value) : 0);
+  add_weak (NULL_TREE, IDENTIFIER_POINTER (name),
+	    value ? IDENTIFIER_POINTER (value) : NULL);
 }
 #endif
 
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/c-pragma.h gcc-ppc64-31/gcc/c-pragma.h
--- gcc-ppc64-31.orig/gcc/c-pragma.h	Sun Jan 20 00:11:57 2002
+++ gcc-ppc64-31/gcc/c-pragma.h	Thu Feb 28 00:19:11 2002
@@ -23,9 +23,8 @@ Software Foundation, 59 Temple Place - S
 #define GCC_C_PRAGMA_H
 
 #ifdef HANDLE_SYSV_PRAGMA
-/* Support #pragma weak iff ASM_WEAKEN_LABEL and ASM_OUTPUT_WEAK_ALIAS are
-   defined.  */
-#if defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_WEAK_ALIAS)
+#if ((defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_WEAK_ALIAS)) \
+     || defined (ASM_WEAKEN_DECL))
 #define HANDLE_PRAGMA_WEAK SUPPORTS_WEAK
 #endif
 
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/defaults.h gcc-ppc64-31/gcc/defaults.h
--- gcc-ppc64-31.orig/gcc/defaults.h	Tue Dec 18 11:27:10 2001
+++ gcc-ppc64-31/gcc/defaults.h	Thu Feb 28 00:19:10 2002
@@ -158,7 +158,7 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNA
 
 /* This determines whether or not we support weak symbols.  */
 #ifndef SUPPORTS_WEAK
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
 #define SUPPORTS_WEAK 1
 #else
 #define SUPPORTS_WEAK 0
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/output.h gcc-ppc64-31/gcc/output.h
--- gcc-ppc64-31.orig/gcc/output.h	Mon Feb 18 15:28:24 2002
+++ gcc-ppc64-31/gcc/output.h	Wed Feb 27 21:43:29 2002
@@ -137,7 +137,7 @@ extern const char *get_insn_template PAR
 
 /* Add function NAME to the weak symbols list.  VALUE is a weak alias
    associated with NAME.  */
-extern int add_weak PARAMS ((const char *, const char *));
+extern int add_weak PARAMS ((tree, const char *, const char *));
 
 /* Functions in flow.c */
 extern void allocate_for_life_analysis	PARAMS ((void));
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/varasm.c gcc-ppc64-31/gcc/varasm.c
--- gcc-ppc64-31.orig/gcc/varasm.c	Thu Feb 21 10:49:53 2002
+++ gcc-ppc64-31/gcc/varasm.c	Thu Feb 28 00:19:08 2002
@@ -42,6 +42,7 @@ Software Foundation, 59 Temple Place - S
 #include "obstack.h"
 #include "hashtab.h"
 #include "c-pragma.h"
+#include "c-tree.h"
 #include "ggc.h"
 #include "langhooks.h"
 #include "tm_p.h"
@@ -166,7 +167,8 @@ static unsigned HOST_WIDE_INT array_size
 static unsigned min_align		PARAMS ((unsigned, unsigned));
 static void output_constructor		PARAMS ((tree, HOST_WIDE_INT,
 						 unsigned int));
-#ifdef ASM_WEAKEN_LABEL
+static void mark_weak_decls		PARAMS ((void *));
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
 static void remove_from_pending_weak_list	PARAMS ((const char *));
 #endif
 static int in_named_entry_eq		PARAMS ((const PTR, const PTR));
@@ -1237,10 +1239,14 @@ assemble_start_function (decl, fnname)
 	    weak_global_object_name = name;
 	}
 
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
       if (DECL_WEAK (decl))
 	{
+#ifdef ASM_WEAKEN_DECL
+	  ASM_WEAKEN_DECL (asm_out_file, decl, fnname, 0);
+#else
 	  ASM_WEAKEN_LABEL (asm_out_file, fnname);
+#endif
 	  /* Remove this function from the pending weak list so that
 	     we do not emit multiple .weak directives for it.  */
 	  remove_from_pending_weak_list
@@ -1644,10 +1650,14 @@ assemble_variable (decl, top_level, at_e
   /* First make the assembler name(s) global if appropriate.  */
   if (TREE_PUBLIC (decl) && DECL_NAME (decl))
     {
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
       if (DECL_WEAK (decl))
 	{
+#ifdef ASM_WEAKEN_DECL
+	  ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
+#else
 	  ASM_WEAKEN_LABEL (asm_out_file, name);
+#endif
 	   /* Remove this variable from the pending weak list so that
 	      we do not emit multiple .weak directives for it.  */
 	  remove_from_pending_weak_list
@@ -5012,17 +5022,41 @@ output_constructor (exp, size, align)
 struct weak_syms
 {
   struct weak_syms * next;
+  tree decl;
   const char * name;
   const char * value;
 };
 
 static struct weak_syms * weak_decls;
 
+/* Mark weak_decls for garbage collection.  */
+
+static void
+mark_weak_decls (arg)
+     void *arg;
+{
+  struct weak_syms *t;
+
+  for (t = *(struct weak_syms **) arg; t != NULL; t = t->next)
+    {
+      tree decl = t->decl;
+      if (decl == NULL_TREE)
+	{
+	  tree name = get_identifier (t->name);
+	  if (name)
+	    decl = lookup_name (name);
+	  t->decl = decl;
+	}
+      ggc_mark_tree (decl);
+    }
+}
+
 /* Add function NAME to the weak symbols list.  VALUE is a weak alias
    associated with NAME.  */
 
 int
-add_weak (name, value)
+add_weak (decl, name, value)
+     tree decl;
      const char *name;
      const char *value;
 {
@@ -5034,6 +5068,7 @@ add_weak (name, value)
     return 0;
 
   weak->next = weak_decls;
+  weak->decl = decl;
   weak->name = name;
   weak->value = value;
   weak_decls = weak;
@@ -5052,7 +5087,7 @@ declare_weak (decl)
   else if (TREE_ASM_WRITTEN (decl))
     error_with_decl (decl, "weak declaration of `%s' must precede definition");
   else if (SUPPORTS_WEAK)
-    add_weak (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), NULL);
+    add_weak (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), NULL);
   else
     warning_with_decl (decl, "weak declaration of `%s' not supported");
 
@@ -5067,8 +5102,18 @@ weak_finish ()
   if (SUPPORTS_WEAK)
     {
       struct weak_syms *t;
-      for (t = weak_decls; t; t = t->next)
+      for (t = weak_decls; t != NULL; t = t->next)
 	{
+#ifdef ASM_WEAKEN_DECL
+	  tree decl = t->decl;
+	  if (decl == NULL_TREE)
+	    {
+	      tree name = get_identifier (t->name);
+	      if (name)
+		decl = lookup_name (name);
+	    }
+	  ASM_WEAKEN_DECL (asm_out_file, decl, t->name, t->value);
+#else
 #ifdef ASM_OUTPUT_WEAK_ALIAS
 	  ASM_OUTPUT_WEAK_ALIAS (asm_out_file, t->name, t->value);
 #else
@@ -5078,6 +5123,7 @@ weak_finish ()
 	  ASM_WEAKEN_LABEL (asm_out_file, t->name);
 #endif
 #endif
+#endif
 	}
     }
 }
@@ -5085,7 +5131,7 @@ weak_finish ()
 /* Remove NAME from the pending list of weak symbols.  This prevents
    the compiler from emitting multiple .weak directives which confuses
    some assemblers.  */
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
 static void
 remove_from_pending_weak_list (name)
      const char *name;
@@ -5105,7 +5151,7 @@ remove_from_pending_weak_list (name)
         p = &(t->next);
     }
 }
-#endif /* ASM_WEAKEN_LABEL */
+#endif /* defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL) */
 
 /* Emit an assembler directive to make the symbol for DECL an alias to
    the symbol for TARGET.  */
@@ -5127,10 +5173,14 @@ assemble_alias (decl, target)
 
   if (TREE_PUBLIC (decl))
     {
-#ifdef ASM_WEAKEN_LABEL
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
       if (DECL_WEAK (decl))
- 	{
+	{
+#ifdef ASM_WEAKEN_DECL
+	  ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
+#else
 	  ASM_WEAKEN_LABEL (asm_out_file, name);
+#endif
 	  /* Remove this function from the pending weak list so that
 	     we do not emit multiple .weak directives for it.  */
 	  remove_from_pending_weak_list
@@ -5147,12 +5197,16 @@ assemble_alias (decl, target)
   ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target));
 #endif
   TREE_ASM_WRITTEN (decl) = 1;
-#else
-#ifdef ASM_OUTPUT_WEAK_ALIAS
+#else /* !ASM_OUTPUT_DEF */
+#if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
   if (! DECL_WEAK (decl))
     warning ("only weak aliases are supported in this configuration");
 
+#ifdef ASM_WEAKEN_DECL
+  ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
+#else
   ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
+#endif
   TREE_ASM_WRITTEN (decl) = 1;
 #else
   warning ("alias definitions not supported in this configuration; ignored");
@@ -5213,6 +5267,7 @@ init_varasm_once ()
 		mark_const_hash_entry);
   ggc_add_root (&const_str_htab, 1, sizeof const_str_htab,
 		mark_const_str_htab);
+  ggc_add_root (&weak_decls, 1, sizeof weak_decls, mark_weak_decls);
 
   const_alias_set = new_alias_set ();
 }
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/config/rs6000/linux64.h gcc-ppc64-31/gcc/config/rs6000/linux64.h
--- gcc-ppc64-31.orig/gcc/config/rs6000/linux64.h	Thu Feb 21 00:05:15 2002
+++ gcc-ppc64-31/gcc/config/rs6000/linux64.h	Thu Feb 28 01:07:39 2002
@@ -250,31 +250,73 @@ do {						\
       fputs (DOUBLE_INT_ASM_OP, (FILE));				\
       putc ('.', (FILE));						\
       assemble_name ((FILE), (NAME));					\
-      putc ('\n', (FILE));						\
-      fputs (DOUBLE_INT_ASM_OP, (FILE));				\
-      fputs (".TOC.@tocbase, 0\n\t.previous\n", (FILE));		\
-									\
-      if (TREE_PUBLIC (DECL))						\
+      fputs (",.TOC.@tocbase,0\n\t.previous\n\t.size\t", (FILE));	\
+      assemble_name ((FILE), (NAME));					\
+      fputs (",24\n\t.type\t.", (FILE));				\
+      assemble_name ((FILE), (NAME));					\
+      fputs (",@function\n", (FILE));					\
+      if (TREE_PUBLIC (DECL) && ! DECL_WEAK (DECL))			\
         {								\
-	  if (DECL_WEAK (DECL))						\
-	    fputs ("\t.weak\t", (FILE));				\
-	  else								\
-	    fputs ("\t.globl\t", (FILE));				\
-	  putc ('.', (FILE));						\
+	  fputs ("\t.globl\t.", (FILE));				\
 	  assemble_name ((FILE), (NAME));				\
 	  putc ('\n', (FILE));						\
         }								\
-      fputs (TYPE_ASM_OP, (FILE));					\
-      putc ('.', (FILE));						\
-      assemble_name ((FILE), (NAME));					\
-      putc (',', (FILE));						\
-      fprintf ((FILE), TYPE_OPERAND_FMT, "function");			\
-      putc ('\n', (FILE));						\
       ASM_DECLARE_RESULT ((FILE), DECL_RESULT (DECL));			\
       putc ('.', (FILE));						\
       ASM_OUTPUT_LABEL ((FILE), (NAME));				\
     }									\
   while (0)
+
+/* This is how to declare the size of a function.  */
+#undef	ASM_DECLARE_FUNCTION_SIZE
+#define	ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL)			\
+  do									\
+    {									\
+      if (!flag_inhibit_size_directive)					\
+	{								\
+	  char label[256];						\
+	  static int labelno;						\
+	  								\
+	  labelno++;							\
+	  								\
+	  ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno);		\
+	  ASM_OUTPUT_INTERNAL_LABEL ((FILE), "Lfe", labelno);		\
+	  								\
+	  fputs ("\t.size\t.", (FILE));					\
+	  assemble_name ((FILE), (FNAME));				\
+	  putc (',', (FILE));						\
+	  assemble_name ((FILE), label);				\
+	  fputs ("-.", (FILE));						\
+	  assemble_name ((FILE), (FNAME));				\
+	  putc ('\n', (FILE));						\
+	}								\
+    }									\
+  while (0)
+
+/* This implements the `alias' attribute.  */
+#undef	ASM_OUTPUT_DEF_FROM_DECLS
+#define	ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL, TARGET)			\
+  do									\
+    {									\
+      const char *alias = XSTR (XEXP (DECL_RTL (DECL), 0), 0);		\
+      const char *name = IDENTIFIER_POINTER (TARGET);			\
+      if (TREE_CODE (DECL) == FUNCTION_DECL)				\
+	{								\
+	  if (TREE_PUBLIC (DECL) && ! DECL_WEAK (DECL))			\
+	    {								\
+	      fputs ("\t.globl\t.", (FILE));				\
+	      assemble_name ((FILE), alias);				\
+	      putc ('\n', (FILE));					\
+	    }								\
+	  fputs ("\t.set\t.", (FILE));					\
+	  assemble_name ((FILE), alias);				\
+	  fputs (",.", (FILE));						\
+	  assemble_name ((FILE), name);					\
+	  fputc ('\n', (FILE));						\
+	}								\
+      ASM_OUTPUT_DEF ((FILE), alias, name);				\
+    }									\
+   while (0)
 
 /* Return non-zero if this entry is to be written into the constant
    pool in a special way.  We do so if this is a SYMBOL_REF, LABEL_REF
diff -urpN -x*~ -xTAGS gcc-ppc64-31.orig/gcc/config/rs6000/rs6000.h gcc-ppc64-31/gcc/config/rs6000/rs6000.h
--- gcc-ppc64-31.orig/gcc/config/rs6000/rs6000.h	Thu Feb 21 18:45:18 2002
+++ gcc-ppc64-31/gcc/config/rs6000/rs6000.h	Thu Feb 28 01:07:42 2002
@@ -2422,23 +2425,48 @@ extern int toc_initialized;
 #define RS6000_WEAK 0
 #endif
 
-/* This implementes the `alias' attribute.  */
+#if RS6000_WEAK
+/* Used in lieu of ASM_WEAKEN_LABEL.  */
+#define	ASM_WEAKEN_DECL(FILE, DECL, NAME, VAL)			 	\
+  do									\
+    {									\
+      fputs ("\t.weak\t", (FILE));					\
+      assemble_name ((FILE), (NAME)); 					\
+      if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL			\
+	  && DEFAULT_ABI == ABI_AIX)					\
+	{								\
+	  fputs (",.", (FILE));						\
+	  assemble_name ((FILE), (NAME)); 				\
+	}								\
+      fputc ('\n', (FILE));						\
+      if (VAL)								\
+	{								\
+	  ASM_OUTPUT_DEF ((FILE), (NAME), (VAL));			\
+	  if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL		\
+	      && DEFAULT_ABI == ABI_AIX)				\
+	    {								\
+	      fputs ("\t.set\t.", (FILE));				\
+	      assemble_name ((FILE), (NAME));				\
+	      fputs (",.", (FILE));					\
+	      assemble_name ((FILE), (VAL));				\
+	      fputc ('\n', (FILE));					\
+	    }								\
+	}								\
+    }									\
+  while (0)
+#endif
+
+/* This implements the `alias' attribute.  */
 #define ASM_OUTPUT_DEF_FROM_DECLS(FILE,decl,target)	\
 do {							\
   const char * alias = XSTR (XEXP (DECL_RTL (decl), 0), 0); \
-  char * name = IDENTIFIER_POINTER (target);		\
+  const char * name = IDENTIFIER_POINTER (target);	\
   if (TREE_CODE (decl) == FUNCTION_DECL			\
       && DEFAULT_ABI == ABI_AIX)			\
     {							\
       if (TREE_PUBLIC (decl))				\
 	{						\
-	  if (RS6000_WEAK && DECL_WEAK (decl))		\
-	    {						\
-	      fputs ("\t.weak .", FILE);		\
-	      assemble_name (FILE, alias);		\
-	      putc ('\n', FILE);			\
-	    }						\
-	  else						\
+	  if (!RS6000_WEAK || !DECL_WEAK (decl))	\
 	    {						\
 	      fputs ("\t.globl .", FILE);		\
 	      assemble_name (FILE, alias);		\


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