diff --git a/lib/master.pike b/lib/master.pike
index 25f788cb2d8ab67e4451707c3244c28f0a6c5139..4fad02869ba3abdbad4ddff08fbdb60a2e59194a 100644
--- a/lib/master.pike
+++ b/lib/master.pike
@@ -259,14 +259,13 @@ class dirnode
   void create(string name) { dirname=name; }
   object|program `[](string index)
   {
-    object m=((object)"/master");
-    if(mixed o=m->findmodule(dirname+"/module"))
+    if(mixed o=findmodule(dirname+"/module"))
     {
       if(mixed tmp=o->_module_value) o=tmp;
       if(o=o[index]) return o;
     }
     index = dirname+"/"+index;
-    if(object o=((object)"/master")->findmodule(index))
+    if(object o=findmodule(index))
     {
       if(mixed tmp=o->_module_value) o=tmp;
       return o;
diff --git a/lib/modules/Stack.pmod b/lib/modules/Stack.pmod
deleted file mode 100644
index aeb471a65bd4bac88873886bf35e1ebb028ee1bb..0000000000000000000000000000000000000000
--- a/lib/modules/Stack.pmod
+++ /dev/null
@@ -1,47 +0,0 @@
-#define error(X) throw( ({ (X), backtrace()[0..sizeof(backtrace())-2] }) )
-
-class stack {
-  int ptr;
-  mixed *arr=allocate(32);
-
-  void push(mixed val)
-  {
-    if(ptr==sizeof(arr)) arr+=allocate(ptr);
-    arr[ptr++]=val;
-  }
-
-  mixed pop(void|int val)
-  {
-    mixed foo;
-
-    if (val) {
-      if (ptr <= 0) {
-	error("Stack underflow\n");
-      }
-
-      if (ptr < val) {
-        val = ptr;
-      }
-      ptr -= val;
-      foo = arr[ptr..ptr + val - 1];
- 
-      for (int i=0; i < val; i++) {
-        arr[ptr + i] = 0;       /* Don't waste references */
-      }
-    } else {
-      if(--ptr < 0)
-	error("Stack underflow\n");
-    
-      foo=arr[ptr];
-      arr[ptr]=0; /* Don't waste references */
-    }
-    return foo;
-  }
-
-  void reset()
-  {
-    arr=allocate(32);
-    ptr=0;
-  }
-};
-
diff --git a/src/ChangeLog b/src/ChangeLog
index 702df0c80c53300850c2d047607fb0a96528c864..fb63905809151712c2e548ba1204b8fc5eaa4e64 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+Thu Jun 26 20:45:53 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
+
+	* objects can now access variables in their parents
+
 Wed Jun 25 15:33:23 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
 
 	* Compiler is now two-pass -> no more prototypes
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 2b0ce84c7cf4e2e4637430a7e4c4cf8d69ebd46f..3e5dc1ccc3ed1397082f4375449c4cb72f89fbbd 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.36.2.1 1997/06/25 22:46:35 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.36.2.2 1997/06/27 06:55:13 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -281,28 +281,6 @@ void f_call_function(INT32 args)
   }
 }
 
-void f_parent(INT32 args)
-{
-  struct object *o;
-  if(!args)
-  {
-    o=fp->current_object;
-  }else{
-    if(sp[-args].type!=T_OBJECT)
-      error("Bad argument 1 to parent()\n");
-    o=sp[-args].u.object;
-  }
-  o->refs++;
-  pop_n_elems(args);
-  if(o->parent)
-  {
-    ref_push_object(o->parent);
-  }else{
-    push_int(0);
-  }
-  free_object(o);
-}
-
 void f_backtrace(INT32 args)
 {
   INT32 frames;
@@ -858,16 +836,14 @@ void f_object_program(INT32 args)
     {
       if(o->parent && o->parent->prog)
       {
-	INT32 i=find_child(o->parent->prog, p);
-	if(i!=-1)
-	{
-	  o->refs++;
-	  pop_n_elems(args);
-	  push_object(o->parent);
-	  sp[-1].subtype=i;
-	  sp[-1].type=T_FUNCTION;
-	  return;
-	}
+	INT32 id=o->parent_identifier;
+	o=o->parent;
+	o->refs++;
+	pop_n_elems(args);
+	push_object(o);
+	sp[-1].subtype=id;
+	sp[-1].type=T_FUNCTION;
+	return;
       }else{
 	p->refs++;
 	pop_n_elems(args);
@@ -1804,6 +1780,5 @@ void init_builtin_efuns()
 
   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("parent", f_parent, "function(object|void:object)", OPT_EXTERNAL_DEPEND);
 }
 
diff --git a/src/builtin_functions.h b/src/builtin_functions.h
index 83f9da886633eeb9e5a34dab0b1fada9e5f2d7d5..704a49da59dbc661ea40aee6647b43df29135f6b 100644
--- a/src/builtin_functions.h
+++ b/src/builtin_functions.h
@@ -26,7 +26,6 @@ void f_search(INT32 args);
 void f_call_function(INT32 args);
 void f_backtrace(INT32 args);
 void f_add_constant(INT32 args);
-void f_compile_file(INT32 args);
 void f_combine_path(INT32 args);
 void f_function_object(INT32 args);
 void f_function_name(INT32 args);
@@ -40,7 +39,6 @@ struct callback *add_exit_callback(callback_func call,
 				   void *arg,
 				   callback_func free_func);
 void f_exit(INT32 args);
-void f_query_host_name(INT32 args);
 void f_time(INT32 args);
 void f_crypt(INT32 args);
 void f_destruct(INT32 args);
@@ -51,7 +49,7 @@ void f_object_program(INT32 args);
 void f_reverse(INT32 args);
 struct tupel;
 void f_replace(INT32 args);
-void f_compile_string(INT32 args);
+void f_compile(INT32 args);
 void f_mkmapping(INT32 args);
 void f_objectp(INT32 args);
 void f_functionp(INT32 args);
@@ -63,6 +61,7 @@ TYPEP(f_arrayp, "arrayp", T_ARRAY)
 TYPEP(f_multisetp, "multisetp", T_MULTISET)
 TYPEP(f_stringp, "stringp", T_STRING)
 TYPEP(f_floatp, "floatp", T_FLOAT)
+void f_programp(INT32 args);
 void f_sort(INT32 args);
 void f_rows(INT32 args);
 void f_column(INT32 args);
@@ -70,9 +69,15 @@ void f__verify_internals(INT32 args);
 void f_localtime(INT32 args);
 void f_glob(INT32 args);
 struct callback *add_memory_usage_callback(callback_func call,
-					   void *arg,
-					   callback_func free_func);
+					  void *arg,
+					  callback_func free_func);
 void f__memory_usage(INT32 args);
+void f__next(INT32 args);
+void f__prev(INT32 args);
+void f__refs(INT32 args);
+void f_replace_master(INT32 args);
+void f_gethrvtime(INT32 args);
+void f_gethrtime(INT32 args);
 void init_builtin_efuns();
 /* Prototypes end here */
 
diff --git a/src/cpp.h b/src/cpp.h
new file mode 100644
index 0000000000000000000000000000000000000000..7fcca20dba76c173454268a89c4a662378305247
--- /dev/null
+++ b/src/cpp.h
@@ -0,0 +1,26 @@
+#ifndef CPP_H
+#define CPP_H
+
+#ifndef STRUCT_HASH_ENTRY_DECLARED
+struct hash_entry;
+#define STRUCT_HASH_ENTRY_DECLARED
+#endif
+
+/* Prototypes begin here */
+struct pike_predef_s;
+struct define_part;
+struct define_argument;
+struct define;
+struct cpp;
+void cpp_error(struct cpp *this,char *err);
+void PUSH_STRING(char *str,
+		 INT32 len,
+		 dynamic_buffer *buf);
+void free_one_define(struct hash_entry *h);
+void f_cpp(INT32 args);
+void init_cpp();
+void add_predefine(char *s);
+void exit_cpp();
+/* Prototypes end here */
+
+#endif
diff --git a/src/docode.c b/src/docode.c
index 2d1d1b35243574d36b4866834cb5f8074e808ccc..80d8baa7ba0b0586774dd0cac27efc28307802e9 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.16.2.1 1997/06/25 22:46:36 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.16.2.2 1997/06/27 06:55:15 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -255,12 +255,25 @@ static int do_docode2(node *n,int flags)
     case F_INDEX:
     case F_ARROW:
     case F_ARG_LIST:
+    case F_EXTERNAL:
       break;
     }
   }
 
   switch(n->token)
   {
+  case F_EXTERNAL:
+    emit(F_LDA, n->u.integer.a);
+    if(flags & DO_LVALUE)
+    {
+      emit(F_EXTERNAL_LVALUE, n->u.integer.b);
+      return 2;
+    }else{
+      emit(F_EXTERNAL, n->u.integer.b);
+      return 1;
+    }
+    break;
+
   case F_UNDEFINED:
     yyerror("Undefined identifier");
     emit(F_NUMBER,0);
@@ -693,14 +706,15 @@ static int do_docode2(node *n,int flags)
 
       tmp=findstring("call_function");
       if(!tmp) yyerror("No call_function efun.");
-      if(!find_module_identifier(tmp))
+      foo=find_module_identifier(tmp);
+      if(!foo || !foo->token==F_CONSTANT)
       {
 	yyerror("No call_function efun.");
       }else{
-	tmp1=store_constant(sp-1, 1);
-	pop_stack();
+	tmp1=store_constant(& foo->u.sval, 1);
 	emit(F_APPLY, tmp1);
       }
+      free_node(foo);
       return 1;
     }
 
diff --git a/src/error.c b/src/error.c
index 1e0c968a681d2299b2465275befcec171dd18211..c029503f7d6c040f673d0acb80eadc5335947ec5 100644
--- a/src/error.c
+++ b/src/error.c
@@ -46,6 +46,7 @@ void throw() ATTRIBUTE((noreturn))
 #endif
     free_object(fp->current_object);
     free_program(fp->context.prog);
+    if(fp->context.parent) free_object(fp->context.parent);
     
     fp = fp->parent_frame;
   }
diff --git a/src/gc.c b/src/gc.c
index a3d1f008beb46c7849bceb88b46fa92d0a97e391..80f8fd6f4297a3340447c9e8a6ae98d75cdef8e5 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -108,7 +108,7 @@ static struct marker *getmark(void *a)
 }
 
 #ifdef DEBUG
-static void *check_for =0;
+void *gc_check_for =0;
 
 static void gdb_gc_stop_here(void *a)
 {
@@ -119,13 +119,14 @@ static void gdb_gc_stop_here(void *a)
 INT32 gc_check(void *a)
 {
 #ifdef DEBUG
-  if(check_for)
+  if(gc_check_for)
   {
-    if(check_for == a)
+    if(gc_check_for == a)
     {
       gdb_gc_stop_here(a);
+      return -2;
     }
-    return 0;
+    return -1;
   }
 #endif
   return getmark(a)->refs++;
@@ -138,16 +139,24 @@ int gc_is_referenced(void *a)
 #ifdef DEBUG
   if(m->refs > *(INT32 *)a)
   {
-    check_for=a;
+    gc_check_for=a;
+
+    fprintf(stderr,"Too many ref counts found %d > %d (%lx)\n",m->refs, *(INT32 *)a, (long)a);
 
+    fprintf(stderr,"Checking arrays\n");
     gc_check_all_arrays();
+    fprintf(stderr,"Checking multisets\n");
     gc_check_all_multisets();
+    fprintf(stderr,"Checking mappings\n");
     gc_check_all_mappings();
+    fprintf(stderr,"Checking programs\n");
     gc_check_all_programs();
+    fprintf(stderr,"Checking objects\n");
     gc_check_all_objects();
+    fprintf(stderr,"Checking callbacks\n");
     call_callback(& gc_callbacks, (void *)0);
 
-    check_for=0;
+    gc_check_for=0;
     fatal("Ref counts are totally wrong!!!\n");
   }
 #endif
diff --git a/src/interpret.c b/src/interpret.c
index 28b4730238625e7b8cfc6840f7e4d4c9361a7315..9830859669bb059242ee55ad7ced19c623c6a7f4 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.42.2.1 1997/06/25 22:46:37 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.42.2.2 1997/06/27 06:55:16 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -479,7 +479,7 @@ static int o_catch(unsigned char *pc);
 
 static void eval_instruction(unsigned char *pc)
 {
-  unsigned INT32 instr, prefix=0;
+  unsigned INT32 accumulator=0, instr, prefix=0;
   while(1)
   {
     fp->pc = pc;
@@ -560,6 +560,9 @@ static void eval_instruction(unsigned char *pc)
       CASE(F_PREFIX_CHARX256);
       prefix+=EXTRACT_UCHAR(pc++)<<8;
       break;
+
+      CASE(F_LDA); accumulator=GET_ARG(); break;
+
       /* Push number */
       CASE(F_CONST0); push_int(0); break;
       CASE(F_CONST1); push_int(1); break;
@@ -568,6 +571,7 @@ static void eval_instruction(unsigned char *pc)
       CASE(F_NUMBER); push_int(GET_ARG()); break;
       CASE(F_NEG_NUMBER); push_int(-GET_ARG()); break;
 
+
       /* The rest of the basic 'push value' instructions */	
       CASE(F_STRING);
       copy_shared_string(sp->u.string,fp->context.prog->strings[GET_ARG()]);
@@ -614,6 +618,82 @@ static void eval_instruction(unsigned char *pc)
       print_return_value();
       break;
 
+      CASE(F_EXTERNAL);
+      {
+	struct inherit *inherit;
+	struct program *p;
+	INT32 id=GET_ARG();
+	struct object *o=fp->context.parent;
+	INT32 i=fp->context.parent_identifier;
+	
+	while(1)
+	{
+	  if(!o)
+	    error("Parent no longer exists\n");
+
+	  if(!(p=o->prog))
+	    error("Attempting to access variable in destructed object\n");
+
+	  inherit=INHERIT_FROM_INT(p, i);
+
+	  if(!accumulator) break;
+	  --accumulator;
+
+	  if(p->identifier_references[id].inherit_offset==0)
+	  {
+	    i=o->parent_identifier;
+	    o=o->parent;
+	  }else{
+	    i=inherit->parent_identifier;
+	    o=inherit->parent;
+	  }
+	}
+
+	low_object_index_no_free(sp,
+				 o,
+				 id + inherit->identifier_level);
+	sp++;
+	print_return_value();
+	break;
+      }
+
+      CASE(F_EXTERNAL_LVALUE);
+      {
+	struct inherit *inherit;
+	struct program *p;
+	INT32 id=GET_ARG();
+	struct object *o=fp->context.parent;
+	INT32 i=fp->context.parent_identifier;
+	
+	while(1)
+	{
+	  if(!o)
+	    error("Parent no longer exists\n");
+
+	  if(!(p=o->prog))
+	    error("Attempting to access variable in destructed object\n");
+
+	  inherit=INHERIT_FROM_INT(p, i);
+
+	  if(!accumulator) break;
+	  accumulator--;
+
+	  if(p->identifier_references[id].inherit_offset==0)
+	  {
+	    i=o->parent_identifier;
+	    o=o->parent;
+	  }else{
+	    i=inherit->parent_identifier;
+	    o=inherit->parent;
+	  }
+	}
+
+	ref_push_object(o);
+	sp->type=T_LVALUE;
+	sp->u.integer=id + inherit->identifier_level;
+	sp++;
+	break;
+      }
 
       CASE(F_MARK_AND_LOCAL); *(mark_sp++)=sp;
       CASE(F_LOCAL);
@@ -1214,6 +1294,7 @@ int apply_low_safe_and_stupid(struct object *o, INT32 offset)
   new_frame.fun = -1;
   new_frame.pc = 0;
   new_frame.current_storage=o->storage;
+  new_frame.context.parent=0;
   fp = & new_frame;
 
   new_frame.current_object->refs++;
@@ -1279,6 +1360,8 @@ void apply_low(struct object *o, int fun, int args)
   new_frame.parent_frame = fp;
   new_frame.current_object = o;
   new_frame.context = p->inherits[ ref->inherit_offset ];
+  if(!ref->inherit_offset) new_frame.context.parent=o->parent;
+
   function = new_frame.context.prog->identifiers + ref->identifier_offset;
   
   new_frame.locals = sp - args;
@@ -1289,6 +1372,7 @@ void apply_low(struct object *o, int fun, int args)
 
   new_frame.current_object->refs++;
   new_frame.context.prog->refs++;
+  if(new_frame.context.parent) new_frame.context.parent->refs++;
 
 #ifdef DEBUG
   if(t_flag)
@@ -1354,7 +1438,10 @@ void apply_low(struct object *o, int fun, int args)
     struct svalue *s=fp->context.prog->constants+function->func.offset;
     if(s->type == T_PROGRAM)
     {
-      struct object *tmp=parent_clone_object(s->u.program,o,args);
+      struct object *tmp=parent_clone_object(s->u.program,
+					     o,
+					     fun,
+					     args);
       push_object(tmp);
     }else{
       error("Calling strange value!\n");
@@ -1424,6 +1511,7 @@ void apply_low(struct object *o, int fun, int args)
     sp++;
   }
 
+  if(new_frame.context.parent) free_object(new_frame.context.parent);
   free_object(new_frame.current_object);
   free_program(new_frame.context.prog);
 
diff --git a/src/language.yacc b/src/language.yacc
index 7c194632eb026a1d546a0f92ff3b7128fcd6e131..505f33d4db58c30ef8a3c51d144883d38f9556a4 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -11,7 +11,7 @@
  */
 %token F_PREFIX_256 F_PREFIX_512 F_PREFIX_768 F_PREFIX_1024
 %token F_PREFIX_CHARX256 F_PREFIX_WORDX256 F_PREFIX_24BITX256
-%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2
+%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 F_LDA
 %token F_CALL_LFUN F_CALL_LFUN_AND_POP
 %token F_APPLY F_APPLY_AND_POP F_MARK_APPLY F_MARK_APPLY_POP
 
@@ -31,8 +31,10 @@
 /*
  * Basic value pushing
  */
-%token F_LFUN F_GLOBAL F_LOCAL F_2_LOCALS F_MARK_AND_LOCAL
-%token F_GLOBAL_LVALUE F_LOCAL_LVALUE
+%token F_LFUN
+%token F_GLOBAL F_GLOBAL_LVALUE
+%token F_LOCAL F_2_LOCALS F_LOCAL_LVALUE F_MARK_AND_LOCAL
+%token F_EXTERNAL F_EXTERNAL_LVALUE
 %token F_CLEAR_LOCAL F_CLEAR_2_LOCAL F_CLEAR_STRING_SUBTYPE
 %token F_CONSTANT F_FLOAT F_STRING F_ARROW_STRING
 %token F_NUMBER F_NEG_NUMBER F_CONST_1 F_CONST0 F_CONST1 F_BIGNUM
@@ -157,7 +159,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.42.2.2 1997/06/25 22:46:38 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.42.2.3 1997/06/27 06:55:17 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -390,16 +392,8 @@ program_ref: string_constant
       break;
 
     case T_FUNCTION:
-    {
-      struct program *p=program_from_function(sp-1);
-      if(p)
-      {
-	p->refs++;
-	pop_stack();
-	push_program(p);
+      if(program_from_function(sp-1))
 	break;
-      }
-    }
 
     default:
       yyerror("Illegal program identifier");
@@ -416,12 +410,11 @@ program_ref: string_constant
           
 inheritance: modifiers F_INHERIT program_ref optional_rename_inherit ';'
   {
-    if(sp[-1].type == T_PROGRAM &&
-       !(new_program->flags & PROGRAM_PASS_1_DONE))
+    if(!(new_program->flags & PROGRAM_PASS_1_DONE))
     {
       struct pike_string *s=sp[-2].u.string;
       if($4) s=$4;
-      do_inherit(sp[-1].u.program,$1,s);
+      do_inherit(sp-1,$1,s);
     }
     if($4) free_string($4);
     pop_n_elems(2);
@@ -679,9 +672,10 @@ type3: F_INT_ID      { push_type(T_INT); }
 opt_object_type:  /* Empty */ { push_type_int(0); }
   | '(' program_ref ')'
   {
-    if(sp[-1].type == T_PROGRAM)
+    struct program *p=program_from_svalue(sp-1);
+    if(p)
     {
-      push_type_int(sp[-1].u.program->id);
+      push_type_int(p->id);
     }else{
       yyerror("Not a valid program specifier");
       push_type_int(0);
@@ -960,25 +954,20 @@ class: modifiers F_CLASS F_IDENTIFIER
   }
   failsafe_program
   {
-    struct svalue s;
+    struct program *p;
     if(compiler_pass == 1)
-      s.u.program=end_first_pass(0);
+      p=end_first_pass(0);
     else
-      s.u.program=end_program();
+      p=end_program();
 
-    if(!s.u.program)
-    {
+    $$=mkidentifiernode(isidentifier($3));
+
+    if(!p)
       yyerror("Class definition failed.");
-      s.type=T_INT;
-      s.subtype=0;
-    } else {
-      s.type=T_PROGRAM;
-      s.subtype=0;
-    }
+    else
+      free_program(p);
 
     free_string($3);
-    $$=mksvaluenode(&s);
-    free_svalue(&s);
   }
   ;
 
@@ -1249,10 +1238,7 @@ low_idents: F_IDENTIFIER
       $$=mklocalnode(i);
     }else if((i=isidentifier($1))>=0){
       $$=mkidentifiernode(i);
-    }else if(find_module_identifier($1)){
-      $$=mkconstantsvaluenode(sp-1);
-      pop_stack();
-    }else{
+    }else if(!($$=find_module_identifier($1))){
       $$=0;
       if( get_master() && !num_parse_error)
       {
diff --git a/src/las.c b/src/las.c
index abf41900f6c514d54a9c2ee3ea20494e6605dd23..8c26260334f74f69b864fc72bf95331a6bf0caf9 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.32.2.1 1997/06/25 22:46:39 hubbe Exp $");
+RCSID("$Id: las.c,v 1.32.2.2 1997/06/27 06:55:17 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -45,6 +45,7 @@ int car_is_node(node *n)
 {
   switch(n->token)
   {
+  case F_EXTERNAL:
   case F_IDENTIFIER:
   case F_CONSTANT:
   case F_LOCAL:
@@ -59,6 +60,7 @@ int cdr_is_node(node *n)
 {
   switch(n->token)
   {
+  case F_EXTERNAL:
   case F_IDENTIFIER:
   case F_CONSTANT:
   case F_LOCAL:
@@ -377,13 +379,12 @@ node *mkefuncallnode(char *function, node *args)
   struct pike_string *name;
   node *n;
   name = findstring(function);
-  if(!name || !find_module_identifier(name))
+  if(!name || !(n=find_module_identifier(name)))
   {
     my_yyerror("Internally used efun undefined: %s",function);
     return mkintnode(0);
   }
-  n=mkapplynode(mksvaluenode(sp-1), args);
-  pop_stack();
+  n=mkapplynode(n, args);
   return n;
 }
 
@@ -431,6 +432,27 @@ node *mkidentifiernode(int i)
   return res;
 }
 
+node *mkexternalnode(int level,
+		     int i,
+		     struct identifier *id)
+{
+  node *res = mkemptynode();
+  res->token = F_EXTERNAL;
+
+  copy_shared_string(res->type, id->type);
+
+  /* FIXME */
+  res->node_info = OPT_NOT_CONST;
+  res->tree_info=res->node_info;
+
+#ifdef __CHECKER__
+  CDR(res)=0;
+#endif
+  res->u.integer.a = level;
+  res->u.integer.b = i;
+  return res;
+}
+
 node *mkcastnode(struct pike_string *type,node *n)
 {
   node *res;
@@ -455,6 +477,9 @@ node *mkcastnode(struct pike_string *type,node *n)
 void resolv_constant(node *n)
 {
   struct identifier *i;
+  struct program *p;
+  INT32 numid;
+
   if(!n)
   {
     push_int(0);
@@ -463,30 +488,49 @@ void resolv_constant(node *n)
     {
     case F_CONSTANT:
       push_svalue(& n->u.sval);
-      break;
+      return;
 
-    case F_IDENTIFIER:
-      i=ID_FROM_INT(new_program, n->u.number);
-	
-      if(IDENTIFIER_IS_CONSTANT(i->flags))
+    case F_EXTERNAL:
+      p=parent_compilation(n->u.integer.a);
+      if(!p)
       {
-	push_svalue(PROG_FROM_INT(new_program, n->u.number)->constants +
-		    i->func.offset);
-      }else{
-	yyerror("Identifier is not a constant");
+	yyerror("Failed to resolv external constant");
 	push_int(0);
+	return;
       }
+      numid=n->u.integer.b;
+      break;
+
+    case F_IDENTIFIER:
+      p=new_program;
+      numid=n->u.number;
       break;
 
     case F_LOCAL:
-	yyerror("Expected constant, got local variable");
-	push_int(0);
-	break;
+      yyerror("Expected constant, got local variable");
+      push_int(0);
+      return;
 
     case F_GLOBAL:
-	yyerror("Expected constant, got global variable");
-	push_int(0);
-	break;
+      yyerror("Expected constant, got global variable");
+      push_int(0);
+      return;
+
+    default:
+      yyerror("Expected constant, got something else");
+      push_int(0);
+      return;
+    }
+
+    i=ID_FROM_INT(p, numid);
+    
+    if(IDENTIFIER_IS_CONSTANT(i->flags))
+    {
+      push_svalue(PROG_FROM_INT(new_program, numid)->constants +
+		  i->func.offset);
+    }else{
+      yyerror("Identifier is not a constant");
+      push_int(0);
     }
   }
 }
diff --git a/src/las.h b/src/las.h
index 7b750e149a10fba4cd8018547fae8352d0459251..e3b1ad1c285dc0fb840a8d46c838e42168ca724c 100644
--- a/src/las.h
+++ b/src/las.h
@@ -35,9 +35,17 @@ struct node_s
     {
       struct node_s *a,*b;
     } node;
+    struct
+    {
+      int a,b;
+    } integer;
   } u;
 };
 
+#ifndef STRUCT_NODE_S_DECLARED
+#define STRUCT_NODE_S_DECLARED
+#endif
+
 typedef struct node_s node;
 
 extern node *init_node;
@@ -93,6 +101,9 @@ node *mkefuncallnode(char *function, node *args);
 node *mkopernode(char *oper_id, node *arg1, node *arg2);
 node *mklocalnode(int var);
 node *mkidentifiernode(int i);
+node *mkexternalnode(int level,
+		     int i,
+		     struct identifier *id);
 node *mkcastnode(struct pike_string *type,node *n);
 void resolv_constant(node *n);
 node *index_node(node *n, struct pike_string * id);
@@ -116,7 +127,6 @@ int dooptcode(struct pike_string *name,
 	      node *n,
 	      struct pike_string *type,
 	      int modifiers);
-INT32 get_opt_info();
 /* Prototypes end here */
 
 #define CAR(n) ((n)->u.node.a)
diff --git a/src/lex.c b/src/lex.c
index 507d5e682c3f1b818f59ecd07c67d3931532a880..fb4c3e8170859f49631a27bfa94cf5dfad3c57f6 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: lex.c,v 1.21.2.2 1997/06/25 22:46:39 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.21.2.3 1997/06/27 06:55:18 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -141,6 +141,9 @@ struct keyword instr_names[]=
 { "local function call and pop",F_CALL_LFUN_AND_POP, I_HASARG },
 { "local function",	F_LFUN, I_HASARG },	
 { "local",		F_LOCAL, I_HASARG },	
+{ "external",		F_EXTERNAL, I_HASARG },
+{ "& external",		F_EXTERNAL_LVALUE, I_HASARG },
+{ "LDA",			F_LDA, I_HASARG },
 { "mark & local",	F_MARK_AND_LOCAL, I_HASARG },	
 { "ltosval2",		F_LTOSVAL2 },
 { "lvalue to svalue",	F_LTOSVAL },	
diff --git a/src/main.c b/src/main.c
index 15b253193a4029969bdc9478e93f47aa061c7100..ac212dc6b0525c0397df7841828dffb4ee716124 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: main.c,v 1.21.2.1 1997/06/25 22:46:40 hubbe Exp $");
+RCSID("$Id: main.c,v 1.21.2.2 1997/06/27 06:55:19 hubbe Exp $");
 #include "types.h"
 #include "backend.h"
 #include "module.h"
@@ -23,6 +23,7 @@ RCSID("$Id: main.c,v 1.21.2.1 1997/06/25 22:46:40 hubbe Exp $");
 #include "dynamic_load.h"
 #include "gc.h"
 #include "mapping.h"
+#include "cpp.h"
 
 #ifdef HAVE_LOCALE_H
 #include <locale.h>
diff --git a/src/object.c b/src/object.c
index 5b9aa08600e7434a577e7d8e7977011f51246301..e23b890d09f4219f03c8490a0ca3914c4d05f489 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.17.2.2 1997/06/25 22:46:41 hubbe Exp $");
+RCSID("$Id: object.c,v 1.17.2.3 1997/06/27 06:55:19 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -19,6 +19,8 @@ RCSID("$Id: object.c,v 1.17.2.2 1997/06/25 22:46:41 hubbe Exp $");
 #include "gc.h"
 #include "backend.h"
 #include "callback.h"
+#include "cpp.h"
+#include "builtin_functions.h"
 
 struct object *master_object = 0;
 struct program *master_program =0;
@@ -33,13 +35,9 @@ void setup_fake_object()
   fake_object.refs=0xffffff;
 }
 
-struct object *low_clone(struct program *p,
-			 struct object *parent)
+static struct object *low_clone(struct program *p)
 {
-  int e;
   struct object *o;
-  struct frame frame;
-
   if(!(p->flags & PROGRAM_FINISHED))
     error("Attempting to clone an unfinished program\n");
 
@@ -48,14 +46,23 @@ struct object *low_clone(struct program *p,
   o=(struct object *)xalloc(sizeof(struct object)-1+p->storage_needed);
 
   o->prog=p;
-  if((o->parent=parent)) parent->refs++;
   p->refs++;
   o->next=first_object;
   o->prev=0;
+  o->parent=0;
+  o->parent_identifier=0;
   if(first_object)
     first_object->prev=o;
   first_object=o;
   o->refs=1;
+  return o;
+}
+
+static void call_c_initializers(struct object *o)
+{
+  int e;
+  struct frame frame;
+  struct program *p=o->prog;
 
   frame.parent_frame=fp;
   frame.current_object=o;
@@ -104,11 +111,9 @@ struct object *low_clone(struct program *p,
 
   free_object(frame.current_object);
   fp = frame.parent_frame;
-
-  return o;
 }
 
-static void init_object(struct object *o, int args)
+static void call_pike_initializers(struct object *o, int args)
 {
   apply_lfun(o,LFUN___INIT,0);
   pop_stack();
@@ -118,17 +123,23 @@ static void init_object(struct object *o, int args)
 
 struct object *clone_object(struct program *p, int args)
 {
-  struct object *o=low_clone(p,0);
-  init_object(o,args);
+  struct object *o=low_clone(p);
+  call_c_initializers(o);
+  call_pike_initializers(o,args);
   return o;
 }
 
 struct object *parent_clone_object(struct program *p,
 				   struct object *parent,
+				   int parent_identifier,
 				   int args)
 {
-  struct object *o=low_clone(p,parent);
-  init_object(o,args);
+  struct object *o=low_clone(p);
+  o->parent=parent;
+  parent->refs++;
+  o->parent_identifier=parent_identifier;
+  call_c_initializers(o);
+  call_pike_initializers(o,args);
   return o;
 }
 
@@ -177,9 +188,10 @@ struct object *get_master()
     master_program=sp[-1].u.program;
     sp--;
   }
-  master_object=low_clone(master_program,0);
+  master_object=low_clone(master_program);
 
-  init_object(master_object,0);
+  call_c_initializers(master_object);
+  call_pike_initializers(master_object,0);
   
   inside = 0;
   return master_object;
@@ -405,32 +417,6 @@ void low_object_index_no_free(struct svalue *to,
   }
 }
 
-void object_index_no_free2(struct svalue *to,
-			  struct object *o,
-			  struct svalue *index)
-{
-  struct program *p;
-  int f;
-
-  if(!o || !(p=o->prog))
-  {
-    error("Lookup in destructed object.\n");
-    return; /* make gcc happy */
-  }
-
-  if(index->type != T_STRING)
-    error("Lookup on non-string value.\n");
-
-  f=find_shared_string_identifier(index->u.string, p);
-  if(f < 0)
-  {
-    to->type=T_INT;
-    to->subtype=NUMBER_UNDEFINED;
-    to->u.integer=0;
-  }else{
-    low_object_index_no_free(to, o, f);
-  }
-}
 
 #define ARROW_INDEX_P(X) ((X)->type==T_STRING && (X)->subtype)
 
@@ -439,23 +425,46 @@ void object_index_no_free(struct svalue *to,
 			   struct svalue *index)
 {
   struct program *p;
-  int lfun;
+  int f;
 
   if(!o || !(p=o->prog))
   {
     error("Lookup in destructed object.\n");
     return; /* make gcc happy */
   }
-  lfun=ARROW_INDEX_P(index) ? LFUN_ARROW : LFUN_INDEX;
-
-  if(p->lfuns[lfun] != -1)
+  f=ARROW_INDEX_P(index) ? LFUN_ARROW : LFUN_INDEX;
+  if(p->lfuns[f] != -1)
   {
     push_svalue(index);
-    apply_lfun(o,lfun,1);
+    apply_lfun(o,f,1);
     to=sp;
     sp--;
-  } else {
-    object_index_no_free2(to,o,index);
+    return;
+  }
+  switch(index->type)
+  {
+  case T_STRING:
+    f=find_shared_string_identifier(index->u.string, p);
+    free_string(index->u.string);
+    index->type=T_LVALUE;
+    index->u.integer=f;
+    break;
+    
+  case T_LVALUE:
+    f=index->u.integer;
+    break;
+      
+  default:
+    error("Lookup on non-string value.\n");
+  }
+    
+  if(f < 0)
+  {
+    to->type=T_INT;
+    to->subtype=NUMBER_UNDEFINED;
+    to->u.integer=0;
+  }else{
+    low_object_index_no_free(to, o, f);
   }
 }
 
@@ -494,9 +503,9 @@ void object_low_set_index(struct object *o,
   }
 }
 
-void object_set_index2(struct object *o,
-		      struct svalue *index,
-		      struct svalue *from)
+void object_set_index(struct object *o,
+		       struct svalue *index,
+		       struct svalue *from)
 {
   struct program *p;
   int f;
@@ -506,42 +515,39 @@ void object_set_index2(struct object *o,
     error("Lookup in destructed object.\n");
     return; /* make gcc happy */
   }
-
-  if(index->type != T_STRING)
-    error("Lookup on non-string value.\n");
-
-  f=find_shared_string_identifier(index->u.string, p);
-  if(f < 0)
+  f=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX;
+  if(p->lfuns[f] != -1)
   {
-    error("No such variable (%s) in object.\n", index->u.string->str);
-  }else{
-    object_low_set_index(o, f, from);
+    push_svalue(index);
+    push_svalue(from);
+    apply_lfun(o,f,2);
+    pop_stack();
+    return;
   }
-}
+  switch(index->type)
+  {
+  case T_STRING:
+    f=find_shared_string_identifier(index->u.string, p);
+    if(f<0)
+      error("No such variable (%s) in object.\n", index->u.string->str);
+    free_string(index->u.string);
+    index->type=T_LVALUE;
+    index->u.integer=f;
+    break;
 
-void object_set_index(struct object *o,
-		       struct svalue *index,
-		       struct svalue *from)
-{
-  struct program *p;
-  int lfun;
+  case T_LVALUE:
+    f=index->u.integer;
+    break;
 
-  if(!o || !(p=o->prog))
-  {
-    error("Lookup in destructed object.\n");
-    return; /* make gcc happy */
+  default:
+    error("Lookup on non-string value.\n");
   }
 
-  lfun=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX;
-
-  if(p->lfuns[lfun] != -1)
+  if(f < 0)
   {
-    push_svalue(index);
-    push_svalue(from);
-    apply_lfun(o,lfun,2);
-    pop_stack();
-  } else {
-    object_set_index2(o,index,from);
+    error("Assigning nonexistant variable in object\n");
+  }else{
+    object_low_set_index(o, f, from);
   }
 }
 
@@ -596,10 +602,24 @@ union anything *object_get_item_ptr(struct object *o,
   if(p->lfuns[f] != -1)
     error("Cannot do incremental operations on overloaded index (yet).\n");
 
-  if(index->type != T_STRING)
+  switch(index->type)
+  {
+  case T_STRING:
+    f=find_shared_string_identifier(index->u.string, p);
+    free_string(index->u.string);
+    index->type=T_LVALUE;
+    index->u.integer=f;
+    break;
+
+  case T_LVALUE:
+    f=index->u.integer;
+    break;
+
+  default:
     error("Lookup on non-string value.\n");
+    return 0;
+  }
 
-  f=find_shared_string_identifier(index->u.string, p);
   if(f < 0)
   {
     error("No such variable in object.\n");
@@ -810,6 +830,9 @@ void gc_mark_object_as_referenced(struct object *o)
 {
   if(gc_mark(o))
   {
+    if(o->parent)
+      gc_mark_object_as_referenced(o);
+      
     if(o->prog)
     {
       INT32 e;
@@ -839,6 +862,14 @@ void gc_check_all_objects()
   struct object *o;
   for(o=first_object;o;o=o->next)
   {
+#ifdef DEBUG
+    if(o->parent)
+      if(gc_check(o->parent)==-2)
+	fprintf(stderr,"(in object at %lx -> parent)\n",(long)o);
+#else
+    if(o->parent)
+      gc_check(o->parent);
+#endif
     if(o->prog)
     {
       INT32 e;
diff --git a/src/object.h b/src/object.h
index 4d39c455fd32e47ad87613068ea1ab59d9139923..e62666dbf324568dbfbaabb4b221f49eccbd5ae7 100644
--- a/src/object.h
+++ b/src/object.h
@@ -19,6 +19,7 @@ struct object
   INT32 refs;                    /* Reference count, must be first. */
   struct program *prog;
   struct object *parent;
+  INT16 parent_identifier;
   struct object *next;
   struct object *prev;
   char storage[1];
@@ -39,11 +40,10 @@ extern struct program *master_program;
 
 /* Prototypes begin here */
 void setup_fake_object();
-struct object *low_clone(struct program *p,
-			 struct object *parent);
 struct object *clone_object(struct program *p, int args);
 struct object *parent_clone_object(struct program *p,
 				   struct object *parent,
+				   int parent_identifier,
 				   int args);
 struct object *get_master();
 struct object *master();
@@ -53,18 +53,12 @@ void really_free_object(struct object *o);
 void low_object_index_no_free(struct svalue *to,
 			      struct object *o,
 			      INT32 f);
-void object_index_no_free2(struct svalue *to,
-			  struct object *o,
-			  struct svalue *index);
 void object_index_no_free(struct svalue *to,
 			   struct object *o,
 			   struct svalue *index);
 void object_low_set_index(struct object *o,
 				 int f,
 				 struct svalue *from);
-void object_set_index2(struct object *o,
-		      struct svalue *index,
-		      struct svalue *from);
 void object_set_index(struct object *o,
 		       struct svalue *index,
 		       struct svalue *from);
diff --git a/src/program.c b/src/program.c
index a23b69b9222db6fa229e8ca1f6eeff7084dda4ef..4f44ed04fd591ab7ba2c032df5ae336125c2de83 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.33.2.2 1997/06/25 22:46:43 hubbe Exp $");
+RCSID("$Id: program.c,v 1.33.2.3 1997/06/27 06:55:20 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -147,12 +147,16 @@ void use_module(struct svalue *s)
 }
 
 
-static int low_find_shared_string_identifier(struct pike_string *name,
-					     struct program *prog);
 
-int find_module_identifier(struct pike_string *ident)
+int low_find_shared_string_identifier(struct pike_string *name,
+				      struct program *prog);
+
+
+
+struct node_s *find_module_identifier(struct pike_string *ident)
 {
   JMP_BUF tmp;
+  node *ret;
 
   if(SETJMP(tmp))
   {
@@ -178,7 +182,9 @@ int find_module_identifier(struct pike_string *ident)
       {
 /*	fprintf(stderr,"MOD: %s, %d %d\n",ident->str, current_line, sp[-1].type); */
 	UNSETJMP(tmp);
-	return 1;
+	ret=mksvaluenode(sp-1);
+	pop_stack();
+	return ret;
       }
       pop_stack();
     }
@@ -197,20 +203,31 @@ int find_module_identifier(struct pike_string *ident)
 	id=ID_FROM_INT(p->new_program, i);
 	if(IDENTIFIER_IS_CONSTANT(id->flags))
 	{
-	  push_svalue(PROG_FROM_INT(p->new_program, i)->constants+
-		      id->func.offset);
-	  return 1;
+	  ret=mksvaluenode(PROG_FROM_INT(p->new_program, i)->constants+
+			   id->func.offset);
+	  return ret;
 	}else{
-	  yyerror("Identifier is not a constant");
-	  return 0;
+	  return mkexternalnode(n, i, id);
 	}
       }
     }
   }
-
   return 0;
 }
 
+struct program *parent_compilation(int level)
+{
+  int n;
+  struct program_state *p=previous_program_state;
+  for(n=0;n<level;n++)
+  {
+    if(n>=compilation_depth) return 0;
+    p=p->previous;
+    if(!p) return 0;
+  }
+  return p->new_program;
+}
+
 #define ID_TO_PROGRAM_CACHE_SIZE 512
 struct program *id_to_program_cache[ID_TO_PROGRAM_CACHE_SIZE];
 
@@ -406,6 +423,8 @@ void low_start_new_program(struct program *p,
     i.identifier_level=0;
     i.storage_offset=0;
     i.inherit_level=0;
+    i.parent=0;
+    i.parent_identifier=0;
     i.name=0;
     add_to_inherits(i);
   }
@@ -452,7 +471,11 @@ void really_free_program(struct program *p)
     free_svalue(p->constants+e);
 
   for(e=1; e<p->num_inherits; e++)
+  {
     free_program(p->inherits[e].prog);
+    if(p->inherits[e].parent)
+      free_object(p->inherits[e].parent);
+  }
 
   if(p->prev)
     p->prev->next=p->next;
@@ -843,12 +866,23 @@ void rename_last_inherit(struct pike_string *n)
 /*
  * make this program inherit another program
  */
-void do_inherit(struct program *p,INT32 flags, struct pike_string *name)
+void do_inherit(struct svalue *prog,
+		INT32 flags,
+		struct pike_string *name)
 {
   int e, inherit_offset, storage_offset;
   struct inherit inherit;
   struct pike_string *s;
 
+  struct program *p=program_from_svalue(prog);
+
+  
+  if(!p)
+  {
+    yyerror("Illegal program pointer.");
+    return;
+  }
+
   inherit_offset = new_program->num_inherits;
 
   storage_offset=new_program->storage_needed;
@@ -861,7 +895,15 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name)
     inherit.identifier_level += new_program->num_identifier_references;
     inherit.storage_offset += storage_offset;
     inherit.inherit_level ++;
-
+    if(!e)
+    {
+      if(prog->type == T_FUNCTION)
+      {
+	inherit.parent=prog->u.object;
+	inherit.parent_identifier=prog->subtype;
+      }
+    }
+    if(inherit.parent) inherit.parent->refs++;
 
     if(name)
     {
@@ -933,7 +975,9 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name)
   }
 }
 
-void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *name)
+void simple_do_inherit(struct pike_string *s,
+		       INT32 flags,
+		       struct pike_string *name)
 {
   reference_shared_string(s);
   push_string(s);
@@ -952,7 +996,7 @@ void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *na
     free_string(s);
     s=name;
   }
-  do_inherit(sp[-1].u.program, flags, s);
+  do_inherit(sp-1, flags, s);
   free_string(s);
   pop_stack();
 }
@@ -1027,8 +1071,12 @@ int define_variable(struct pike_string *name,
     dummy.flags = 0;
     dummy.run_time_type=compile_type_to_runtime_type(type);
 
-    if(dummy.run_time_type == T_FUNCTION)
+    switch(dummy.run_time_type)
+    {
+    case T_FUNCTION:
+    case T_PROGRAM:
       dummy.run_time_type = T_MIXED;
+    }
 
     dummy.func.offset=add_storage(dummy.run_time_type == T_MIXED ?
 				  sizeof(struct svalue) :
@@ -1335,8 +1383,8 @@ INT32 define_function(struct pike_string *name,
  * lookup the number of a function in a program given the name in
  * a shared_string
  */
-static int low_find_shared_string_identifier(struct pike_string *name,
-					     struct program *prog)
+int low_find_shared_string_identifier(struct pike_string *name,
+				      struct program *prog)
 {
   int max,min,tst;
   struct reference *funp;
@@ -1722,7 +1770,20 @@ void cleanup_program(void)
 void gc_mark_program_as_referenced(struct program *p)
 {
   if(gc_mark(p))
+  {
+    int e;
     gc_mark_svalues(p->constants, p->num_constants);
+
+    for(e=0;e<p->num_inherits;e++)
+    {
+      if(p->inherits[e].parent)
+	gc_mark_object_as_referenced(p->inherits[e].parent);
+
+      if(e)
+	gc_mark_program_as_referenced(p->inherits[e].prog);
+    }
+      
+  }
 }
 
 void gc_check_all_programs(void)
@@ -1730,8 +1791,30 @@ void gc_check_all_programs(void)
   struct program *p;
   for(p=first_program;p;p=p->next)
   {
+    int e;
     gc_check_svalues(p->constants, p->num_constants);
 
+    for(e=0;e<p->num_inherits;e++)
+    {
+      if(p->inherits[e].parent)
+      {
+#ifdef DEBUG
+	if(gc_check(p->inherits[e].parent)==-2)
+	  fprintf(stderr,"(program at 0x%lx -> inherit[%d].parent)\n",
+		  (long)p,
+		  e);
+#else
+	gc_check(p->inherits[e].parent);
+#endif
+      }
+
+      if(d_flag && p->inherits[e].name)
+	gc_check(p->inherits[e].name);
+
+      if(e)
+	gc_check(p->inherits[e].prog);
+    }
+
     if(d_flag)
     {
       int e;
@@ -1763,8 +1846,17 @@ void gc_free_all_unreferenced_programs(void)
   {
     if(gc_do_free(p))
     {
+      int e;
       p->refs++;
       free_svalues(p->constants, p->num_constants, -1);
+      for(e=0;e<p->num_inherits;e++)
+      {
+	if(p->inherits[e].parent)
+	{
+	  free_object(p->inherits[e].parent);
+	  p->inherits[e].parent=0;
+	}
+      }
       next=p->next;
       free_program(p);
     }else{
@@ -1895,6 +1987,19 @@ struct program *program_from_function(struct svalue *f)
   return low_program_from_function(f->u.object->prog, f->subtype);
 }
 
+struct program *program_from_svalue(struct svalue *s)
+{
+  switch(s->type)
+  {
+  case T_FUNCTION:
+    return program_from_function(s);
+  case T_PROGRAM:
+    return s->u.program;
+  default:
+    return 0;
+  }
+}
+
 #define FIND_CHILD_HASHSIZE 5003
 struct find_child_cache_s
 {
diff --git a/src/program.h b/src/program.h
index 9eba51d6ea8a8adc864636e82b6789bb4ffbaec6..45c44a4b22ef68530300b8f1c671e6a0da96b715 100644
--- a/src/program.h
+++ b/src/program.h
@@ -49,6 +49,11 @@ extern char *lfun_names[];
 struct svalue;
 #endif
 
+#ifndef STRUCT_NODE_S_DECLARED
+#define STRUCT_NODE_S_DECLARED
+struct node_s;
+#endif
+
 #ifndef STRUCT_OBJECT_DECLARED
 #define STRUCT_OBJECT_DECLARED
 struct object;
@@ -127,11 +132,13 @@ struct reference
 
 struct inherit
 {
-  struct program *prog;
-  struct pike_string *name;
   INT16 inherit_level; /* really needed? */
   INT16 identifier_level;
+  INT16 parent_identifier;
   INT32 storage_offset;
+  struct object *parent;
+  struct program *prog;
+  struct pike_string *name;
 };
 
 /* program parts have been realloced into one block */
@@ -197,7 +204,8 @@ extern int compiler_pass;
 void ins_int(INT32 i, void (*func)(char tmp));
 void ins_short(INT16 i, void (*func)(char tmp));
 void use_module(struct svalue *s);
-int find_module_identifier(struct pike_string *ident);
+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);
 void fixate_program(void);
@@ -218,8 +226,12 @@ int low_reference_inherited_identifier(int e,
 int reference_inherited_identifier(struct pike_string *super_name,
 				   struct pike_string *function_name);
 void rename_last_inherit(struct pike_string *n);
-void do_inherit(struct program *p,INT32 flags, struct pike_string *name);
-void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *name);
+void do_inherit(struct svalue *prog,
+		INT32 flags,
+		struct pike_string *name);
+void simple_do_inherit(struct pike_string *s,
+		       INT32 flags,
+		       struct pike_string *name);
 int isidentifier(struct pike_string *s);
 int define_variable(struct pike_string *name,
 		    struct pike_string *type,
@@ -252,6 +264,8 @@ INT32 define_function(struct pike_string *name,
 		      INT16 flags,
 		      INT8 function_flags,
 		      union idptr *func);
+int low_find_shared_string_identifier(struct pike_string *name,
+				      struct program *prog);
 struct ff_hash;
 int find_shared_string_identifier(struct pike_string *name,
 				  struct program *prog);
@@ -278,6 +292,7 @@ char *get_storage(struct object *o, struct program *p);
 struct program *low_program_from_function(struct program *p,
 					  INT32 i);
 struct program *program_from_function(struct svalue *f);
+struct program *program_from_svalue(struct svalue *s);
 struct find_child_cache_s;
 int find_child(struct program *parent, struct program *child);
 void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2)));
diff --git a/src/svalue.c b/src/svalue.c
index 565de67fa9fd87ea0e376d0bf04b4d673fc59816..09df8a58e3b65eaf2d6748c1dc5f9c1016afeed6 100644
--- a/src/svalue.c
+++ b/src/svalue.c
@@ -897,7 +897,12 @@ TYPE_FIELD gc_check_svalues(struct svalue *s, int num)
     case T_OBJECT:
       if(s->u.object->prog)
       {
-	gc_check(s->u.object);
+#ifdef DEBUG
+	if(gc_check(s->u.object) == -2)
+	  fprintf(stderr,"(in svalue at %lx, type = %d)\n",(long)s,s->type);
+#else	  
+	  gc_check(s->u.object);
+#endif
       }else{
 	free_svalue(s);
 	s->type=T_INT;
diff --git a/src/testsuite.in b/src/testsuite.in
index d796edd591a4aeaaea3c7505f031b18688eb384b..44cb55fe2c3ef7b37d28e5a60d37b1aea240ad78 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,9 +1,19 @@
-test_true([["$Id: testsuite.in,v 1.40.2.2 1997/06/25 22:46:46 hubbe Exp $"]])
+test_true([["$Id: testsuite.in,v 1.40.2.3 1997/06/27 06:55:22 hubbe Exp $"]])
 test_eq(1e1,10.0)
 test_eq(1E1,10.0)
 test_eq(1e+1,10.0)
 test_eq(1.1e1,11.0)
 test_eq(1e-1,0.1)
+test_any([[object o=class foo{int c;class bar{void create(){c++;};}}(); o->bar(); return o->c;]],1)
+test_do([[add_constant("GURKA2",class foo { int c; class bar{void create() {c+=17;}}}()); ]])
+test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],17)
+test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],34)
+
+test_do([[add_constant("GURKA2",class foo { int c; class bar{void create() { class sune { void create() {c+=17;}}(); }}}()); ]])
+test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],17)
+test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],34)
+test_do([[add_constant("GURKA2");]]);
+
 test_compile_error([[void foo() { return destruct(this_object()); }]])
 test_any([[class foo { constant x=17; }; class bar { inherit foo; constant x=18; }; return bar()->x;]],18)
 test_program([[inline string foo(string s){ while(s[0] == ' ' || s[0] == '\t') s = s[1..]; return(s); } string a() { return foo("   bar"); }]])