diff --git a/src/pike_types.c b/src/pike_types.c
index 7bec6c42a981a7ffffa43d79a914c8286aac2e20..3cdfa6ba72b746150d2f50119c6b5b60fa7e37b9 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: pike_types.c,v 1.90 1999/12/12 00:26:08 mast Exp $");
+RCSID("$Id: pike_types.c,v 1.91 1999/12/12 18:31:33 grubba Exp $");
 #include <ctype.h>
 #include "svalue.h"
 #include "pike_types.h"
@@ -24,6 +24,7 @@ RCSID("$Id: pike_types.c,v 1.90 1999/12/12 00:26:08 mast Exp $");
 #include "lex.h"
 #include "pike_memory.h"
 #include "bignum.h"
+#include "main.h"
 
 /* #define PIKE_TYPE_DEBUG */
 
@@ -1414,75 +1415,78 @@ static char *low_match_types(char *a,char *b, int flags)
 {
   int e;
   char *s;
-  char *low_match_types2(char *a,char *b, int flags);
+  static char *low_match_types2(char *a,char *b, int flags);
 
-  init_buf();
-  for(e=0;e<indent;e++) my_strcat("  ");
-  my_strcat("low_match_types(");
-  low_describe_type(a);
-  if(type_length(a) + type_length(b) > 10)
-  {
-    my_strcat(",\n");
-    for(e=0;e<indent;e++) my_strcat("  ");
-    my_strcat("                ");
-    low_describe_type(b);
-    my_strcat(",\n");
+  if (l_flag) {
+    init_buf();
     for(e=0;e<indent;e++) my_strcat("  ");
-    my_strcat("                ");
-  }else{
-    my_strcat(", ");
-    low_describe_type(b);
-    my_strcat(", ");
-  }
-  if (flags) {
-    int f = 0;
-    if (flags & A_EXACT) {
-      my_strcat("A_EXACT");
-      f = 1;
+    my_strcat("low_match_types(");
+    low_describe_type(a);
+    if(type_length(a) + type_length(b) > 10)
+    {
+      my_strcat(",\n");
+      for(e=0;e<indent;e++) my_strcat("  ");
+      my_strcat("                ");
+      low_describe_type(b);
+      my_strcat(",\n");
+      for(e=0;e<indent;e++) my_strcat("  ");
+      my_strcat("                ");
+    }else{
+      my_strcat(", ");
+      low_describe_type(b);
+      my_strcat(", ");
     }
-    if (flags & B_EXACT) {
-      if (f) {
-	my_strcat(" | ");
+    if (flags) {
+      int f = 0;
+      if (flags & A_EXACT) {
+	my_strcat("A_EXACT");
+	f = 1;
       }
-      my_strcat("B_EXACT");
-      f = 1;
-    }
-    if (flags & NO_MAX_ARGS) {
-      if (f) {
-	my_strcat(" | ");
+      if (flags & B_EXACT) {
+	if (f) {
+	  my_strcat(" | ");
+	}
+	my_strcat("B_EXACT");
+	f = 1;
       }
-      my_strcat("NO_MAX_ARGS");
-      f = 1;
-    }
-    if (flags & NO_SHORTCUTS) {
-      if (f) {
-	my_strcat(" | ");
+      if (flags & NO_MAX_ARGS) {
+	if (f) {
+	  my_strcat(" | ");
+	}
+	my_strcat("NO_MAX_ARGS");
+	f = 1;
       }
-      my_strcat("NO_SHORTCUTS");
-      f = 1;
+      if (flags & NO_SHORTCUTS) {
+	if (f) {
+	  my_strcat(" | ");
+	}
+	my_strcat("NO_SHORTCUTS");
+	f = 1;
+      }
+    } else {
+      my_strcat("0");
     }
-  } else {
-    my_strcat("0");
+    my_strcat(");\n");
+    fprintf(stderr,"%s",(s=simple_free_buf()));
+    free(s);
+    indent++;
   }
-  my_strcat(");\n");
-  fprintf(stderr,"%s",(s=simple_free_buf()));
-  free(s);
-  indent++;
 
   a=low_match_types2(a,b,flags);
 
-  indent--;
-  init_buf();
-  for(e=0;e<indent;e++) my_strcat("  ");
-  my_strcat("= ");
-  if(a)
-    low_describe_type(a);
-  else
-    my_strcat("NULL");
-  my_strcat("\n");
-  fprintf(stderr,"%s",(s=simple_free_buf()));
-  free(s);
-
+  if (l_flag) {
+    indent--;
+    init_buf();
+    for(e=0;e<indent;e++) my_strcat("  ");
+    my_strcat("= ");
+    if(a)
+      low_describe_type(a);
+    else
+      my_strcat("NULL");
+    my_strcat("\n");
+    fprintf(stderr,"%s",(s=simple_free_buf()));
+    free(s);
+  }
   return a;
 }
 
@@ -1538,7 +1542,7 @@ static char *low_match_types2(char *a,char *b, int flags)
 	a_markers[m]=pop_unfinished_type();
 
 #ifdef PIKE_TYPE_DEBUG
-	{
+	if (l_flag) {
 	  char *s;
 	  int e;
 	  init_buf();
@@ -1622,7 +1626,7 @@ static char *low_match_types2(char *a,char *b, int flags)
 	free_string(tmp);
 	b_markers[m]=pop_unfinished_type();
 #ifdef PIKE_TYPE_DEBUG
-	{
+	if (l_flag) {
 	  char *s;
 	  int e;
 	  init_buf();
@@ -1835,9 +1839,11 @@ static char *low_match_types2(char *a,char *b, int flags)
       if(EXTRACT_UCHAR(a+1))
       {
 	/* object(1 x) =? object(1 x) */
+	/* FIXME: Ought to check if a inherits b or b inherits a. */
 	if(extract_type_int(a+2) != extract_type_int(b+2)) return 0;
       }else{
 	/* object(0 *) =? object(0 *) */
+	/* FIXME: Ought to check the implements relation */
 	break;
       }
     }
@@ -1849,6 +1855,13 @@ static char *low_match_types2(char *a,char *b, int flags)
 
       if(!ap || !bp) break;
 
+#if 1
+      /* FIXME: Temporary kludge.
+       * match_types() currently seems to need to be symetric.
+       */
+      if (!implements(ap,bp) && !implements(bp,ap))
+	return 0;
+#else /* !1 */
       if(EXTRACT_UCHAR(a+1))
       {
 	if(!implements(ap,bp))
@@ -1857,6 +1870,7 @@ static char *low_match_types2(char *a,char *b, int flags)
 	if(!implements(bp,ap))
 	  return 0;
       }
+#endif /* 1 */
     }
     
     break;
@@ -1914,35 +1928,38 @@ static int low_pike_types_le(char *a,char *b)
 {
   int e;
   char *s;
-  int low_pike_types_le2(char *a,char *b);
+  static int low_pike_types_le2(char *a,char *b);
   int res;
 
-  init_buf();
-  for(e=0;e<indent;e++) my_strcat("  ");
-  my_strcat("low_pike_types_le(");
-  low_describe_type(a);
-  if(type_length(a) + type_length(b) > 10)
-  {
-    my_strcat(",\n");
+  if (l_flag) {
+    init_buf();
     for(e=0;e<indent;e++) my_strcat("  ");
-    my_strcat("                ");
-    low_describe_type(b);
-  }else{
-    my_strcat(", ");
-    low_describe_type(b);
+    my_strcat("low_pike_types_le(");
+    low_describe_type(a);
+    if(type_length(a) + type_length(b) > 10)
+    {
+      my_strcat(",\n");
+      for(e=0;e<indent;e++) my_strcat("  ");
+      my_strcat("                ");
+      low_describe_type(b);
+    }else{
+      my_strcat(", ");
+      low_describe_type(b);
+    }
+    my_strcat(");\n");
+    fprintf(stderr,"%s",(s=simple_free_buf()));
+    free(s);
+    indent++;
   }
-  my_strcat(");\n");
-  fprintf(stderr,"%s",(s=simple_free_buf()));
-  free(s);
-  indent++;
 
   res=low_pike_types_le2(a,b);
 
-  indent--;
-
-  for(e=0;e<indent;e++) fprintf(stderr, "  ");
-  fprintf(stderr, "= %d\n", res);
+  if (l_flag) {
+    indent--;
 
+    for(e=0;e<indent;e++) fprintf(stderr, "  ");
+    fprintf(stderr, "= %d\n", res);
+  }
   return res;
 }
 
@@ -1984,14 +2001,14 @@ static int low_pike_types_le2(char *a,char *b)
       type_stack_mark();
       push_unfinished_type_with_markers(b, b_markers);
       tmp=pop_unfinished_type();
-
+      
       type_stack_mark();
       medium_or_pike_types(a_markers[m], tmp, 0);
       if(a_markers[m]) free_string(a_markers[m]);
       free_string(tmp);
       a_markers[m]=pop_unfinished_type();
 #ifdef PIKE_TYPE_DEBUG
-      {
+      if (l_flag) {
 	char *s;
 	int e;
 	init_buf();
@@ -2056,7 +2073,7 @@ static int low_pike_types_le2(char *a,char *b)
       free_string(tmp);
       b_markers[m]=pop_unfinished_type();
 #ifdef PIKE_TYPE_DEBUG
-      {
+      if (l_flag) {
 	char *s;
 	int e;
 	init_buf();
@@ -2137,7 +2154,6 @@ static int low_pike_types_le2(char *a,char *b)
 
   if(EXTRACT_UCHAR(a) != EXTRACT_UCHAR(b)) return 0;
 
-  ret=1;
   switch(EXTRACT_UCHAR(a))
   {
   case T_FUNCTION:
@@ -2173,7 +2189,7 @@ static int low_pike_types_le2(char *a,char *b)
       }
 
       if (EXTRACT_UCHAR(a_tmp) != T_VOID) {
-	if (EXTRACT_UCHAR(b_tmp) == T_VOID) return 0;
+	/* if (EXTRACT_UCHAR(b_tmp) == T_VOID) return 0; */
 	if (!low_pike_types_le(b_tmp, a_tmp)) return 0;
       }
     }
@@ -2213,6 +2229,14 @@ static int low_pike_types_le2(char *a,char *b)
     }
 #endif
 
+    /*
+     * object(0|1 x) <= object(0|1 0)
+     * object(0|1 0) <=! object(0|1 !0)
+     * object(1 x) <= object(0|1 x)
+     * object(1 x) <= object(1 y)	iff x inherits y
+     * object(0|1 x) <= object(0 y)	iff x implements y
+     */
+
     /* object(* 0) matches any object */
     if(!extract_type_int(b+2))
       return 1;
@@ -2220,38 +2244,32 @@ static int low_pike_types_le2(char *a,char *b)
     if(!extract_type_int(a+2))
       return 0;
     
+    if ((EXTRACT_UCHAR(a+1) || !EXTRACT_UCHAR(b+1)) &&
+	(extract_type_int(a+2) == extract_type_int(b+2)))
+      return 1;
 
-    /* object(x *) =? object(x *) */
-    if(EXTRACT_UCHAR(a+1) == EXTRACT_UCHAR(b+1))
-    {
-      /* x? */
-      if(EXTRACT_UCHAR(a+1))
-      {
-	/* object(1 x) =? object(1 x) */
-	if(extract_type_int(a+2) != extract_type_int(b+2)) return 0;
-      }else{
-	/* object(0 *) =? object(0 *) */
-	break;
+    if (EXTRACT_UCHAR(b+1)) {
+      if (!EXTRACT_UCHAR(a+1)) {
+	/* We can't guarantee the inherit relation. */
+	return 0;
       }
     }
 
     {
-      struct program *ap,*bp;
-      ap=id_to_program(extract_type_int(a+2));
-      bp=id_to_program(extract_type_int(b+2));
-
-      if(!ap || !bp) break;
+      struct program *ap = id_to_program(extract_type_int(a+2));
+      struct program *bp = id_to_program(extract_type_int(b+2));
 
-      if(EXTRACT_UCHAR(a+1))
-      {
-	if(!implements(ap,bp))
-	  return 0;
-      }else{
-	if(!implements(bp,ap))
-	  return 0;
+      if (!ap || !bp) {
+	/* Shouldn't happen... */
+	return 0;
+      }
+      if (EXTRACT_UCHAR(b+1)) {
+	/* FIXME: Should probably have a better test here. */
+	return low_get_storage(ap, bp) != -1;
+      } else {
+	return implements(ap, bp);
       }
     }
-    
     break;
 
   case T_INT:
@@ -2283,7 +2301,25 @@ static int low_pike_types_le2(char *a,char *b)
   default:
     fatal("error in type string.\n");
   }
-  return ret;
+  return 1;
+}
+
+/*
+ * Check the function parameters.
+ * Note: The difference between this function, and pike_types_le()
+ *       is the more lenient check for T_OR, and the handling of T_ARRAY.
+ */
+int strict_check_call(char *fun_type, char *arg_type)
+{
+  while ((EXTRACT_UCHAR(fun_type) == T_OR) ||
+	 (EXTRACT_UCHAR(fun_type) == T_ARRAY)) {
+    if (EXTRACT_UCHAR(fun_type++) == T_OR) {
+      int res = strict_check_call(fun_type, arg_type);
+      if (res) return res;
+      fun_type += type_length(fun_type);
+    }
+  }
+  return low_pike_types_le(fun_type, arg_type);
 }
 
 /*
@@ -2825,6 +2861,19 @@ struct pike_string *check_call(struct pike_string *args,
   
   if(low_get_return_type(type->str,args->str))
   {
+    if (lex.pragmas & ID_STRICT_TYPES) {
+      if (type == mixed_type_string) {
+	yywarning("Calling mixed.");
+      } else if (!strict_check_call(type->str, args->str)) {
+	struct pike_string *arg_t = describe_type(args);
+	struct pike_string *type_t = describe_type(type);
+	yywarning("Arguments not strictly compatible.");
+	yywarning("Expected: %s", type_t->str);
+	yywarning("Got     : %s", arg_t->str);
+	free_string(type_t);
+	free_string(arg_t);
+      }
+    }
     return pop_unfinished_type();
   }else{
     pop_stack_mark();