diff --git a/src/operators.c b/src/operators.c
index d870a255838e76c73134c62022e17b02b86e5b9b..eca9dccce239c99c4abcc4662c491f83a3758af4 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -6,7 +6,7 @@
 /**/
 #include "global.h"
 #include <math.h>
-RCSID("$Id: operators.c,v 1.75 1999/12/13 20:44:15 grubba Exp $");
+RCSID("$Id: operators.c,v 1.76 1999/12/15 00:48:18 grubba Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -761,9 +761,41 @@ void o_and(void)
 {
   if(sp[-1].type != sp[-2].type)
   {
-    if(call_lfun(LFUN_AND, LFUN_RAND))
+    if(call_lfun(LFUN_AND, LFUN_RAND)) {
       return;
-    {
+    } else if (((sp[-1].type == T_TYPE) || (sp[-1].type == T_PROGRAM) ||
+		(sp[-1].type == T_FUNCTION)) &&
+	       ((sp[-2].type == T_TYPE) || (sp[-2].type == T_PROGRAM) ||
+		(sp[-2].type == T_FUNCTION))) {
+      if (sp[-2].type != T_TYPE) {
+	struct program *p = program_from_svalue(sp - 2);
+	if (!p) {
+	  int args = 2;
+	  SIMPLE_BAD_ARG_ERROR("`&", 1, "type");
+	}
+	type_stack_mark();
+	push_type_int(p->id);
+	push_type(0);
+	push_type(T_OBJECT);
+	free_svalue(sp - 2);
+	sp[-2].u.string = pop_unfinished_type();
+	sp[-2].type = T_TYPE;
+      }
+      if (sp[-1].type != T_TYPE) {
+	struct program *p = program_from_svalue(sp - 1);
+	if (!p) {
+	  int args = 2;
+	  SIMPLE_BAD_ARG_ERROR("`&", 2, "type");
+	}
+	type_stack_mark();
+	push_type_int(p->id);
+	push_type(0);
+	push_type(T_OBJECT);
+	free_svalue(sp - 1);
+	sp[-1].u.string = pop_unfinished_type();
+	sp[-1].type = T_TYPE;
+      }
+    } else {
       int args = 2;
       SIMPLE_BAD_ARG_ERROR("`&", 2, get_name_of_type(sp[-2].type));
     }
@@ -817,6 +849,46 @@ void o_and(void)
     return;
   }
 
+  case T_FUNCTION:
+  case T_PROGRAM:
+  {
+    struct program *p;
+    struct pike_string *a;
+    struct pike_string *b;
+    struct pike_string *t;
+
+    p = program_from_svalue(sp - 2);
+    if (!p) {
+      int args = 2;
+      SIMPLE_BAD_ARG_ERROR("`&", 1, "type");
+    }    
+    type_stack_mark();
+    push_type_int(p->id);
+    push_type(0);
+    push_type(T_OBJECT);
+    a = pop_unfinished_type();
+
+    p = program_from_svalue(sp - 1);
+    if (!p) {
+      int args = 2;
+      SIMPLE_BAD_ARG_ERROR("`&", 2, "type");
+    }    
+    type_stack_mark();
+    push_type_int(p->id);
+    push_type(0);
+    push_type(T_OBJECT);
+    b = pop_unfinished_type();
+
+    t = and_pike_types(a, b);
+
+    pop_n_elems(2);
+    push_string(t);
+    sp[-1].type = T_TYPE;
+    free_string(a);
+    free_string(b);
+    return;
+  }
+
 #define STRING_BITOP(OP,STROP)						  \
   case T_STRING:							  \
   {									  \
@@ -958,10 +1030,41 @@ void o_or(void)
 {
   if(sp[-1].type != sp[-2].type)
   {
-    if(call_lfun(LFUN_OR, LFUN_ROR))
+    if(call_lfun(LFUN_OR, LFUN_ROR)) {
       return;
-
-    {
+    } else if (((sp[-1].type == T_TYPE) || (sp[-1].type == T_PROGRAM) ||
+		(sp[-1].type == T_FUNCTION)) &&
+	       ((sp[-2].type == T_TYPE) || (sp[-2].type == T_PROGRAM) ||
+		(sp[-2].type == T_FUNCTION))) {
+      if (sp[-2].type != T_TYPE) {
+	struct program *p = program_from_svalue(sp - 2);
+	if (!p) {
+	  int args = 2;
+	  SIMPLE_BAD_ARG_ERROR("`|", 1, "type");
+	}
+	type_stack_mark();
+	push_type_int(p->id);
+	push_type(0);
+	push_type(T_OBJECT);
+	free_svalue(sp - 2);
+	sp[-2].u.string = pop_unfinished_type();
+	sp[-2].type = T_TYPE;
+      }
+      if (sp[-1].type != T_TYPE) {
+	struct program *p = program_from_svalue(sp - 1);
+	if (!p) {
+	  int args = 2;
+	  SIMPLE_BAD_ARG_ERROR("`|", 2, "type");
+	}
+	type_stack_mark();
+	push_type_int(p->id);
+	push_type(0);
+	push_type(T_OBJECT);
+	free_svalue(sp - 1);
+	sp[-1].u.string = pop_unfinished_type();
+	sp[-1].type = T_TYPE;
+      }
+    } else {
       int args = 2;
       SIMPLE_BAD_ARG_ERROR("`|", 2, get_name_of_type(sp[-2].type));
     }
@@ -1015,6 +1118,46 @@ void o_or(void)
     return;
   }
 
+  case T_FUNCTION:
+  case T_PROGRAM:
+  {
+    struct program *p;
+    struct pike_string *a;
+    struct pike_string *b;
+    struct pike_string *t;
+
+    p = program_from_svalue(sp - 2);
+    if (!p) {
+      int args = 2;
+      SIMPLE_BAD_ARG_ERROR("`|", 1, "type");
+    }
+    type_stack_mark();
+    push_type_int(p->id);
+    push_type(0);
+    push_type(T_OBJECT);
+    a = pop_unfinished_type();
+
+    p = program_from_svalue(sp - 1);
+    if (!p) {
+      int args = 2;
+      SIMPLE_BAD_ARG_ERROR("`|", 2, "type");
+    }
+    type_stack_mark();
+    push_type_int(p->id);
+    push_type(0);
+    push_type(T_OBJECT);
+    b = pop_unfinished_type();
+
+    t = or_pike_types(a, b, 0);
+
+    pop_n_elems(2);
+    push_string(t);
+    sp[-1].type = T_TYPE;
+    free_string(a);
+    free_string(b);
+    return;
+  }
+
   STRING_BITOP(|,"OR")
 
   default:
@@ -1062,9 +1205,41 @@ void o_xor(void)
 {
   if(sp[-1].type != sp[-2].type)
   {
-    if(call_lfun(LFUN_XOR, LFUN_RXOR))
+    if(call_lfun(LFUN_XOR, LFUN_RXOR)) {
       return;
-    {
+    } else if (((sp[-1].type == T_TYPE) || (sp[-1].type == T_PROGRAM) ||
+		(sp[-1].type == T_FUNCTION)) &&
+	       ((sp[-2].type == T_TYPE) || (sp[-2].type == T_PROGRAM) ||
+		(sp[-2].type == T_FUNCTION))) {
+      if (sp[-2].type != T_TYPE) {
+	struct program *p = program_from_svalue(sp - 2);
+	if (!p) {
+	  int args = 2;
+	  SIMPLE_BAD_ARG_ERROR("`^", 1, "type");
+	}
+	type_stack_mark();
+	push_type_int(p->id);
+	push_type(0);
+	push_type(T_OBJECT);
+	free_svalue(sp - 2);
+	sp[-2].u.string = pop_unfinished_type();
+	sp[-2].type = T_TYPE;
+      }
+      if (sp[-1].type != T_TYPE) {
+	struct program *p = program_from_svalue(sp - 1);
+	if (!p) {
+	  int args = 2;
+	  SIMPLE_BAD_ARG_ERROR("`^", 2, "type");
+	}
+	type_stack_mark();
+	push_type_int(p->id);
+	push_type(0);
+	push_type(T_OBJECT);
+	free_svalue(sp - 1);
+	sp[-1].u.string = pop_unfinished_type();
+	sp[-1].type = T_TYPE;
+      }
+    } else {
       int args = 2;
       SIMPLE_BAD_ARG_ERROR("`^", 2, get_name_of_type(sp[-2].type));
     }
@@ -1108,6 +1283,41 @@ void o_xor(void)
     return;
   }
 
+  case T_FUNCTION:
+  case T_PROGRAM:
+  {
+    struct program *p;
+
+    p = program_from_svalue(sp - 1);
+    if (!p) {
+      int args = 2;
+      SIMPLE_BAD_ARG_ERROR("`^", 2, "type");
+    }
+    type_stack_mark();
+    push_type_int(sp[-1].u.program->id);
+    push_type(0);
+    push_type(T_OBJECT);
+    pop_stack();
+    push_string(pop_unfinished_type());
+    sp[-1].type = T_TYPE;
+
+    stack_swap();
+
+    p = program_from_svalue(sp - 1);
+    if (!p) {
+      int args = 2;
+      stack_swap();
+      SIMPLE_BAD_ARG_ERROR("`^", 1, "type");
+    }
+    type_stack_mark();
+    push_type_int(sp[-1].u.program->id);
+    push_type(0);
+    push_type(T_OBJECT);
+    pop_stack();
+    push_string(pop_unfinished_type());
+    sp[-1].type = T_TYPE;
+  }
+  /* FALL_THROUGH */
   case T_TYPE:
   {
     /* a ^ b  ==  (a&~b)|(~a&b) */
@@ -1871,13 +2081,36 @@ void o_compl(void)
 
   case T_TYPE:
     type_stack_mark();
-    push_unfinished_type(sp[-1].u.string->str);
-    push_type(T_NOT);
+    if (EXTRACT_UCHAR(sp[-1].u.string->str) == T_NOT) {
+      push_unfinished_type(sp[-1].u.string->str + 1);
+    } else {
+      push_unfinished_type(sp[-1].u.string->str);
+      push_type(T_NOT);
+    }
     pop_stack();
     push_string(pop_unfinished_type());
     sp[-1].type = T_TYPE;
     break;
 
+  case T_FUNCTION:
+  case T_PROGRAM:
+    {
+      /* !object(p) */
+      struct program *p = program_from_svalue(sp - 1);
+      if (!p) {
+	PIKE_ERROR("`~", "Bad argument.\n", sp, 1);
+      }
+      type_stack_mark();
+      push_type_int(p->id);
+      push_type(0);
+      push_type(T_OBJECT);
+      push_type(T_NOT);
+      pop_stack();
+      push_string(pop_unfinished_type());
+      sp[-1].type = T_TYPE;
+    }
+    break;
+
   case T_STRING:
   {
     struct pike_string *s;
@@ -2215,7 +2448,7 @@ void init_operators(void)
   add_efun2("`!",f_not,"function(mixed:int(0..1))",OPT_TRY_OPTIMIZE,
 	    optimize_not,generate_not);
 
-#define CMP_TYPE "!function(!(object|mixed)...:mixed)&function(mixed...:int(0..1))|function(int|float...:int(0..1))|function(string...:int(0..1))|function(type,type,type...:int(0..1))"
+#define CMP_TYPE "!function(!(object|mixed)...:mixed)&function(mixed...:int(0..1))|function(int|float...:int(0..1))|function(string...:int(0..1))|function(type|program,type|program,type|program...:int(0..1))"
   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);
@@ -2249,7 +2482,7 @@ void init_operators(void)
 		 tFuncV(tStr,tStr,tStr)),
 	    OPT_TRY_OPTIMIZE,0,generate_minus);
 
-#define LOG_TYPE "function(mixed,object...:mixed)|function(object,mixed...:mixed)|function(int...:int)|function(mapping(0=mixed:1=mixed)...:mapping(0:1))|function(multiset(2=mixed)...:multiset(2))|function(array(3=mixed)...:array(3))|function(string...:string)|function(type,type...:type)"
+#define LOG_TYPE "function(mixed,object...:mixed)|function(object,mixed...:mixed)|function(int...:int)|function(mapping(0=mixed:1=mixed)...:mapping(0:1))|function(multiset(2=mixed)...:multiset(2))|function(array(3=mixed)...:array(3))|function(string...:string)|function(type|program,type|program...:type)"
 
   add_efun2("`&",f_and,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_and);
 
@@ -2304,7 +2537,7 @@ void init_operators(void)
 		 tFunc(tInt,tInt),
 		 tFunc(tFlt,tFlt),
 		 tFunc(tStr,tStr),
-		 tFunc(tType,tType)),
+		 tFunc(tOr(tType,tProgram),tType)),
 	    OPT_TRY_OPTIMIZE,0,generate_compl);
   /* function(string|multiset|array|mapping|object:int) */
   ADD_EFUN2("sizeof", f_sizeof,tFunc(tOr5(tStr,tMultiset,tArray,tMapping,tObj),tInt),0,0,generate_sizeof);