diff --git a/src/las.c b/src/las.c
index f4256117201f0526fc75b23ab229d15c8284bb31..41d9d2dc2ee84727c41f700fe14dcfea4d647ca1 100644
--- a/src/las.c
+++ b/src/las.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: las.c,v 1.50 1998/02/01 04:01:34 hubbe Exp $");
+RCSID("$Id: las.c,v 1.51 1998/02/23 23:24:02 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -1424,6 +1424,7 @@ void fix_type_field(node *n)
   {
     struct pike_string *s;
     struct pike_string *f;
+    INT32 max_args,args;
     push_type(T_MIXED); /* match any return type, even void */
     push_type(T_VOID); /* not varargs */
     push_type(T_MANY);
@@ -1432,6 +1433,8 @@ void fix_type_field(node *n)
     s=pop_type();
     f=CAR(n)->type?CAR(n)->type:mixed_type_string;
     n->type=check_call(s,f);
+    args=count_arguments(s);
+    max_args=get_max_args(f);
 
     if(!n->type)
     {
@@ -1447,8 +1450,13 @@ void fix_type_field(node *n)
 	switch(CAR(n)->u.sval.type)
 	{
 	  case T_FUNCTION:
-	    name=ID_FROM_INT(CAR(n)->u.sval.u.object->prog,
-			     CAR(n)->u.sval.subtype)->name->str;
+	    if(CAR(n)->u.sval.subtype == FUNCTION_BUILTIN)
+	    {
+	      name=CAR(n)->u.sval.u.efun->name->str;
+	    }else{
+	      name=ID_FROM_INT(CAR(n)->u.sval.u.object->prog,
+			       CAR(n)->u.sval.subtype)->name->str;
+	    }
 	    break;
 
 	  case T_ARRAY:
@@ -1463,12 +1471,17 @@ void fix_type_field(node *n)
 	    name="`() (function call)";
 	    break;
 	}
+	break;
 
       default:
 	name="unknown function";
       }
 
-      if(max_correct_args == count_arguments(s))
+      if(max_args < args)
+      {
+	my_yyerror("To many arguments to %s.\n",name);
+      }
+      else if(max_correct_args == args)
       {
 	my_yyerror("To few arguments to %s.\n",name);
       }else{
diff --git a/src/modules/math/math.c b/src/modules/math/math.c
index 3641a11bbb7d31fd0ac4e1a69e60d3424ce54ddf..28fef483b9c8ef394da52a1a5aaa44f68b297331 100644
--- a/src/modules/math/math.c
+++ b/src/modules/math/math.c
@@ -141,16 +141,21 @@ void f_ceil(INT32 args)
 
 void f_min(INT32 args)
 {
-  check_all_args("min",args,BIT_MIXED,BIT_MIXED,0);
-  if(args<2) error("Too few arguments to min()\n");
-  if(is_gt(sp-args,sp-args+1)) assign_svalue(sp-args,sp-args+1);
+  INT32 i;
+  if(!args) error("Too few arguments to min()\n");
+  for(i=args-2;i>=0;i--)
+    if(is_gt(sp-args+i,sp-args+1+i))
+      assign_svalue(sp-args+i,sp-args+1+i);
   pop_n_elems(args-1);
 }
 
 void f_max(INT32 args)
 {
-  check_all_args("max",args,BIT_MIXED,BIT_MIXED,0);
-  if(is_lt(sp-args,sp-args+1)) assign_svalue(sp-args,sp-args+1);
+  INT32 i;
+  if(!args) error("Too few arguments to max()\n");
+  for(i=args-2;i>=0;i--)
+    if(is_lt(sp-args+i,sp-args+1+i))
+      assign_svalue(sp-args+i,sp-args+1+i);
   pop_n_elems(args-1);
 }
 
@@ -206,8 +211,15 @@ void pike_module_init(void)
   add_efun("floor",f_floor,"function(float:float)",0);
   add_efun("ceil",f_ceil,"function(float:float)",0);
 
-  add_efun("max",f_max,"function(mixed,mixed:mixed)",0);
-  add_efun("min",f_min,"function(mixed,mixed:mixed)",0);
+#define CMP_TYPE \
+  "!function(!object...:mixed)&function(mixed...:mixed)|" \
+  "function(int...:int)|" \
+  "function(float...:float)|" \
+  "function(string...:string)|"  \
+  "!function(int...:mixed)&!function(float...:mixed)&function(int|float...:int|float)"
+    
+  add_efun("max",f_max,CMP_TYPE,0);
+  add_efun("min",f_min,CMP_TYPE,0);
   add_efun("abs",f_abs,"function(float|int|object:float|int|object)",0);
   add_efun("sgn",f_sgn,"function(mixed,mixed|void:int)",0);
 }
diff --git a/src/operators.c b/src/operators.c
index 9dec0f1529aba787422a56b84c9b523cfc78693d..9bd585357e955927c7affd5d0711fdab7e9cdf64 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -5,7 +5,7 @@
 \*/
 #include <math.h>
 #include "global.h"
-RCSID("$Id: operators.c,v 1.24 1998/02/20 01:00:42 hubbe Exp $");
+RCSID("$Id: operators.c,v 1.25 1998/02/23 23:24:03 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -25,25 +25,39 @@ RCSID("$Id: operators.c,v 1.24 1998/02/20 01:00:42 hubbe Exp $");
 #include "object.h"
 #include "pike_types.h"
 
-#define COMPARISON(ID,NAME,EXPR) \
-void ID(INT32 args) \
-{ \
-  int i; \
-  if(args > 2) \
-    pop_n_elems(args-2); \
-  else if(args < 2) \
-    error("Too few arguments to %s\n",NAME); \
-  i=EXPR; \
-  pop_n_elems(2); \
-  push_int(i); \
+#define COMPARISON(ID,NAME,FUN)			\
+void ID(INT32 args)				\
+{						\
+  int i;					\
+  switch(args)					\
+  {						\
+    case 0: case 1:				\
+      error("Too few arguments to %s\n",NAME);	\
+    case 2:					\
+      i=FUN (sp-2,sp-1);			\
+      pop_n_elems(2);				\
+      push_int(i);				\
+      break;					\
+    default:					\
+      for(i=1;i<args;i++)			\
+        if(! ( FUN (sp-args+i-1, sp-args+i)))	\
+          break;				\
+      pop_n_elems(args);			\
+      push_int(i==args);			\
+  }						\
 }
 
-COMPARISON(f_eq,"`==", is_eq(sp-2,sp-1))
-COMPARISON(f_ne,"`!=",!is_eq(sp-2,sp-1))
-COMPARISON(f_lt,"`<" , is_lt(sp-2,sp-1))
-COMPARISON(f_le,"`<=",!is_gt(sp-2,sp-1))
-COMPARISON(f_gt,"`>" , is_gt(sp-2,sp-1))
-COMPARISON(f_ge,"`>=",!is_lt(sp-2,sp-1))
+void f_ne(INT32 args)
+{
+  f_eq(args);
+  o_not();
+}
+
+COMPARISON(f_eq,"`==", is_eq)
+COMPARISON(f_lt,"`<" , is_lt)
+COMPARISON(f_le,"`<=",!is_gt)
+COMPARISON(f_gt,"`>" , is_gt)
+COMPARISON(f_ge,"`>=",!is_lt)
 
 
 #define CALL_OPERATOR(OP, args) \
@@ -493,10 +507,22 @@ void f_minus(INT32 args)
 {
   switch(args)
   {
-  case 0: error("Too few arguments to `-\n");
-  case 1: o_negate(); break;
-  case 2: o_subtract(); break;
-  default: error("Too many arguments to `-\n");
+    case 0: error("Too few arguments to `-\n");
+    case 1: o_negate(); break;
+    case 2: o_subtract(); break;
+    default:
+    {
+      INT32 e;
+      struct svalue *s=sp-args;
+      push_svalue(s);
+      for(e=1;e<args;e++)
+      {
+	push_svalue(s+e);
+	o_subtract();
+      }
+      assign_svalue(s,sp-1);
+      pop_n_elems(sp-s-1);
+    }
   }
 }
 
@@ -1287,9 +1313,25 @@ void o_divide(void)
 
 void f_divide(INT32 args)
 {
-  if(args != 2)
-    error("Bad number of args to `/\n");
-  o_divide();
+  switch(args)
+  {
+    case 0: 
+    case 1: error("Too few arguments to `/\n");
+    case 2: o_divide(); break;
+    default:
+    {
+      INT32 e;
+      struct svalue *s=sp-args;
+      push_svalue(s);
+      for(e=1;e<args;e++)
+      {
+	push_svalue(s+e);
+	o_divide();
+      }
+      assign_svalue(s,sp-1);
+      pop_n_elems(sp-s-1);
+    }
+  }
 }
 
 static int generate_divide(node *n)
@@ -1669,11 +1711,11 @@ void init_operators(void)
   add_efun2("`->",f_arrow,
 	    "function(array(object|mapping|multiset|array)|object|mapping|multiset,string:mixed)",OPT_TRY_OPTIMIZE,0,0);
 
-  add_efun2("`==",f_eq,"function(mixed,mixed:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
-  add_efun2("`!=",f_ne,"function(mixed,mixed:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
+  add_efun2("`==",f_eq,"function(mixed...:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
+  add_efun2("`!=",f_ne,"function(mixed...:int)",OPT_TRY_OPTIMIZE,0,generate_comparison);
   add_efun2("`!",f_not,"function(mixed:int)",OPT_TRY_OPTIMIZE,0,generate_not);
 
-#define CMP_TYPE "function(object,mixed:int)|function(mixed,object:int)|function(int|float,int|float:int)|function(string,string:int)"
+#define CMP_TYPE "!function(!object...:mixed)&function(mixed...:int)|function(int|float...:int)|function(string...:int)"
   add_efun2("`<", f_lt,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison);
   add_efun2("`<=",f_le,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison);
   add_efun2("`>", f_gt,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison);
@@ -1708,13 +1750,11 @@ void init_operators(void)
 	    OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply);
 
   add_efun2("`/",f_divide,
-	    "function(mixed,object:mixed)|"
-	    "function(array,array|int|float:array(array))|"
-	    "function(object,mixed:mixed)|"
-	    "function(int,int:int)|"
-	    "function(float|int,float:float)|"
-	    "function(float,int:float)|"
-	    "function(string,string|int|float:string*)",
+	    "!function(!object...:mixed)&function(mixed...:mixed)|"
+	    "function(int,int...:int)|"
+	    "!function(int...:mixed)&function(float|int...:float)|"
+	    "function(array,array|int|float...:array(array))|"
+	    "function(string,string|int|float...:array(string))",
 	    OPT_TRY_OPTIMIZE,0,generate_divide);
 
   add_efun2("`%",f_mod,"function(mixed,object:mixed)|function(object,mixed:mixed)|function(int,int:int)|!function(int,int:mixed)&function(int|float,int|float:float)",OPT_TRY_OPTIMIZE,0,generate_mod);
diff --git a/src/pike_types.c b/src/pike_types.c
index 16a0aa58b04d42c30ce24016fe2c6ab6c5398315..b1b12a420b9e37feb1d3a6c0a86ef67501bcaa7f 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: pike_types.c,v 1.31 1998/02/20 00:55:23 hubbe Exp $");
+RCSID("$Id: pike_types.c,v 1.32 1998/02/23 23:24:04 hubbe Exp $");
 #include <ctype.h>
 #include "svalue.h"
 #include "pike_types.h"
@@ -645,6 +645,7 @@ TYPE_T compile_type_to_runtime_type(struct pike_string *s)
 
 #define A_EXACT 1
 #define B_EXACT 2
+#define NO_MAX_ARGS 4
 
 /*
  * match two type strings, return zero if they don't match, and return
@@ -673,7 +674,7 @@ static char *low_match_types(char *a,char *b, int flags)
     return low_match_types(a,b,flags);
 
   case T_NOT:
-    if(low_match_types(a+1,b,flags | B_EXACT))
+    if(low_match_types(a+1,b,flags | B_EXACT | NO_MAX_ARGS))
       return 0;
     return a;
   }
@@ -695,7 +696,7 @@ static char *low_match_types(char *a,char *b, int flags)
     return low_match_types(a,b,flags);
 
   case T_NOT:
-    if(low_match_types(a,b+1, flags | A_EXACT))
+    if(low_match_types(a,b+1, flags | A_EXACT | NO_MAX_ARGS))
       return 0;
     return a;
   }
@@ -763,9 +764,10 @@ static char *low_match_types(char *a,char *b, int flags)
 	b+=type_length(b);
       }
 
-      if(!low_match_types(a_tmp, b_tmp, flags)) return 0;
+      if(!low_match_types(a_tmp, b_tmp, flags | NO_MAX_ARGS)) return 0;
       if(++correct_args > max_correct_args)
-	max_correct_args=correct_args;
+	if(!(flags & NO_MAX_ARGS))
+	  max_correct_args=correct_args;
     }
     /* check the 'many' type */
     a++;
@@ -775,8 +777,10 @@ static char *low_match_types(char *a,char *b, int flags)
       a+=type_length(a);
       b+=type_length(b);
     }else{
-      if(!low_match_types(a,b,flags)) return 0;
+      if(!low_match_types(a,b,flags | NO_MAX_ARGS)) return 0;
     }
+    if(!(flags & NO_MAX_ARGS))
+       max_correct_args=0x7fffffff;
     /* check the returntype */
     if(!low_match_types(a,b,flags)) return 0;
     break;
@@ -1087,29 +1091,52 @@ int check_indexing(struct pike_string *type,
   return low_check_indexing(type->str, index_type->str, n);
 }
 
+static int low_count_arguments(char *q)
+{
+  int num,num2;
+  
+  switch(EXTRACT_UCHAR(q++))
+  {
+    case T_OR:
+      num=low_count_arguments(q);
+      num2=low_count_arguments(q+type_length(q));
+      if(num<0 && num2>0) return num;
+      if(num2<0 && num>0) return num2;
+      if(num2<0 && num<0) return ~num>~num2?num:num2;
+      return num>num2?num:num2;
+
+    case T_AND:
+      num=low_count_arguments(q);
+      num2=low_count_arguments(q+type_length(q));
+      if(num<0 && num2>0) return num2;
+      if(num2<0 && num>0) return num;
+      if(num2<0 && num<0) return ~num<~num2?num:num2;
+      return num<num2?num:num2;
+
+    default: return MAX_LOCAL;
+
+    case T_FUNCTION:
+      num=0;
+      while(EXTRACT_UCHAR(q)!=T_MANY)
+      {
+	num++;
+	q+=type_length(q);
+      }
+      q++;
+      if(EXTRACT_UCHAR(q)!=T_VOID) return ~num;
+      return num;
+  }
+}
+
 /* Count the number of arguments for a funciton type.
  * return -1-n if the function can take number of arguments
  * >= n  (varargs)
  */
 int count_arguments(struct pike_string *s)
 {
-  int num;
-  char *q;
-
   CHECK_TYPE(s);
 
-  q=s->str;
-  if(EXTRACT_UCHAR(q) != T_FUNCTION) return MAX_LOCAL;
-  q++;
-  num=0;
-  while(EXTRACT_UCHAR(q)!=T_MANY)
-  {
-    num++;
-    q+=type_length(q);
-  }
-  q++;
-  if(EXTRACT_UCHAR(q)!=T_VOID) return ~num;
-  return num;
+  return low_count_arguments(s->str);
 }
 
 struct pike_string *check_call(struct pike_string *args,
@@ -1129,6 +1156,17 @@ struct pike_string *check_call(struct pike_string *args,
   }
 }
 
+INT32 get_max_args(struct pike_string *type)
+{
+  INT32 ret,tmp=max_correct_args;
+  CHECK_TYPE(type);
+  type=check_call(function_type_string, type);
+  if(type) free_string(type);
+  ret=max_correct_args;
+  max_correct_args=tmp;
+  return tmp;
+}
+
 struct pike_string *get_type_of_svalue(struct svalue *s)
 {
   struct pike_string *ret;
diff --git a/src/pike_types.h b/src/pike_types.h
index 0c449555f2e944e975de6559cf5f707b12b1b755..1f184c9071d4338834704eb6d52d92cca5d13dfb 100644
--- a/src/pike_types.h
+++ b/src/pike_types.h
@@ -85,6 +85,7 @@ int check_indexing(struct pike_string *type,
 int count_arguments(struct pike_string *s);
 struct pike_string *check_call(struct pike_string *args,
 			       struct pike_string *type);
+INT32 get_max_args(struct pike_string *type);
 struct pike_string *get_type_of_svalue(struct svalue *s);
 char *get_name_of_type(int t);
 void cleanup_pike_types(void);