diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index b55450f28238811ca2ae6a46e978ed34404a8b96..e97d0fd7b84936ca7d5af8f7c33fc6b3ac3ae98d 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.100 1998/04/17 05:08:01 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.101 1998/04/24 00:32:08 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -1406,8 +1406,7 @@ void f_column(INT32 args)
 #ifdef DEBUG
 void f__verify_internals(INT32 args)
 {
-  INT32 tmp;
-  tmp=d_flag;
+  INT32 tmp=d_flag;
   d_flag=0x7fffffff;
   do_debug();
   d_flag=tmp;
@@ -2775,8 +2774,8 @@ void init_builtin_efuns(void)
   add_efun("gc",f_gc,"function(:int)",OPT_SIDE_EFFECT);
   add_efun("version", f_version, "function(:string)", OPT_TRY_OPTIMIZE);
 
-  add_efun("encode_value", f_encode_value, "function(mixed:string)", OPT_TRY_OPTIMIZE);
-  add_efun("decode_value", f_decode_value, "function(string:mixed)", OPT_TRY_OPTIMIZE);
+  add_efun("encode_value", f_encode_value, "function(mixed,void|object:string)", OPT_TRY_OPTIMIZE);
+  add_efun("decode_value", f_decode_value, "function(string,void|object:mixed)", OPT_TRY_OPTIMIZE);
   add_efun("object_variablep", f_object_variablep, "function(object,string:int)", OPT_EXTERNAL_DEPEND);
 
   add_function("diff",f_diff,"function(array,array:array(array))",OPT_TRY_OPTIMIZE);
diff --git a/src/compilation.h b/src/compilation.h
index dfac0397e4b84e8d1edcbfb0baa2ba7f1cb5d272..c69032220b838eea8b5339e67723c7c1fee6fdb4 100644
--- a/src/compilation.h
+++ b/src/compilation.h
@@ -1,5 +1,5 @@
 /*
- * $Id: compilation.h,v 1.8 1998/03/28 15:38:36 grubba Exp $
+ * $Id: compilation.h,v 1.9 1998/04/24 00:32:08 hubbe Exp $
  *
  * Compilator state push / pop operator construction file
  *
@@ -86,11 +86,12 @@
   ZMEMBER(INT32,last_pc)
   ZMEMBER(int,num_parse_error)
   ZMEMBER(struct compiler_frame *,compiler_frame)
-  ZMEMBER(dynamic_buffer,used_modules)
+  ZMEMBER(INT32,num_used_modules)
   IMEMBER(int,comp_stackp)
   IMEMBER(int,compiler_pass)
   ZMEMBER(int,local_class_counter)
   ZMEMBER(int,catch_level)
+  ZMEMBER(struct mapping *,module_index_cache)
   SEND
 
 #undef PCODE
diff --git a/src/encode.c b/src/encode.c
index b6e40c838899904e4d11a17ec1b0f828247d3ec8..dbfacd50d7d46219addb11758a3ffd97c3435f46 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -17,8 +17,10 @@
 #include "error.h"
 #include "operators.h"
 #include "builtin_functions.h"
+#include "module_support.h"
+#include "fsort.h"
 
-RCSID("$Id: encode.c,v 1.19 1998/04/20 18:53:15 grubba Exp $");
+RCSID("$Id: encode.c,v 1.20 1998/04/24 00:32:08 hubbe Exp $");
 
 #ifdef _AIX
 #include <net/nh.h>
@@ -51,16 +53,31 @@ double LDEXP(double x, int exp)
 }
 #endif
 
+#ifdef DEBUG
+#define encode_value2 encode_value2_
+#define decode_value2 decode_value2_
+#endif
+
+
 
 struct encode_data
 {
+  struct object *codec;
   struct svalue counter;
   struct mapping *encoded;
   dynamic_buffer buf;
 };
 
+static void encode_value2(struct svalue *val, struct encode_data *data);
+
 #define addstr(s, l) low_my_binary_strcat((s), (l), &(data->buf))
 #define addchar(t)   low_my_putchar((t),&(data->buf))
+#define adddata(S) do { \
+  code_entry(T_STRING, (S)->len, data); \
+  addstr((char *)((S)->str),(S)->len); \
+}while(0)
+
+#define adddata2(s,l) addstr((char *)(s),(l) * sizeof(s[0]));
 
 /* Current encoding: �ik0 */
 #define T_AGAIN 15
@@ -110,9 +127,89 @@ static void code_entry(int type, INT32 num, struct encode_data *data)
   }
 }
 
-#ifdef DEBUG
-#define encode_value2 encode_value2_
-#endif
+
+static void code_number(INT32 num, struct encode_data *data)
+{
+  code_entry(num & 15, num >> 4, data);
+}
+
+static int encode_type(char *t, struct encode_data *data)
+{
+  char *q=t;
+one_more_type:
+  addchar(EXTRACT_UCHAR(t));
+  switch(EXTRACT_UCHAR(t++))
+  {
+    default:
+      fatal("error in type string.\n");
+      /*NOTREACHED*/
+      
+      break;
+      
+    case T_ASSIGN:
+      addchar(EXTRACT_UCHAR(t++));
+      goto one_more_type;
+      
+    case T_FUNCTION:
+      while(EXTRACT_UCHAR(t)!=T_MANY)
+	t+=encode_type(t, data);
+      addchar(EXTRACT_UCHAR(t++));
+      
+    case T_MAPPING:
+    case T_OR:
+    case T_AND:
+      t+=encode_type(t, data);
+      
+    case T_ARRAY:
+    case T_MULTISET:
+    case T_NOT:
+      goto one_more_type;
+      
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case T_INT:
+    case T_FLOAT:
+    case T_STRING:
+    case T_PROGRAM:
+    case T_MIXED:
+    case T_VOID:
+    case T_UNKNOWN:
+      break;
+      
+    case T_OBJECT:
+    {
+      INT32 x;
+      addchar(EXTRACT_UCHAR(t++));
+      x=EXTRACT_INT(t);
+      t+=sizeof(INT32);
+      if(x)
+      {
+	struct program *p=id_to_program(x);
+	if(p)
+	{
+	  ref_push_program(p);
+	}else{
+	  push_int(0);
+	}
+      }else{
+	push_int(0);
+      }
+      encode_value2(sp-1, data);
+      pop_stack();
+      break;
+    }
+  }
+  return t-q;
+}
+
 
 static void encode_value2(struct svalue *val, struct encode_data *data)
 
@@ -126,7 +223,8 @@ static void encode_value2(struct svalue *val, struct encode_data *data)
   INT32 i;
   struct svalue *tmp;
   
-  if((val->type == T_OBJECT || val->type==T_FUNCTION) && !val->u.object->prog)
+  if((val->type == T_OBJECT || (val->type==T_FUNCTION && \
+				val->subtype!=FUNCTION_BUILTIN)) && !val->u.object->prog)
     val=&dested;
   
   if((tmp=low_mapping_lookup(data->encoded, val)))
@@ -209,22 +307,22 @@ static void encode_value2(struct svalue *val, struct encode_data *data)
     case T_OBJECT:
       check_stack(1);
       push_svalue(val);
-      APPLY_MASTER("nameof", 1);
+      apply(data->codec, "nameof", 1);
       switch(sp[-1].type)
       {
 	case T_INT:
 	  if(sp[-1].subtype == NUMBER_UNDEFINED) 
 	  {
-	    struct svalue s;
-	    s.type = T_PROGRAM;
-	    s.u.program=val->u.object->prog;
-	    
 	    pop_stack();
+	    push_svalue(val);
+	    f_object_program(1);
+	    
 	    code_entry(val->type, 1,data);
-	    encode_value2(&s, data);
+	    encode_value2(sp-1, data);
+	    pop_stack();
 	    
 	    push_svalue(val);
-	    APPLY_MASTER("encode_object",1);
+	    apply(data->codec,"encode_object",1);
 	    break;
 	  }
 	  /* FALL THROUGH */
@@ -241,7 +339,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data)
     case T_FUNCTION:
       check_stack(1);
       push_svalue(val);
-      APPLY_MASTER("nameof", 1);
+      apply(data->codec,"nameof", 1);
       if(sp[-1].type == T_INT && sp[-1].subtype==NUMBER_UNDEFINED)
       {
 	if(val->subtype != FUNCTION_BUILTIN)
@@ -282,15 +380,92 @@ static void encode_value2(struct svalue *val, struct encode_data *data)
       
       
     case T_PROGRAM:
+    {
+      int d;
       check_stack(1);
       push_svalue(val);
-      APPLY_MASTER("nameof", 1);
+      apply(data->codec,"nameof", 1);
       if(sp[-1].type == val->type)
 	error("Error in master()->nameof(), same type returned.\n");
-      code_entry(val->type, 0,data);
-      encode_value2(sp-1, data);
+      if(sp[-1].type == T_INT && sp[-1].subtype == NUMBER_UNDEFINED)
+      {
+	INT32 e;
+	struct program *p=val->u.program;
+	if(p->init || p->exit || p->gc_marked || p->gc_check ||
+	   (p->flags & PROGRAM_HAS_C_METHODS))
+	  error("Cannot encode C programs.\n");
+	code_entry(val->type, 1,data);
+	code_number(p->flags,data);
+	code_number(p->storage_needed,data);
+	code_number(p->timestamp.tv_sec,data);
+	code_number(p->timestamp.tv_usec,data);
+
+#define FOO(X,Y,Z) \
+	code_number( p->num_##Z, data);
+#include "program_areas.h"
+
+	adddata2(p->program, p->num_program);
+	adddata2(p->linenumbers, p->num_linenumbers);
+
+	for(d=0;d<p->num_identifier_index;d++)
+	  code_number(p->identifier_index[d],data);
+
+	for(d=0;d<p->num_variable_index;d++)
+	  code_number(p->variable_index[d],data);
+
+	for(d=0;d<p->num_identifier_references;d++)
+	{
+	  code_number(p->identifier_references[d].inherit_offset,data);
+	  code_number(p->identifier_references[d].identifier_offset,data);
+	  code_number(p->identifier_references[d].id_flags,data);
+	}
+	  
+	for(d=0;d<p->num_strings;d++) adddata(p->strings[d]);
+
+	for(d=1;d<p->num_inherits;d++)
+	{
+	  code_number(p->inherits[d].inherit_level,data);
+	  code_number(p->inherits[d].identifier_level,data);
+	  code_number(p->inherits[d].parent_offset,data);
+	  code_number(p->inherits[d].storage_offset,data);
+
+	  if(p->inherits[d].parent)
+	  {
+	    ref_push_object(p->inherits[d].parent);
+	    sp[-1].subtype=p->inherits[d].parent_identifier;
+	    sp[-1].type=T_FUNCTION;
+	  }else if(p->inherits[d].prog){
+	    ref_push_program(p->inherits[d].prog);
+	  }else{
+	    push_int(0);
+	  }
+	  encode_value2(sp-1,data);
+	  pop_stack();
+
+	  adddata(p->inherits[d].name);
+	}
+
+	for(d=0;d<p->num_identifiers;d++)
+	{
+	  adddata(p->identifiers[d].name);
+	  encode_type(p->identifiers[d].type->str, data);
+	  code_number(p->identifiers[d].identifier_flags,data);
+	  code_number(p->identifiers[d].run_time_type,data);
+	  code_number(p->identifiers[d].func.offset,data);
+	}
+
+	for(d=0;d<p->num_constants;d++)
+	  encode_value2(p->constants+d, data);
+
+	for(d=0;d<NUM_LFUNS;d++)
+	  code_number(p->lfuns[d], data);
+      }else{
+	code_entry(val->type, 0,data);
+	encode_value2(sp-1, data);
+      }
       pop_stack();
       break;
+      }
   }
 }
 
@@ -305,11 +480,19 @@ void f_encode_value(INT32 args)
   ONERROR tmp;
   struct encode_data d, *data;
   data=&d;
+  
+  check_all_args("encode_value", args, BIT_MIXED, BIT_VOID | BIT_OBJECT, 0);
 
   initialize_buf(&data->buf);
   data->encoded=allocate_mapping(128);
   data->counter.type=T_INT;
   data->counter.u.integer=COUNTER_START;
+  if(args > 1)
+  {
+    data->codec=sp[1-args].u.object;
+  }else{
+    data->codec=get_master();
+  }
 
   SET_ONERROR(tmp, free_encode_data, data);
   addstr("\266ke0", 4);
@@ -317,6 +500,7 @@ void f_encode_value(INT32 args)
   UNSET_ONERROR(tmp);
 
   free_mapping(data->encoded);
+
   pop_n_elems(args);
   push_string(low_free_buf(&data->buf));
 }
@@ -328,8 +512,12 @@ struct decode_data
   INT32 ptr;
   struct mapping *decoded;
   struct svalue counter;
+  struct object *codec;
+  int pickyness;
 };
 
+static void decode_value2(struct decode_data *data);
+
 static int my_extract_char(struct decode_data *data)
 {
   if(data->ptr >= data->len)
@@ -351,9 +539,124 @@ static int my_extract_char(struct decode_data *data)
   } \
   if(what & T_NEG) num=~num
 
-#ifdef DEBUG
-#define decode_value2 decode_value2_
-#endif
+
+#define decode_entry(X,Y,Z)					\
+  do {								\
+    INT32 what, e, num;                                         \
+    DECODE();							\
+    if((what & T_MASK) != (X)) error("Failed to decode, wrong bits (%d).\n", what & T_MASK);\
+    (Y)=num;							\
+  } while(0);
+
+#define getdata2(S,L) do {						\
+      if(data->ptr + (long)(sizeof(S[0])*(L)) > data->len)		\
+	error("Failed to decode string. (string range error)\n");	\
+      MEMCPY((S),(data->data + data->ptr), sizeof(S[0])*(L));		\
+      data->ptr+=sizeof(S[0])*(L);					\
+  }while(0)
+
+#define getdata(X) do {							     \
+   long length;								     \
+      decode_entry(T_STRING, length,data);				     \
+      if(data->ptr + length > data->len || length <0)			     \
+	error("Failed to decode string. (string range error)\n");	     \
+      X=make_shared_binary_string((char *)(data->data + data->ptr), length); \
+      data->ptr+=length;						     \
+  }while(0)
+
+#define decode_number(X,data) do {	\
+   int what, e, num;				\
+   DECODE();					\
+   X=(what & T_MASK) | (num<<4);		\
+  }while(0)					\
+
+
+static void low_decode_type(struct decode_data *data)
+{
+  int tmp;
+one_more_type:
+  push_type(tmp=GETC());
+  switch(tmp)
+  {
+    default:
+      fatal("error in type string.\n");
+      /*NOTREACHED*/
+      break;
+      
+    case T_ASSIGN:
+      push_type(GETC());
+      goto one_more_type;
+      
+    case T_FUNCTION:
+      while(GETC()!=T_MANY)
+      {
+	data->ptr--;
+	low_decode_type(data);
+      }
+      push_type(T_MANY);
+      
+    case T_MAPPING:
+    case T_OR:
+    case T_AND:
+      low_decode_type(data);
+
+    case T_ARRAY:
+    case T_MULTISET:
+    case T_NOT:
+      goto one_more_type;
+      
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case T_INT:
+    case T_FLOAT:
+    case T_STRING:
+    case T_PROGRAM:
+    case T_MIXED:
+    case T_VOID:
+    case T_UNKNOWN:
+      break;
+      
+    case T_OBJECT:
+    {
+      INT32 x;
+      push_type(GETC());
+      decode_value2(data);
+      type_stack_mark();
+      switch(sp[-1].type)
+      {
+	case T_INT:
+	  push_type_int(0);
+	  break;
+
+	case T_PROGRAM:
+	  push_type_int(sp[-1].u.program->id);
+	  break;
+	  
+	default:
+	  error("Failed to decode type.\n");
+      }
+      pop_stack();
+      type_stack_reverse();
+    }
+  }
+}
+
+/* This really needs to disable threads.... */
+#define decode_type(X,data)  do {		\
+  type_stack_mark();				\
+  type_stack_mark();				\
+  low_decode_type(data);			\
+  type_stack_reverse();				\
+  (X)=pop_unfinished_type();			\
+} while(0)
 
 static void decode_value2(struct decode_data *data)
 
@@ -488,7 +791,14 @@ static void decode_value2(struct decode_data *data)
       switch(num)
       {
 	case 0:
-	  APPLY_MASTER("objectof", 1);
+	  if(data->codec)
+	  {
+	    apply(data->codec,"objectof", 1);
+	  }else{
+	    ref_push_mapping(get_builtin_constants());
+	    stack_swap();
+	    f_index(2);
+	  }
 	  break;
 	  
 	case 1:
@@ -502,15 +812,21 @@ static void decode_value2(struct decode_data *data)
 	    mapping_insert(data->decoded, &tmp, sp-1);
 	    push_svalue(sp-1);
 	    decode_value2(data);
-	    APPLY_MASTER("decode_object",2);
+	    if(!data->codec)
+	      error("Failed to decode (no codec)\n");
+	    apply(data->codec,"decode_object",2);
 	    pop_stack();
 	  }
+	  if(data->pickyness && sp[-1].type != T_OBJECT)
+	    error("Failed to decode object.\n");
 	  return;
 	  
 	default:
 	  error("Object coding not compatible.\n");
 	  break;
       }
+      if(data->pickyness && sp[-1].type != T_OBJECT)
+	error("Failed to decode.\n");
       break;
       
     case T_FUNCTION:
@@ -521,7 +837,14 @@ static void decode_value2(struct decode_data *data)
       switch(num)
       {
 	case 0:
-	  APPLY_MASTER("objectof", 1);
+	  if(data->codec)
+	  {
+	    apply(data->codec,"functionof", 1);
+	  }else{
+	    ref_push_mapping(get_builtin_constants());
+	    stack_swap();
+	    f_index(2);
+	  }
 	  break;
 	  
 	case 1:
@@ -533,14 +856,201 @@ static void decode_value2(struct decode_data *data)
 	  error("Function coding not compatible.\n");
 	  break;
       }
+      if(data->pickyness && sp[-1].type != T_FUNCTION)
+	error("Failed to decode function.\n");
       break;
       
       
     case T_PROGRAM:
-      tmp=data->counter;
-      data->counter.u.integer++;
-      decode_value2(data);
-      APPLY_MASTER("programof", 1);
+      switch(num)
+      {
+	case 0:
+	  tmp=data->counter;
+	  data->counter.u.integer++;
+	  decode_value2(data);
+	  if(data->codec)
+	  {
+	    apply(data->codec,"programof", 1);
+	  }else{
+	    ref_push_mapping(get_builtin_constants());
+	    stack_swap();
+	    f_index(2);
+	  }
+	  if(data->pickyness && sp[-1].type != T_PROGRAM)
+	    error("Failed to decode program.\n");
+	  break;
+
+	case 1:
+	{
+	  int d;
+	  SIZE_T size=0;
+	  char *dat;
+	  struct program *p;
+
+	  p=low_allocate_program();
+	  debug_malloc_touch(p);
+	  tmp.type=T_PROGRAM;
+	  tmp.u.program=p;
+	  mapping_insert(data->decoded, & data->counter, &tmp);
+	  data->counter.u.integer++;
+	  p->refs--;
+	  
+	  decode_number(p->flags,data);
+	  p->flags &= ~(PROGRAM_FINISHED | PROGRAM_OPTIMIZED);
+	  decode_number(p->storage_needed,data);
+	  decode_number(p->timestamp.tv_sec,data);
+	  decode_number(p->timestamp.tv_usec,data);
+
+#define FOO(X,Y,Z) \
+	  decode_number( p->num_##Z, data);
+#include "program_areas.h"
+	  
+#define FOO(NUMTYPE,TYPE,NAME) \
+          size=DO_ALIGN(size, ALIGNOF(TYPE)); \
+          size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]);
+#include "program_areas.h"
+
+	  dat=xalloc(size);
+	  debug_malloc_touch(dat);
+	  MEMSET(dat,0,size);
+	  size=0;
+#define FOO(NUMTYPE,TYPE,NAME) \
+	  size=DO_ALIGN(size, ALIGNOF(TYPE)); \
+          p->NAME=(TYPE *)(dat+size); \
+          size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]);
+#include "program_areas.h"
+
+	  for(e=0;e<p->num_constants;e++)
+	    p->constants[e].type=T_INT;
+
+	  debug_malloc_touch(dat);
+
+	  p->total_size=size + sizeof(struct program);
+
+	  p->flags |= PROGRAM_OPTIMIZED;
+
+	  getdata2(p->program, p->num_program);
+	  getdata2(p->linenumbers, p->num_linenumbers);
+
+	  for(d=0;d<p->num_identifier_index;d++)
+	  {
+	    decode_number(p->identifier_index[d],data);
+	    if(p->identifier_index[d] > p->num_identifier_references)
+	    {
+	      p->identifier_index[d]=0;
+	      error("Malformed program in decode.\n");
+	    }
+	  }
+	  
+	  for(d=0;d<p->num_variable_index;d++)
+	  {
+	    decode_number(p->variable_index[d],data);
+	    if(p->variable_index[d] > p->num_identifiers)
+	    {
+	      p->variable_index[d]=0;
+	      error("Malformed program in decode.\n");
+	    }
+	  }
+	  
+	  for(d=0;d<p->num_identifier_references;d++)
+	  {
+	    decode_number(p->identifier_references[d].inherit_offset,data);
+	    if(p->identifier_references[d].inherit_offset > p->num_inherits)
+	    {
+	      p->identifier_references[d].inherit_offset=0;
+	      error("Malformed program in decode.\n");
+	    }
+	    decode_number(p->identifier_references[d].identifier_offset,data);
+	    decode_number(p->identifier_references[d].id_flags,data);
+	  }
+	  
+	  for(d=0;d<p->num_strings;d++)
+	    getdata(p->strings[d]);
+
+	  debug_malloc_touch(dat);
+
+	  data->pickyness++;
+	  p->inherits[0].prog=p;
+	  p->inherits[0].parent_offset=1;
+
+	  for(d=1;d<p->num_inherits;d++)
+	  {
+	    decode_number(p->inherits[d].inherit_level,data);
+	    decode_number(p->inherits[d].identifier_level,data);
+	    decode_number(p->inherits[d].parent_offset,data);
+	    decode_number(p->inherits[d].storage_offset,data);
+	    
+	    decode_value2(data);
+	    switch(sp[-1].type)
+	    {
+	      case T_FUNCTION:
+		if(sp[-1].subtype == FUNCTION_BUILTIN)
+		  error("Failed to decode parent.\n");
+		
+		p->inherits[d].parent_identifier=sp[-1].subtype;
+		p->inherits[d].prog=program_from_svalue(sp-1);
+		if(!p->inherits[d].prog)
+		  error("Failed to decode parent.\n");
+		add_ref(p->inherits[d].prog);
+		p->inherits[d].parent=sp[-1].u.object;
+		sp--;
+		break;
+
+	      case T_PROGRAM:
+		p->inherits[d].parent_identifier=0;
+		p->inherits[d].prog=sp[-1].u.program;
+		sp--;
+		break;
+	      default:
+		error("Failed to decode inheritance.\n");
+	    }
+	    
+	    getdata(p->inherits[d].name);
+	  }
+	  
+	  debug_malloc_touch(dat);
+
+	  for(d=0;d<p->num_identifiers;d++)
+	  {
+	    getdata(p->identifiers[d].name);
+	    decode_type(p->identifiers[d].type,data);
+	    decode_number(p->identifiers[d].identifier_flags,data);
+	    decode_number(p->identifiers[d].run_time_type,data);
+	    decode_number(p->identifiers[d].func.offset,data);
+	  }
+
+	  debug_malloc_touch(dat);
+	  
+	  for(d=0;d<p->num_constants;d++)
+	  {
+	    decode_value2(data);
+	    p->constants[d]=*--sp;
+	  }
+	  data->pickyness--;
+
+	  debug_malloc_touch(dat);
+
+	  for(d=0;d<NUM_LFUNS;d++)
+	    decode_number(p->lfuns[d],data);
+
+	  debug_malloc_touch(dat);
+	  
+	  {
+	    struct program *new_program_save=new_program;
+	    new_program=p;
+	    fsort((void *)p->identifier_index,
+		  p->num_identifier_index,
+		  sizeof(unsigned short),(fsortfun)program_function_index_compare);
+	    new_program=new_program_save;
+	  }
+	  p->flags |= PROGRAM_FINISHED;
+	  ref_push_program(p);
+	  return;
+	}
+
+	default:
+	  error("Cannot decode program encoding type %d\n",num);
+      }
       break;
 
   default:
@@ -556,7 +1066,8 @@ static void free_decode_data(struct decode_data *data)
   free_mapping(data->decoded);
 }
 
-static INT32 my_decode(struct pike_string *tmp)
+static INT32 my_decode(struct pike_string *tmp,
+		       struct object *codec)
 {
   ONERROR err;
   struct decode_data d, *data;
@@ -566,6 +1077,8 @@ static INT32 my_decode(struct pike_string *tmp)
   data->data=(unsigned char *)tmp->str;
   data->len=tmp->len;
   data->ptr=0;
+  data->codec=codec;
+  data->pickyness=0;
 
   if(data->len < 5) return 0;
   if(GETC() != 182 ||
@@ -689,12 +1202,25 @@ static void rec_restore_value(char **v, INT32 *l)
 void f_decode_value(INT32 args)
 {
   struct pike_string *s;
+  struct object *codec;
 
-  if(args != 1 || (sp[-1].type != T_STRING))
-    error("Illegal argument to decode_value()\n");
+  check_all_args("decode_value",args, BIT_STRING, BIT_VOID | BIT_OBJECT | BIT_INT, 0);
 
-  s = sp[-1].u.string;
-  if(!my_decode(s))
+  s = sp[-args].u.string;
+  if(args<2)
+  {
+    codec=get_master();
+  }
+  else if(sp[1-args].type == T_OBJECT)
+  {
+    codec=sp[1-args].u.object;
+  }
+  else
+  {
+    codec=0;
+  }
+
+  if(!my_decode(s, codec))
   {
     char *v=s->str;
     INT32 l=s->len;
@@ -704,3 +1230,4 @@ void f_decode_value(INT32 args)
   pop_n_elems(args);
 }
 
+
diff --git a/src/gc.c b/src/gc.c
index b9e327feaaac7f23376f41815ebd34ce07a8b241..c2fcd938454433bca982577a4c50770f20f3c314 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -25,7 +25,7 @@ struct callback *gc_evaluator_callback=0;
 #include "main.h"
 #include <math.h>
 
-RCSID("$Id: gc.c,v 1.35 1998/04/20 18:53:16 grubba Exp $");
+RCSID("$Id: gc.c,v 1.36 1998/04/24 00:32:08 hubbe Exp $");
 
 /* Run garbage collect approximate every time we have
  * 20 percent of all arrays, objects and programs is
@@ -337,7 +337,7 @@ void describe_something(void *a, int t, int dm)
       INT32 line,pos;
 
       fprintf(stderr,"**Program id: %ld\n",(long)(p->id));
-      if(!p->num_linenumbers)
+      if(p->flags & PROGRAM_HAS_C_METHODS)
       {
 	int e;
 	fprintf(stderr,"**The program was written in C.\n");
diff --git a/src/object.c b/src/object.c
index 982cc346a3d021d9e38b224383b85b0504d5a8b2..dfe941db334d97c60f22cc9e633bf8f89fe99199 100644
--- a/src/object.c
+++ b/src/object.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: object.c,v 1.47 1998/04/17 16:55:48 hubbe Exp $");
+RCSID("$Id: object.c,v 1.48 1998/04/24 00:32:09 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -59,7 +59,7 @@ struct object *low_clone(struct program *p)
   return o;
 }
 
-static void call_c_initializers(struct object *o)
+void call_c_initializers(struct object *o)
 {
   int e;
   struct frame frame;
@@ -77,17 +77,15 @@ static void call_c_initializers(struct object *o)
   /* clear globals and call C initializers */
   for(e=p->num_inherits-1; e>=0; e--)
   {
-    int d;
+    int q;
 
     frame.context=p->inherits[e];
     add_ref(frame.context.prog);
     frame.current_storage=o->storage+frame.context.storage_offset;
 
-    for(d=0;d<(int)frame.context.prog->num_identifiers;d++)
+    for(q=0;q<(int)frame.context.prog->num_variable_index;q++)
     {
-      if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].identifier_flags))
-	continue;
-      
+      int d=frame.context.prog->variable_index[q];
       if(frame.context.prog->identifiers[d].run_time_type == T_MIXED)
       {
 	struct svalue *s;
@@ -162,6 +160,23 @@ struct object *parent_clone_object(struct program *p,
   return o;
 }
 
+static struct pike_string *low_read_file(char *file)
+{
+  struct pike_string *s;
+  INT32 len;
+  FILE *f=fopen(file,"r");
+  if(f)
+  {
+    fseek(f,0,SEEK_END);
+    len=ftell(f);
+    fseek(f,0,SEEK_SET);
+    s=begin_shared_string(len);
+    fread(s->str,1,len,f);
+    fclose(f);
+    return end_shared_string(s);
+  }
+  return 0;
+}
 
 struct object *get_master(void)
 {
@@ -184,24 +199,43 @@ struct object *get_master(void)
 
   if(!master_program)
   {
-    INT32 len;
-    struct pike_string *s;
+    extern struct timeval TM;
+    struct pike_string *s,*s2;
+    char *tmp=xalloc(strlen(master_file)+3);
+    MEMCPY(tmp, master_file, strlen(master_file)+1);
+    strcat(tmp,".o");
+    s=low_read_file(tmp);
+    free(tmp);
+    if(s)
+    {
+      JMP_BUF tmp;
+      if(SETJMP(tmp))
+      {
+	/* do nothing */
+	UNSETJMP(tmp);
+      }else{
+	extern f_decode_value(INT32);
+
+	push_string(s);
+	push_int(0);
+	f_decode_value(2);
 
+	if(sp[-1].type == T_PROGRAM)
+	  goto compiled;
 
-    FILE *f=fopen(master_file,"r");
-    if(f)
+	pop_stack();
+	  
+      }
+    }
+    s2=low_read_file(master_file);
+    if(s2)
     {
-      fseek(f,0,SEEK_END);
-      len=ftell(f);
-      fseek(f,0,SEEK_SET);
-      s=begin_shared_string(len);
-      fread(s->str,1,len,f);
-      fclose(f);
-      push_string(end_shared_string(s));
+      push_string(s2);
       push_text(master_file);
       f_cpp(2);
       f_compile(1);
-      
+
+    compiled:
       if(sp[-1].type != T_PROGRAM)
       {
 	pop_stack();
@@ -284,7 +318,7 @@ void destruct(struct object *o)
   /* free globals and call C de-initializers */
   for(e=p->num_inherits-1; e>=0; e--)
   {
-    int d;
+    int q;
 
     frame.context=p->inherits[e];
     add_ref(frame.context.prog);
@@ -293,10 +327,9 @@ void destruct(struct object *o)
     if(frame.context.prog->exit)
       frame.context.prog->exit(o);
 
-    for(d=0;d<(int)frame.context.prog->num_identifiers;d++)
+    for(q=0;q<(int)frame.context.prog->num_variable_index;q++)
     {
-      if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].identifier_flags)) 
-	continue;
+      int d=frame.context.prog->variable_index[q];
       
       if(frame.context.prog->identifiers[d].run_time_type == T_MIXED)
       {
@@ -931,7 +964,7 @@ void gc_mark_object_as_referenced(struct object *o)
 
     for(e=p->num_inherits-1; e>=0; e--)
     {
-      int d;
+      int q;
       
       frame.context=p->inherits[e];
       add_ref(frame.context.prog);
@@ -940,10 +973,9 @@ void gc_mark_object_as_referenced(struct object *o)
       if(frame.context.prog->gc_marked)
 	frame.context.prog->gc_marked(o);
 
-      for(d=0;d<(int)frame.context.prog->num_identifiers;d++)
+      for(q=0;q<(int)frame.context.prog->num_variable_index;q++)
       {
-	if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].identifier_flags)) 
-	  continue;
+	int d=frame.context.prog->variable_index[q];
 	
 	if(frame.context.prog->identifiers[d].run_time_type == T_MIXED)
 	{
@@ -996,7 +1028,7 @@ void gc_check_all_objects(void)
       
       for(e=p->num_inherits-1; e>=0; e--)
       {
-	int d;
+	int q;
 	
 	frame.context=p->inherits[e];
 	add_ref(frame.context.prog);
@@ -1004,11 +1036,10 @@ void gc_check_all_objects(void)
 	
 	if(frame.context.prog->gc_check)
 	  frame.context.prog->gc_check(o);
-	
-	for(d=0;d<(int)frame.context.prog->num_identifiers;d++)
+
+	for(q=0;q<(int)frame.context.prog->num_variable_index;q++)
 	{
-	  if(!IDENTIFIER_IS_VARIABLE(frame.context.prog->identifiers[d].identifier_flags)) 
-	    continue;
+	  int d=frame.context.prog->variable_index[q];
 	  
 	  if(frame.context.prog->identifiers[d].run_time_type == T_MIXED)
 	  {
diff --git a/src/object.h b/src/object.h
index e9ab0ccce1303a4ba3d9900df9823a8f2e474e28..e21c0ee3938ee0f933b816a27beea8cbac693950 100644
--- a/src/object.h
+++ b/src/object.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: object.h,v 1.18 1998/04/20 18:53:20 grubba Exp $
+ * $Id: object.h,v 1.19 1998/04/24 00:32:09 hubbe Exp $
  */
 #ifndef OBJECT_H
 #define OBJECT_H
@@ -42,8 +42,9 @@ extern struct program *master_program;
 #define this_object() (add_ref(fp->current_object), fp->current_object)
 
 /* Prototypes begin here */
-void setup_fake_object(void);
 struct object *low_clone(struct program *p);
+void call_c_initializers(struct object *o);
+void do_free_object(struct object *o);
 struct object *debug_clone_object(struct program *p, int args);
 struct object *parent_clone_object(struct program *p,
 				   struct object *parent,
diff --git a/src/program.c b/src/program.c
index 12f6a75cd128b742540ba077efc1b99884d8697d..94251ef89f7dfb910bd64be567381201f70651e9 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: program.c,v 1.86 1998/04/19 03:14:15 per Exp $");
+RCSID("$Id: program.c,v 1.87 1998/04/24 00:32:09 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -26,6 +26,8 @@ RCSID("$Id: program.c,v 1.86 1998/04/19 03:14:15 per Exp $");
 #include "operators.h"
 #include "builtin_functions.h"
 #include "stuff.h"
+#include "mapping.h"
+#include "cyclic.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -105,6 +107,9 @@ static INT32 last_line = 0;
 static INT32 last_pc = 0;
 static struct pike_string *last_file = 0;
 dynamic_buffer used_modules;
+INT32 num_used_modules;
+static struct mapping *resolve_cache=0;
+static struct mapping *module_index_cache=0;
 
 /* So what if we don't have templates? / Hubbe */
 
@@ -174,25 +179,60 @@ void use_module(struct svalue *s)
 {
   if( (1<<s->type) & (BIT_MAPPING | BIT_OBJECT))
   {
+    num_used_modules++;
     assign_svalue_no_free((struct svalue *)
 			  low_make_buf_space(sizeof(struct svalue),
 					     &used_modules), s);
+    if(module_index_cache)
+    {
+      free_mapping(module_index_cache);
+      module_index_cache=0;
+    }
   }else{
     yyerror("Module is neither mapping nor object");
   }
 }
 
-
+void unuse_modules(INT32 howmany)
+{
+  if(!howmany) return;
+#ifdef DEBUG
+  if(howmany *sizeof(struct svalue) > used_modules.s.len)
+    fatal("Unusing too many modules.\n");
+#endif
+  num_used_modules-=howmany;
+  low_make_buf_space(-sizeof(struct svalue)*howmany, &used_modules);
+  free_svalues((struct svalue *)low_make_buf_space(0, &used_modules),
+	       howmany,
+	       BIT_MAPPING | BIT_OBJECT);
+  if(module_index_cache)
+  {
+    free_mapping(module_index_cache);
+    module_index_cache=0;
+  }
+}
 
 int low_find_shared_string_identifier(struct pike_string *name,
 				      struct program *prog);
 
 
 
-struct node_s *find_module_identifier(struct pike_string *ident)
+static struct node_s *index_modules(struct pike_string *ident)
 {
+  struct node_s *ret;
   JMP_BUF tmp;
-  node *ret;
+
+  if(module_index_cache)
+  {
+    struct svalue *tmp=low_mapping_string_lookup(module_index_cache,ident);
+    if(tmp)
+    {
+      if(!(IS_ZERO(tmp) && tmp->subtype==1))
+	return mksvaluenode(tmp);
+      return 0;
+    }
+  }
+
 
   if(SETJMP(tmp))
   {
@@ -215,8 +255,10 @@ struct node_s *find_module_identifier(struct pike_string *ident)
       
       if(!IS_UNDEFINED(sp-1))
       {
-/*	fprintf(stderr,"MOD: %s, %d %d\n",ident->str, current_line, sp[-1].type); */
 	UNSETJMP(tmp);
+	if(!module_index_cache)
+	  module_index_cache=allocate_mapping(10);
+	mapping_string_insert(module_index_cache, ident, sp-1);
 	ret=mksvaluenode(sp-1);
 	pop_stack();
 	return ret;
@@ -226,6 +268,16 @@ struct node_s *find_module_identifier(struct pike_string *ident)
   }
   UNSETJMP(tmp);
 
+  return 0;
+}
+
+struct node_s *find_module_identifier(struct pike_string *ident)
+{
+  struct node_s *ret;
+
+  if((ret=index_modules(ident))) return ret;
+
+     
   {
     struct program_state *p=previous_program_state;
     int n;
@@ -236,23 +288,61 @@ struct node_s *find_module_identifier(struct pike_string *ident)
       {
 	struct identifier *id;
 	id=ID_FROM_INT(p->new_program, i);
-#if 0
-	if(IDENTIFIER_IS_CONSTANT(id->identifier_flags))
+	return mkexternalnode(n, i, id);
+      }
+    }
+  }
+
+
+  if(resolve_cache)
+  {
+    struct svalue *tmp=low_mapping_string_lookup(resolve_cache,ident);
+    if(tmp)
+    {
+      if(!(IS_ZERO(tmp) && tmp->subtype==1))
+	return mkconstantsvaluenode(tmp);
+
+      return 0;
+    }
+  }
+
+  if(!num_parse_error && get_master())
+  {	
+    DECLARE_CYCLIC();
+    node *ret=0;
+    if(BEGIN_CYCLIC(ident, lex.current_file))
+    {
+      my_yyerror("Recursive module dependency in %s.",
+		 ident->str);
+    }else{
+      SET_CYCLIC_RET(1);
+
+      ref_push_string(ident);
+      ref_push_string(lex.current_file);
+      SAFE_APPLY_MASTER("resolv", 2);
+
+      if(throw_value.type == T_STRING)
+      {
+	if(compiler_pass==2)
+	  my_yyerror("%s",throw_value.u.string->str);
+      }
+      else
+      {
+	if(!resolve_cache)
+	  resolve_cache=allocate_mapping(10);
+	mapping_string_insert(resolve_cache,ident,sp-1);
+	
+	if(!(IS_ZERO(sp-1) && sp[-1].subtype==1))
 	{
-	  struct svalue *s=PROG_FROM_INT(p->new_program, i)->constants+
-			   id->func.offset;
-	  if(s->type != T_PROGRAM)
-	  {
-	    ret=mksvaluenode(s);
-	    return ret;
-	  }
+	  ret=mkconstantsvaluenode(sp-1);
 	}
-#endif
-
-	return mkexternalnode(n, i, id);
       }
+      pop_stack();
+      END_CYCLIC();
     }
+    if(ret) return ret;
   }
+  
   return 0;
 }
 
@@ -336,7 +426,7 @@ void optimize_program(struct program *p)
 }
 
 /* internal function to make the index-table */
-static int funcmp(const void *a,const void *b)
+int program_function_index_compare(const void *a,const void *b)
 {
   return
     my_order_strcmp(ID_FROM_INT(new_program, *(unsigned short *)a)->name,
@@ -383,7 +473,7 @@ void fixate_program(void)
   }
   fsort((void *)new_program->identifier_index,
 	new_program->num_identifier_index,
-	sizeof(unsigned short),(fsortfun)funcmp);
+	sizeof(unsigned short),(fsortfun)program_function_index_compare);
   
   
   for(i=0;i<NUM_LFUNS;i++)
@@ -392,6 +482,22 @@ void fixate_program(void)
   new_program->flags |= PROGRAM_FIXED;
 }
 
+struct program *low_allocate_program(void)
+{
+  struct program *p;
+  p=ALLOC_STRUCT(program);
+  MEMSET(p, 0, sizeof(struct program));
+  
+  GC_ALLOC();
+  p->refs=1;
+  p->id=++current_program_id;
+  
+  if((p->next=first_program)) first_program->prev=p;
+  first_program=p;
+  GETTIMEOFDAY(& p->timestamp);
+  return p;
+}
+
 /*
  * Start building a new program
  */
@@ -408,14 +514,7 @@ void low_start_new_program(struct program *p,
 
   if(!p)
   {
-    p=ALLOC_STRUCT(program);
-    MEMSET(p, 0, sizeof(struct program));
-    
-    p->refs=1;
-    p->id=++current_program_id;
-    
-    if((p->next=first_program)) first_program->prev=p;
-    first_program=p;
+    p=low_allocate_program();
   }else{
     add_ref(p);
   }
@@ -431,9 +530,9 @@ void low_start_new_program(struct program *p,
 #define PUSH
 #include "compilation.h"
 
+  num_used_modules=0;
   init_type_stack();
 
-  low_reinit_buf(& used_modules);
 
   if(p && (p->flags & PROGRAM_FINISHED))
   {
@@ -494,20 +593,13 @@ void low_start_new_program(struct program *p,
     add_to_inherits(i);
   }
 
-  {
-    struct svalue tmp;
-    tmp.type=T_MAPPING;
-#ifdef __CHECKER__
-    tmp.subtype=0;
-#endif /* __CHECKER__ */
-    tmp.u.mapping=get_builtin_constants();
-    use_module(& tmp);
-  }
 
   init_node=0;
   num_parse_error=0;
 
   push_compiler_frame();
+  if(lex.current_file)
+    store_linenumber(lex.current_line, lex.current_file);
 }
 
 void start_new_program(void)
@@ -524,52 +616,61 @@ void really_free_program(struct program *p)
   if(id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]==p)
     id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]=0;
 
-  for(e=0; e<p->num_strings; e++)
-    free_string(p->strings[e]);
+  if(p->strings)
+    for(e=0; e<p->num_strings; e++)
+      if(p->strings[e])
+	free_string(p->strings[e]);
 
-  for(e=0; e<p->num_identifiers; e++)
+  if(p->identifiers)
   {
-    free_string(p->identifiers[e].name);
-    free_string(p->identifiers[e].type);
+    for(e=0; e<p->num_identifiers; e++)
+    {
+      if(p->identifiers[e].name)
+	free_string(p->identifiers[e].name);
+      if(p->identifiers[e].type)
+	free_string(p->identifiers[e].type);
+    }
   }
 
-  for(e=0; e<p->num_constants; e++)
-    free_svalue(p->constants+e);
+  if(p->constants)
+    free_svalues(p->constants, p->num_constants, BIT_MIXED);
 
-  for(e=0; e<p->num_inherits; e++)
-  {
-    if(p->inherits[e].name)
-      free_string(p->inherits[e].name);
-    if(e)
+  if(p->inherits)
+    for(e=0; e<p->num_inherits; e++)
     {
-      free_program(p->inherits[e].prog);
+      if(p->inherits[e].name)
+	free_string(p->inherits[e].name);
+      if(e)
+      {
+	if(p->inherits[e].prog)
+	  free_program(p->inherits[e].prog);
+      }
+      if(p->inherits[e].parent)
+	free_object(p->inherits[e].parent);
     }
-    if(p->inherits[e].parent)
-      free_object(p->inherits[e].parent);
-  }
 
   if(p->prev)
     p->prev->next=p->next;
   else
     first_program=p->next;
-
+  
   if(p->next)
     p->next->prev=p->prev;
-
+  
   if(p->flags & PROGRAM_OPTIMIZED)
-    {
-      if(p->program)
-	  free(p->program);
+  {
+    if(p->program)
+      free(p->program);
 #define FOO(NUMTYPE,TYPE,NAME) p->NAME=0;
 #include "program_areas.h"
-    }else{
+  }else{
 #define FOO(NUMTYPE,TYPE,NAME) \
-  if(p->NAME) { free((char *)p->NAME); p->NAME=0; }
+    if(p->NAME) { free((char *)p->NAME); p->NAME=0; }
 #include "program_areas.h"
-    }
-
+  }
+  
   free((char *)p);
-
+  
   GC_FREE();
 }
 
@@ -625,6 +726,12 @@ static void toss_compilation_resources(void)
       free((char *)malloc_size_program);
       malloc_size_program=0;
     }
+
+  if(module_index_cache)
+  {
+    free_mapping(module_index_cache);
+    module_index_cache=0;
+  }
   
   while(compiler_frame)
     pop_compiler_frame();
@@ -634,17 +741,8 @@ static void toss_compilation_resources(void)
     free_string(last_file);
     last_file=0;
   }
-  
-  {
-    struct svalue *modules=(struct svalue *)used_modules.s.str;
-    INT32 e;
 
-    for(e=0;e<(long)(used_modules.s.len / sizeof(struct svalue));e++)
-      free_svalue(modules+e);
-
-    toss_buffer(&used_modules);
-  }
-  
+  unuse_modules(num_used_modules);
 }
 
 int sizeof_variable(int run_time_type)
@@ -836,20 +934,25 @@ struct program *end_first_pass(int finish)
       new_program->flags |= PROGRAM_FINISHED;
     }
 
-    GC_ALLOC();
   }
   toss_compilation_resources();
 
 #define POP
 #include "compilation.h"
 
+
   compilation_depth--;
-  threads_disabled--;
-  co_signal(&threads_disabled_change);
+  if(!--threads_disabled)
+    co_signal(&threads_disabled_change);
 
   /* fprintf(stderr, "end_first_pass(): compilation_depth:%d\n", compilation_depth); */
 
   free_all_nodes();
+  if(!compiler_frame && compiler_pass==2 && resolve_cache)
+  {
+    free_mapping(resolve_cache);
+    resolve_cache=0;
+  }
   return prog;
 }
 
@@ -1308,12 +1411,14 @@ int low_define_variable(struct pike_string *name,
   ref.id_flags=flags;
   ref.identifier_offset=new_program->num_identifiers;
   ref.inherit_offset=0;
+
+  add_to_variable_index(ref.identifier_offset);
   
   add_to_identifiers(dummy);
   
   n=new_program->num_identifier_references;
   add_to_identifier_references(ref);
-  
+
   return n;
 }
 
@@ -1676,6 +1781,8 @@ INT32 define_function(struct pike_string *name,
 	fun.run_time_type=T_FUNCTION;
 	
 	fun.identifier_flags=function_flags;
+	if(function_flags & IDENTIFIER_C_FUNCTION)
+	  new_program->flags |= PROGRAM_HAS_C_METHODS;
 	
 	if(func)
 	  fun.func = *func;
@@ -1704,6 +1811,8 @@ INT32 define_function(struct pike_string *name,
   copy_shared_string(fun.type, type);
   
   fun.identifier_flags=function_flags;
+  if(function_flags & IDENTIFIER_C_FUNCTION)
+    new_program->flags |= PROGRAM_HAS_C_METHODS;
   
   fun.run_time_type=T_FUNCTION;
   
@@ -2019,6 +2128,8 @@ struct program *compile(struct pike_string *prog)
   struct lex save_lex;
   int save_depth=compilation_depth;
   int saved_threads_disabled = threads_disabled;
+  dynamic_buffer used_modules_save = used_modules;
+  INT32 num_used_modules_save = num_used_modules;
   void yyparse(void);
 
 #ifdef DEBUG
@@ -2026,6 +2137,18 @@ struct program *compile(struct pike_string *prog)
     fatal("Compiler exited with longjump!\n");
 #endif
 
+  num_used_modules=0;
+  initialize_buf(&used_modules);
+  {
+    struct svalue tmp;
+    tmp.type=T_MAPPING;
+#ifdef __CHECKER__
+    tmp.subtype=0;
+#endif /* __CHECKER__ */
+    tmp.u.mapping=get_builtin_constants();
+    use_module(& tmp);
+  }
+
   save_lex=lex;
 
   lex.end=prog->str+prog->len;
@@ -2064,12 +2187,22 @@ struct program *compile(struct pike_string *prog)
 #endif /* DEBUG */
   threads_disabled = saved_threads_disabled;
   /* fprintf(stderr, "compile() Leave: threads_disabled:%d, compilation_depth:%d\n", threads_disabled, compilation_depth); */
-  co_signal(&threads_disabled_change);
+  if(!threads_disabled)
+    co_signal(&threads_disabled_change);
 
   free_string(lex.current_file);
   lex=save_lex;
 
+  unuse_modules(1);
+#ifdef DEBUG
+  if(num_used_modules)
+    fatal("Failed to pop modules properly.\n");
+#endif
+
+  toss_buffer(&used_modules);
   compilation_depth=save_depth;
+  used_modules = used_modules_save;
+  num_used_modules = num_used_modules_save ;
 
 #ifdef DEBUG
   UNSETJMP(tmp);
@@ -2149,7 +2282,11 @@ void cleanup_program(void)
     }
   }
 #endif
-
+  if(resolve_cache)
+  {
+    free_mapping(resolve_cache);
+    resolve_cache=0;
+  }
 }
 
 #ifdef GC2
@@ -2508,3 +2645,42 @@ int implements(struct program *a, struct program *b)
   implements_cache[hval].ret=low_implements(a,b);
   return implements_cache[hval].ret;
 }
+
+#if 0
+void f_encode_program(INT32 args)
+{
+  check_stack(20);
+  f_version();
+  push_int(p->flags);
+  push_int(p->storage_needed);
+  if(p->init || p->exit || p->gc_marked || p->gc_check)
+    error("Cannot encode C programs.\n");
+  push_int(total_size);
+  push_string(make_shared_binary_string(p->program, p->num_program));
+  push_string(make_shared_binary_string(p->linenumbers, p->num_linenumbers));
+  push_string(make_shared_binary_string((char *)p->identifier_index, p->num_identifier_index * sizeof(unsigned short*)));
+  push_string(make_shared_binary_string((char *)p->variable_index, p->num_variable_index * sizeof(unsigned short*)));
+  push_string(make_shared_binary_string((char *)p->identifier_references, p->num_identifier_references * sizeof(struct reference)));
+  check_stack(p->num_strings);
+  for(e=0;e<p->num_strings;e++) ref_push_string(p->strings[e]);
+  f_aggregate(p->num_strings);
+
+  check_stack(p->num_inherits * 2);
+  for(e=1;e<p->num_strings;e++)
+  {
+    ref_push_string(p->inherits[e].name);
+  }
+
+  f_aggregate(p->num_inherits);
+  
+  check_stack(NUM_LFUNS);
+  for(e=0;e<NUM_LFUNS;e++) push_int(p->lfuns[e]);
+  
+  UNSET_ONERROR(tmp);
+
+  free_mapping(data->encoded);
+  pop_n_elems(args);
+  push_string(low_free_buf(&data->buf));
+}
+
+#endif
diff --git a/src/program.h b/src/program.h
index b28c2c61cd900b259732851160e39ff57fe43481..ca7afc91d5c8e7b1b387bbad2de39f66d57ecd7c 100644
--- a/src/program.h
+++ b/src/program.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: program.h,v 1.40 1998/04/14 22:10:50 hubbe Exp $
+ * $Id: program.h,v 1.41 1998/04/24 00:32:09 hubbe Exp $
  */
 #ifndef PROGRAM_H
 #define PROGRAM_H
@@ -14,6 +14,7 @@
 #include "global.h"
 #include "pike_types.h"
 #include "svalue.h"
+#include "time_stuff.h"
 
 #define LFUN___INIT 0
 #define LFUN_CREATE 1
@@ -180,12 +181,15 @@ struct inherit
 /* Program will be destructed as soon at it runs out of references. */
 #define PROGRAM_DESTRUCT_IMMEDIATE 16
 
+#define PROGRAM_HAS_C_METHODS 32
+
 struct program
 {
   INT32 refs;
   INT32 id;             /* used to identify program in caches */
   INT32 flags;
   INT32 storage_needed; /* storage needed in the object struct */
+  struct timeval timestamp;
 
   struct program *next;
   struct program *prev;
@@ -230,6 +234,7 @@ extern struct program *first_program;
 extern int compiler_pass;
 extern long local_class_counter;
 extern int catch_level;
+extern INT32 num_used_modules;
 
 #define COMPILER_IN_CATCH 1
 
@@ -240,11 +245,14 @@ extern int catch_level;
 void ins_int(INT32 i, void (*func)(char tmp));
 void ins_short(INT16 i, void (*func)(char tmp));
 void use_module(struct svalue *s);
+void unuse_modules(INT32 howmany);
 struct node_s *find_module_identifier(struct pike_string *ident);
 struct program *parent_compilation(int level);
 struct program *id_to_program(INT32 id);
 void optimize_program(struct program *p);
+int program_function_index_compare(const void *a,const void *b);
 void fixate_program(void);
+struct program *low_allocate_program(void);
 void low_start_new_program(struct program *p,
 			   struct pike_string *name,
 			   int flags);
@@ -362,6 +370,7 @@ int find_child(struct program *parent, struct program *child);
 void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2)));
 struct implements_cache_s;
 int implements(struct program *a, struct program *b);
+void f_encode_program(INT32 args);
 /* Prototypes end here */
 
 
diff --git a/src/program_areas.h b/src/program_areas.h
index e10c5dfafc16783d8e00e76addf1aa1c17bba4da..0cb01707e9d4ea512e88f88f4205df7a5987fb65 100644
--- a/src/program_areas.h
+++ b/src/program_areas.h
@@ -1,15 +1,15 @@
-/* $Id: program_areas.h,v 1.4 1998/04/08 01:00:58 hubbe Exp $ */
+/* $Id: program_areas.h,v 1.5 1998/04/24 00:32:10 hubbe Exp $ */
 /* Who needs templates anyway? / Hubbe */
 
 /* Program *must* be first! */
 FOO(SIZE_T,unsigned char,program)
 FOO(SIZE_T,char,linenumbers)
 FOO(unsigned INT16,unsigned INT16,identifier_index)
+FOO(unsigned INT16,unsigned INT16,variable_index)
 FOO(unsigned INT16,struct reference,identifier_references)
 FOO(unsigned INT16,struct pike_string *,strings)
 FOO(unsigned INT16,struct inherit,inherits)
 FOO(unsigned INT16,struct identifier,identifiers)
 FOO(unsigned INT16,struct svalue, constants)
-
 #undef FOO