This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the EGCS project.


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

difference of labels


By request, here's a bit of code to support difference of labels
in static data.  Eg.

   int foo(int i)
   {
     static long a[] = { &&l1 - &&l1, &&l2 - &&l1};
     void *p;
   
     p = &&l1 + a[i];
   
     goto *p; 
   
   l1: return 1;
   l2: return 2;
   }

This allows jump tables in shared libraries to be written in 
such a way that they do not require runtime relocations.

C++ parts written and approved with Jason peeking over my shoulder.



r~


gcc/
        * c-typeck.c (initializer_constant_valid_p): Move ...
        * c-common.c (initializer_constant_valid_p): ... here.  Use 
        FOO_TYPE_P instead of tests against TREE_CODE.  Allow subtraction
        of label addresses.
        * c-common.h (initializer_constant_valid_p): Declare.
        * c-tree.h (initializer_constant_valid_p): Remove.

gcc/cp/
        * typeck2.c (initializer_constant_valid_p): Moved to c-common.c.
        * cp-tree.h (initializer_constant_valid_p): Remove.


Index: c-common.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-common.c,v
retrieving revision 1.62
diff -c -p -d -r1.62 c-common.c
*** c-common.c	1999/07/27 05:43:56	1.62
--- c-common.c	1999/07/31 01:06:39
*************** build_va_arg (expr, type)
*** 3767,3769 ****
--- 3767,3925 ----
  {
    return build1 (VA_ARG_EXPR, type, expr);
  }
+ 
+ /* Return nonzero if VALUE is a valid constant-valued expression
+    for use in initializing a static variable; one that can be an
+    element of a "constant" initializer.
+ 
+    Return null_pointer_node if the value is absolute;
+    if it is relocatable, return the variable that determines the relocation.
+    We assume that VALUE has been folded as much as possible;
+    therefore, we do not need to check for such things as
+    arithmetic-combinations of integers.  */
+ 
+ tree
+ initializer_constant_valid_p (value, endtype)
+      tree value;
+      tree endtype;
+ {
+   switch (TREE_CODE (value))
+     {
+     case CONSTRUCTOR:
+       if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
+ 	   || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
+ 	  && TREE_CONSTANT (value)
+ 	  && CONSTRUCTOR_ELTS (value))
+ 	return
+ 	  initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
+ 					endtype);
+ 	
+       return TREE_STATIC (value) ? null_pointer_node : 0;
+ 
+     case INTEGER_CST:
+     case REAL_CST:
+     case STRING_CST:
+     case COMPLEX_CST:
+       return null_pointer_node;
+ 
+     case ADDR_EXPR:
+       return TREE_OPERAND (value, 0);
+ 
+     case NON_LVALUE_EXPR:
+       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+ 
+     case CONVERT_EXPR:
+     case NOP_EXPR:
+       /* Allow conversions between pointer types.  */
+       if (POINTER_TYPE_P (TREE_TYPE (value))
+ 	  && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
+ 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+ 
+       /* Allow conversions between real types.  */
+       if (FLOAT_TYPE_P (TREE_TYPE (value))
+ 	  && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
+ 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+ 
+       /* Allow length-preserving conversions between integer types.  */
+       if (INTEGRAL_TYPE_P (TREE_TYPE (value))
+ 	  && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
+ 	  && (TYPE_PRECISION (TREE_TYPE (value))
+ 	      == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
+ 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+ 
+       /* Allow conversions between other integer types only if
+ 	 explicit value.  */
+       if (INTEGRAL_TYPE_P (TREE_TYPE (value))
+ 	  && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
+ 	{
+ 	  tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
+ 						     endtype);
+ 	  if (inner == null_pointer_node)
+ 	    return null_pointer_node;
+ 	  break;
+ 	}
+ 
+       /* Allow (int) &foo provided int is as wide as a pointer.  */
+       if (INTEGRAL_TYPE_P (TREE_TYPE (value))
+ 	  && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
+ 	  && (TYPE_PRECISION (TREE_TYPE (value))
+ 	      >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
+ 	return initializer_constant_valid_p (TREE_OPERAND (value, 0),
+ 					     endtype);
+ 
+       /* Likewise conversions from int to pointers, but also allow
+ 	 conversions from 0.  */
+       if (POINTER_TYPE_P (TREE_TYPE (value))
+ 	  && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
+ 	{
+ 	  if (integer_zerop (TREE_OPERAND (value, 0)))
+ 	    return null_pointer_node;
+ 	  else if (TYPE_PRECISION (TREE_TYPE (value))
+ 		   <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
+ 	    return initializer_constant_valid_p (TREE_OPERAND (value, 0),
+ 						 endtype);
+ 	}
+ 
+       /* Allow conversions to union types if the value inside is okay.  */
+       if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
+ 	return initializer_constant_valid_p (TREE_OPERAND (value, 0),
+ 					     endtype);
+       break;
+ 
+     case PLUS_EXPR:
+       if (! INTEGRAL_TYPE_P (endtype)
+ 	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
+         {
+ 	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
+ 						      endtype);
+ 	  tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
+ 						      endtype);
+ 	  /* If either term is absolute, use the other terms relocation.  */
+ 	  if (valid0 == null_pointer_node)
+ 	    return valid1;
+ 	  if (valid1 == null_pointer_node)
+ 	    return valid0;
+         }
+       break;
+ 
+     case MINUS_EXPR:
+       if (! INTEGRAL_TYPE_P (endtype)
+ 	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
+ 	{
+ 	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
+ 						      endtype);
+ 	  tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
+ 						      endtype);
+ 	  /* Win if second argument is absolute.  */
+ 	  if (valid1 == null_pointer_node)
+ 	    return valid0;
+ 	  /* Win if both arguments have the same relocation.
+ 	     Then the value is absolute.  */
+ 	  if (valid0 == valid1)
+ 	    return null_pointer_node;
+ 	}
+ 
+       /* Support differences between labels.  */
+       if (INTEGRAL_TYPE_P (endtype))
+ 	{
+ 	  tree op0, op1;
+ 	  op0 = TREE_OPERAND (value, 0);
+ 	  op1 = TREE_OPERAND (value, 1);
+ 	  STRIP_NOPS (op0);
+ 	  STRIP_NOPS (op1);
+ 
+ 	  if (TREE_CODE (op0) == ADDR_EXPR
+ 	      && TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
+ 	      && TREE_CODE (op1) == ADDR_EXPR
+ 	      && TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL)
+ 	    return null_pointer_node;
+ 	}
+       break;
+ 
+     default:
+       break;
+     }
+ 
+   return 0;
+ }
+ 
Index: c-common.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-common.h,v
retrieving revision 1.3
diff -c -p -d -r1.3 c-common.h
*** c-common.h	1999/07/26 01:21:02	1.3
--- c-common.h	1999/07/31 01:06:39
*************** extern tree builtin_function			PROTO((co
*** 190,192 ****
--- 190,194 ----
  extern void c_common_nodes_and_builtins		PROTO((int, int, int));
  
  extern tree build_va_arg			PROTO((tree, tree));
+ 
+ extern tree initializer_constant_valid_p	PROTO((tree, tree));
Index: c-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-tree.h,v
retrieving revision 1.22
diff -c -p -d -r1.22 c-tree.h
*** c-tree.h	1999/07/20 10:40:39	1.22
--- c-tree.h	1999/07/31 01:06:39
*************** extern tree build_compound_expr         
*** 282,288 ****
  extern tree build_c_cast                        PROTO((tree, tree));
  extern tree build_modify_expr                   PROTO((tree, enum tree_code,
  						       tree));
- extern tree initializer_constant_valid_p	PROTO((tree, tree));
  extern void store_init_value                    PROTO((tree, tree));
  extern void error_init				PROTO((const char *));
  extern void pedwarn_init			PROTO((const char *));
--- 282,287 ----
Index: c-typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-typeck.c,v
retrieving revision 1.30
diff -c -p -d -r1.30 c-typeck.c
*** c-typeck.c	1999/07/14 15:47:26	1.30
--- c-typeck.c	1999/07/31 01:06:39
*************** warn_for_assignment (msgid, opname, func
*** 4246,4390 ****
    pedwarn (msgid, opname);
  }
  
- /* Return nonzero if VALUE is a valid constant-valued expression
-    for use in initializing a static variable; one that can be an
-    element of a "constant" initializer.
- 
-    Return null_pointer_node if the value is absolute;
-    if it is relocatable, return the variable that determines the relocation.
-    We assume that VALUE has been folded as much as possible;
-    therefore, we do not need to check for such things as
-    arithmetic-combinations of integers.  */
- 
- tree
- initializer_constant_valid_p (value, endtype)
-      tree value;
-      tree endtype;
- {
-   switch (TREE_CODE (value))
-     {
-     case CONSTRUCTOR:
-       if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
- 	   || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
- 	  && TREE_CONSTANT (value)
- 	  && CONSTRUCTOR_ELTS (value))
- 	return
- 	  initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
- 					endtype);
- 	
-       return TREE_STATIC (value) ? null_pointer_node : 0;
- 
-     case INTEGER_CST:
-     case REAL_CST:
-     case STRING_CST:
-     case COMPLEX_CST:
-       return null_pointer_node;
- 
-     case ADDR_EXPR:
-       return TREE_OPERAND (value, 0);
- 
-     case NON_LVALUE_EXPR:
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- 
-     case CONVERT_EXPR:
-     case NOP_EXPR:
-       /* Allow conversions between pointer types.  */
-       if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- 
-       /* Allow conversions between real types.  */
-       if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE)
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- 
-       /* Allow length-preserving conversions between integer types.  */
-       if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
- 	  && (TYPE_PRECISION (TREE_TYPE (value))
- 	      == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- 
-       /* Allow conversions between other integer types only if
- 	 explicit value.  */
-       if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
- 	{
- 	  tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 						     endtype);
- 	  if (inner == null_pointer_node)
- 	    return null_pointer_node;
- 	  return 0;
- 	}
- 
-       /* Allow (int) &foo provided int is as wide as a pointer.  */
-       if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
- 	  && (TYPE_PRECISION (TREE_TYPE (value))
- 	      >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 					     endtype);
- 
-       /* Likewise conversions from int to pointers, but also allow
- 	 conversions from 0.  */
-       if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
- 	{
- 	  if (integer_zerop (TREE_OPERAND (value, 0)))
- 	    return null_pointer_node;
- 	  else if (TYPE_PRECISION (TREE_TYPE (value))
- 		   <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
- 	    return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 						 endtype);
- 	}
- 
-       /* Allow conversions to union types if the value inside is okay.  */
-       if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 					     endtype);
-       return 0;
- 
-     case PLUS_EXPR:
-       if (TREE_CODE (endtype) == INTEGER_TYPE
- 	  && TYPE_PRECISION (endtype) < POINTER_SIZE)
- 	return 0;
-       {
- 	tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 						    endtype);
- 	tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- 						    endtype);
- 	/* If either term is absolute, use the other terms relocation.  */
- 	if (valid0 == null_pointer_node)
- 	  return valid1;
- 	if (valid1 == null_pointer_node)
- 	  return valid0;
- 	return 0;
-       }
- 
-     case MINUS_EXPR:
-       if (TREE_CODE (endtype) == INTEGER_TYPE
- 	  && TYPE_PRECISION (endtype) < POINTER_SIZE)
- 	return 0;
-       {
- 	tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 						    endtype);
- 	tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- 						    endtype);
- 	/* Win if second argument is absolute.  */
- 	if (valid1 == null_pointer_node)
- 	  return valid0;
- 	/* Win if both arguments have the same relocation.
- 	   Then the value is absolute.  */
- 	if (valid0 == valid1)
- 	  return null_pointer_node;
- 	return 0;
-       }
- 
-     default:
-       return 0;
-     }
- }
- 
  /* If VALUE is a compound expr all of whose expressions are constant, then
     return its value.  Otherwise, return error_mark_node.
  
--- 4246,4251 ----
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.250
diff -c -p -d -r1.250 cp-tree.h
*** cp-tree.h	1999/07/28 00:45:12	1.250
--- cp-tree.h	1999/07/31 01:06:40
*************** extern tree build_functional_cast		PROTO
*** 3586,3592 ****
  extern char *enum_name_string			PROTO((tree, tree));
  extern void report_case_error			PROTO((int, tree, tree, tree));
  extern void check_for_new_type			PROTO((const char *, flagged_type_tree));
- extern tree initializer_constant_valid_p	PROTO((tree, tree));
  
  /* in xref.c */
  extern void GNU_xref_begin			PROTO((const char *));
--- 3586,3591 ----
Index: cp/typeck2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck2.c,v
retrieving revision 1.56
diff -c -p -d -r1.56 typeck2.c
*** typeck2.c	1999/07/26 08:18:12	1.56
--- typeck2.c	1999/07/31 01:06:40
*************** my_friendly_assert (cond, where)
*** 378,523 ****
      my_friendly_abort (where);
  }
  
- /* Return nonzero if VALUE is a valid constant-valued expression
-    for use in initializing a static variable; one that can be an
-    element of a "constant" initializer.
- 
-    Return null_pointer_node if the value is absolute;
-    if it is relocatable, return the variable that determines the relocation.
-    We assume that VALUE has been folded as much as possible;
-    therefore, we do not need to check for such things as
-    arithmetic-combinations of integers.  */
- 
- tree
- initializer_constant_valid_p (value, endtype)
-      tree value;
-      tree endtype;
- {
-   switch (TREE_CODE (value))
-     {
-     case CONSTRUCTOR:
-       if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
- 	  && TREE_CONSTANT (value))
- 	return
- 	  initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
- 					endtype);
- 	
-       return TREE_STATIC (value) ? null_pointer_node : 0;
- 
-     case INTEGER_CST:
-     case REAL_CST:
-     case STRING_CST:
-     case COMPLEX_CST:
-     case PTRMEM_CST:
-       return null_pointer_node;
- 
-     case ADDR_EXPR:
-       return TREE_OPERAND (value, 0);
- 
-     case NON_LVALUE_EXPR:
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- 
-     case CONVERT_EXPR:
-     case NOP_EXPR:
-       /* Allow conversions between pointer types.  */
-       if (POINTER_TYPE_P (TREE_TYPE (value))
- 	  && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- 
-       /* Allow conversions between real types.  */
-       if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE)
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- 
-       /* Allow length-preserving conversions between integer types.  */
-       if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
- 	  && (TYPE_PRECISION (TREE_TYPE (value))
- 	      == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- 
-       /* Allow conversions between other integer types only if
- 	 explicit value.  */
-       if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
- 	{
- 	  tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 						     endtype);
- 	  if (inner == null_pointer_node)
- 	    return null_pointer_node;
- 	  return 0;
- 	}
- 
-       /* Allow (int) &foo provided int is as wide as a pointer.  */
-       if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
- 	  && (TYPE_PRECISION (TREE_TYPE (value))
- 	      >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 					     endtype);
- 
-       /* Likewise conversions from int to pointers, but also allow
- 	 conversions from 0.  */
-       if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- 	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
- 	{
- 	  if (integer_zerop (TREE_OPERAND (value, 0)))
- 	    return null_pointer_node;
- 	  else if (TYPE_PRECISION (TREE_TYPE (value))
- 		   <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
- 	    return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 						 endtype);
- 	}
- 
-       /* Allow conversions to union types if the value inside is okay.  */
-       if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
- 	return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 					     endtype);
-       return 0;
- 
-     case PLUS_EXPR:
-       if ((TREE_CODE (endtype) == INTEGER_TYPE)
- 	  && (TYPE_PRECISION (endtype) < POINTER_SIZE))
- 	return 0;
-       {
- 	tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 						    endtype);
- 	tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- 						    endtype);
- 	/* If either term is absolute, use the other terms relocation.  */
- 	if (valid0 == null_pointer_node)
- 	  return valid1;
- 	if (valid1 == null_pointer_node)
- 	  return valid0;
- 	return 0;
-       }
- 
-     case MINUS_EXPR:
-       if ((TREE_CODE (endtype) == INTEGER_TYPE)
- 	  && (TYPE_PRECISION (endtype) < POINTER_SIZE))
- 	return 0;
-       {
- 	tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- 						    endtype);
- 	tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- 						    endtype);
- 	/* Win if second argument is absolute.  */
- 	if (valid1 == null_pointer_node)
- 	  return valid0;
- 	/* Win if both arguments have the same relocation.
- 	   Then the value is absolute.  */
- 	if (valid0 == valid1)
- 	  return null_pointer_node;
- 	return 0;
-       }
- 
-     default:
-       break;
-     }
- 
-   return 0;
- }
- 
  /* Perform appropriate conversions on the initial value of a variable,
     store it in the declaration DECL,
     and print any error messages that are appropriate.
--- 378,383 ----

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