diff --git a/lib/master.pike b/lib/master.pike
index 47505abf589883a0862524b4607bc18c747bd9c0..215964e5ef3c92827acb35ab133f845b1909ce75 100644
--- a/lib/master.pike
+++ b/lib/master.pike
@@ -1,3 +1,4 @@
+#define UNDEFINED (([])[0])
 string describe_backtrace(mixed *trace);
 
 string pike_library_path;
@@ -15,7 +16,7 @@ void putenv(string var, string val)
   environment[var]=val;
 }
 
-mapping (string:program) programs=([]);
+mapping (string:program) programs=(["/master":object_program(this_object())]);
 
 #define capitalize(X) (upper_case((X)[..0])+(X)[1..])
 
@@ -36,6 +37,36 @@ void add_precompiled_program(string name, program p)
   }
 }
 
+static program findprog(string pname)
+{
+  program ret;
+  
+  if(ret=programs[pname]) return ret;
+  
+  if(file_stat(pname))
+  {
+    ret=compile_file(pname);
+  }
+  else if(file_stat(pname+".pike"))
+  {
+    ret=compile_file(pname+".pike");
+  }
+#if efun(load_module)
+  else if(file_stat(pname+".so"))
+  {
+    load_module(pname+".so");
+    ret=programs[pname];
+  }
+#endif
+  if(ret)
+  {
+    programs[pname]=ret;
+    return ret;
+  }else{
+    return UNDEFINED;
+  }
+}
+
 /* This function is called when the driver wants to cast a string
  * to a program, this might be because of an explicit cast, an inherit
  * or a implict cast. In the future it might receive more arguments,
@@ -46,31 +77,6 @@ program cast_to_program(string pname)
   if(pname[sizeof(pname)-3..sizeof(pname)]==".pike")
     pname=pname[0..sizeof(pname)-4];
 
-  function findprog=lambda(string pname)
-  {
-    program ret;
-
-    if(ret=programs[pname]) return ret;
-  
-    if(file_stat(pname))
-    {
-      ret=compile_file(pname);
-    }
-    else if(file_stat(pname+".pike"))
-    {
-      ret=compile_file(pname+".pike");
-    }
-#if efun(load_module)
-    else if(file_stat(pname+".so"))
-    {
-      load_module(pname+".so");
-      ret=programs[pname];
-    }
-#endif
-    if(ret) programs[pname]=ret;
-    return ret;
-  };
-
   if(pname[0]=='/')
   {
     return findprog(pname);
@@ -163,11 +169,52 @@ object cast_to_object(string oname)
   return objects[oname]=cast_to_program(oname)();
 }
 
+class dirnode
+{
+  string dirname;
+  void create(string name) { dirname=name; }
+  object|program `[](string index)
+  {
+    index=dirname+"/"+index;
+    return
+      ((object)"/master")->findmodule(index) || (program) index;
+  }
+};
 
-mixed resolv(string identifier, string file)
+object findmodule(string fullname)
 {
-  /* Module system goes here */
-  throw(sprintf("'%s' is undefined.",identifier));
+  mixed *stat;
+  if(mixed *stat=file_stat(fullname))
+  {
+    if(stat[1]==-2) return dirnode(fullname);
+  }
+  program p;
+  if(p=(program)(fullname+".pmod"))
+    return (object)(fullname+".pmod");
+  return UNDEFINED;
+}
+
+mixed resolv(string identifier, string current_file)
+{
+  mixed ret;
+  string *tmp,path;
+
+  tmp=current_file/"/";
+  tmp[-1]=identifier;
+  path=combine_path(getcwd(), tmp*"/");
+  if(ret=findmodule(path)) return tmp;
+
+  if(path=getenv("PIKE_MODULE_PATH"))
+  {
+    foreach(path/":", path)
+      {
+	path=combine_path(path,identifier);
+	if(ret=findmodule(path)) return ret;
+      }
+  }
+
+  path=combine_path(pike_library_path+"/modules",identifier);
+  return findmodule(path);
 }
 
 /* This function is called when all the driver is done with all setup
diff --git a/src/ChangeLog b/src/ChangeLog
index 2af827b40341479870e31f4015534d6cf28f07aa..188d3105b5937b83d4f7049c1188092b558b091a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+Sun Jan 19 01:03:49 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
+
+	* new module system implemented. '.' operator utilized
+
 Sat Jan 18 13:54:23 1997  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
 
 	* f___version moved from main.c to version.c and renamed to f_version.
diff --git a/src/Makefile.in b/src/Makefile.in
index d853da01a7956e6698090c44de30ffb186c2d6ae..3c4dc73bdb3aefecde19a657ff602c9efe5101c2 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -132,6 +132,7 @@ install:
 	if [ ! -d "$(prefix)" ]; then mkdir "$(prefix)" ; chmod 755 "$(prefix)" ; else : ; fi
 	if [ ! -d "$(exec_prefix)" ]; then mkdir "$(exec_prefix)" ; chmod 755 "$(exec_prefix)" ; else : ; fi
 	$(INSTALL) ./pike $(exec_prefix)
+	$(INSTALL) ../bin/hilfe $(exec_prefix)
 	if [ ! -d "$(prefix)/lib" ]; then mkdir "$(prefix)/lib" ; chmod 755 "$(prefix)/lib" ; else : ; fi
 	if [ ! -d "$(lib_prefix)" ]; then mkdir "$(lib_prefix)" ; chmod 755 "$(lib_prefix)" ; else : ; fi
 	if [ ! -d "$(prefix)/include" ]; then mkdir "$(prefix)/include"; chmod 755 "$(prefix)/include"; fi
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 54f2ea6699b053b26cbe5263fbf5fc3499141b38..ee0c21a2a88b22136a95be6e62437c5d13f04f64 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.20 1997/01/18 21:34:32 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.21 1997/01/19 09:07:59 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "macros.h"
@@ -1606,7 +1606,7 @@ void init_builtin_efuns()
 {
   init_operators();
   
-  add_efun("_refs",f__refs,"function(string|array|mapping|multiset|object|program:int)",OPT_EXTERNAL_DEPEND);
+  add_efun("_refs",f__refs,"function(function|string|array|mapping|multiset|object|program:int)",OPT_EXTERNAL_DEPEND);
   add_efun("replace_master",f_replace_master,"function(object:void)",OPT_SIDE_EFFECT);
   add_efun("add_constant",f_add_constant,"function(string,void|mixed:void)",OPT_SIDE_EFFECT);
   add_efun("aggregate",f_aggregate,"function(mixed ...:mixed *)",OPT_TRY_OPTIMIZE);
diff --git a/src/interpret.h b/src/interpret.h
index 3ae421679252c6021c51f126def00f059cd84741..1ca3f0fd53de7d4b41e3d590ca155a55ff1301ab 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -40,7 +40,7 @@ struct frame
 #define push_mapping(M) do{ struct mapping *_=(M); sp->u.mapping=_; sp++->type=T_MAPPING; }while(0)
 #define push_array(A) do{ struct array *_=(A); sp->u.array=_ ;sp++->type=T_ARRAY; }while(0)
 #define push_multiset(L) do{ struct multiset *_=(L); sp->u.multiset=_; sp++->type=T_MULTISET; }while(0)
-#define push_string(S) do{ struct pike_string *_=(S); sp->u.string=_; sp++->type=T_STRING; }while(0)
+#define push_string(S) do{ struct pike_string *_=(S); sp->subtype=0; sp->u.string=_; sp++->type=T_STRING; }while(0)
 #define push_object(O) do{ struct object  *_=(O); sp->u.object=_; sp++->type=T_OBJECT; }while(0)
 #define push_float(F) do{ float _=(F); sp->u.float_number=_; sp++->type=T_FLOAT; }while(0)
 #define push_text(T) push_string(make_shared_string((T)))
diff --git a/src/language.yacc b/src/language.yacc
index 5be58913c23555aaeed459f4f078f65ae678f437..b9e2f54b4548ee5a36aaa8d1bd543a53793a405f 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -95,6 +95,7 @@
 %token F_GAUGE
 %token F_IDENTIFIER
 %token F_IF
+%token F_IMPORT
 %token F_INHERIT
 %token F_INLINE
 %token F_INT_ID
@@ -155,7 +156,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.17 1997/01/16 05:00:44 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.18 1997/01/19 09:08:00 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -303,6 +304,7 @@ void fix_comp_stack(int sp)
 %type <n> idents
 %type <n> lambda
 %type <n> local_name_list
+%type <n> low_idents
 %type <n> lvalue
 %type <n> lvalue_list
 %type <n> m_expr_list
@@ -359,41 +361,14 @@ program_ref: string_constant
   | idents
   {
     push_string(make_shared_string(""));
-    if(!$1)
+    resolv_constant($1);
+    if(sp[-1].type != T_PROGRAM)
     {
+      yyerror("Illegal program identifier");
+      pop_stack();
       push_int(0);
-    }else{
-      switch($1->token)
-      {
-      case F_CONSTANT:
-        if($1->u.sval.type == T_PROGRAM)
-        {
-	  push_svalue(& $1->u.sval);
-	}else{
-	  yyerror("Illegal program identifier");
-	  push_int(0);
-	}
-	break;
-	
-      case F_IDENTIFIER:
-      {
-	struct identifier *i;
-	setup_fake_program();
-	i=ID_FROM_INT(& fake_program, $1->u.number);
-	
-	if(IDENTIFIER_IS_CONSTANT(i->flags))
-	{
-	  push_svalue(PROG_FROM_INT(&fake_program, $1->u.number)->constants +
-		      i->func.offset);
-	}else{
-	  yyerror("Illegal program identifier");
-	  push_int(0);
-	}
-	break;
-      }
-      }
-      free_node($1);
     }
+    free_node($1);
   }
   ;
           
@@ -411,6 +386,15 @@ inheritance: modifiers F_INHERIT program_ref optional_rename_inherit ';'
   }
   ;
 
+import: modifiers F_IMPORT idents ';'
+  {
+    resolv_constant($3);
+    free_node($3);
+    use_module(sp-1);
+    sp--;
+  }
+  ;
+
 constant_name: F_IDENTIFIER '=' expr0
   {
     int tmp;
@@ -555,6 +539,7 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')'
   }
   | modifiers type_or_error name_list ';' {}
   | inheritance {}
+  | import {}
   | constant {}
   | class { free_node($1); }
   | error 
@@ -1147,7 +1132,16 @@ expr4: string
   }
   ;
 
-idents: F_IDENTIFIER
+idents: low_idents
+  | idents '.' F_IDENTIFIER
+  {
+    $$=index_node($1, $3);
+    free_node($1);
+    free_string($3);
+  }
+  ;
+
+low_idents: F_IDENTIFIER
   {
     int i;
     struct efun *f;
@@ -1156,10 +1150,13 @@ 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 if((f=lookup_efun($1))){
       $$=mkconstantsvaluenode(&f->function);
     }else{
-	$$=0;
+      $$=0;
       if( get_master() )
       {
 	reference_shared_string($1);
@@ -1171,10 +1168,14 @@ idents: F_IDENTIFIER
 	if(throw_value.type == T_STRING)
 	{
 	  my_yyerror("%s",throw_value.u.string->str);
+	}
+	else if(IS_ZERO(sp-1) && sp[-1].subtype==1)
+	{
+	  my_yyerror("'%s' undefined.", $1->str);
 	}else{
 	  $$=mkconstantsvaluenode(sp-1);
-	  pop_stack();
 	}
+	pop_stack();
       }else{
 	my_yyerror("'%s' undefined.", $1->str);
       }
diff --git a/src/las.c b/src/las.c
index d49cf595cb91d26c301c5b745848c41d8f30e144..49a8ab05f381f3f9fc5c76c7de9d625d46097c6b 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.11 1997/01/16 05:00:45 hubbe Exp $");
+RCSID("$Id: las.c,v 1.12 1997/01/19 09:08:00 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -445,6 +445,71 @@ node *mkcastnode(struct pike_string *type,node *n)
   return res;
 }
 
+void resolv_constant(node *n)
+{
+  struct identifier *i;
+  if(!n)
+  {
+    push_int(0);
+  }else{
+    switch(n->token)
+    {
+    case F_CONSTANT:
+      push_svalue(& n->u.sval);
+      break;
+
+    case F_IDENTIFIER:
+      setup_fake_program();
+      i=ID_FROM_INT(& fake_program, n->u.number);
+	
+      if(IDENTIFIER_IS_CONSTANT(i->flags))
+      {
+	push_svalue(PROG_FROM_INT(&fake_program, n->u.number)->constants +
+		    i->func.offset);
+      }else{
+	yyerror("Identifier is not a constant");
+	push_int(0);
+      }
+      break;
+
+    case F_LOCAL:
+	yyerror("Expected constant, got local variable");
+	push_int(0);
+
+    case F_GLOBAL:
+	yyerror("Expected constant, got global variable");
+	push_int(0);
+    }
+  }
+}
+
+node *index_node(node *n, struct pike_string * id)
+{
+  node *ret;
+  JMP_BUF tmp;
+  if(SETJMP(tmp))
+  {
+    ONERROR tmp;
+    SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
+    assign_svalue_no_free(sp++, & throw_value);
+    APPLY_MASTER("handle_error", 1);
+    pop_stack();
+    UNSET_ONERROR(tmp);
+    
+    yyerror("Couldn't index module.");
+    push_svalue(0);
+  }else{
+    resolv_constant(n);
+    push_string(id);
+    f_index(2);
+  }
+  UNSETJMP(tmp);
+  ret=mkconstantsvaluenode(sp-1);
+  pop_stack();
+  return ret;
+}
+
+
 int node_is_eq(node *a,node *b)
 {
   if(a == b) return 1;
diff --git a/src/las.h b/src/las.h
index 6d97e60d7b544b240c4a003d75c7a42615413914..6c85fe750b5b942373cd8a8b3a9762361b63fac2 100644
--- a/src/las.h
+++ b/src/las.h
@@ -92,6 +92,8 @@ node *mkopernode(char *oper_id, node *arg1, node *arg2);
 node *mklocalnode(int var);
 node *mkidentifiernode(int i);
 node *mkcastnode(struct pike_string *type,node *n);
+void resolv_constant(node *n);
+node *index_node(node *n, struct pike_string * id);
 int node_is_eq(node *a,node *b);
 node *mkconstantsvaluenode(struct svalue *s);
 node *mkliteralsvaluenode(struct svalue *s);
diff --git a/src/lex.c b/src/lex.c
index 50b25aa5a5c8ececc7ac2fee9125725c4f56f2e3..e6aa0075cd9d928e7d3707e98eea1b64966d7aec 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.11 1997/01/18 04:43:50 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.12 1997/01/19 09:08:01 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -101,11 +101,10 @@ struct keyword reserved_words[] =
 { "case",	F_CASE, },
 { "catch",	F_CATCH, },
 { "class",	F_CLASS, },
-{ "continue",	F_CONTINUE, },
 { "constant",	F_CONSTANT, },
+{ "continue",	F_CONTINUE, },
 { "default",	F_DEFAULT, },
 { "do",		F_DO, },
-{ "predef",	F_PREDEF, },
 { "else",	F_ELSE, },
 { "float",	F_FLOAT_ID, },
 { "for",	F_FOR, },
@@ -113,15 +112,17 @@ struct keyword reserved_words[] =
 { "function",	F_FUNCTION_ID, },
 { "gauge",	F_GAUGE, },
 { "if",		F_IF, },
+{ "import",	F_IMPORT, },
 { "inherit",	F_INHERIT, },
 { "inline",	F_INLINE, },
 { "int",	F_INT_ID, },
 { "lambda",	F_LAMBDA, },
-{ "multiset",	F_MULTISET_ID, },
 { "mapping",	F_MAPPING_ID, },
 { "mixed",	F_MIXED_ID, },
+{ "multiset",	F_MULTISET_ID, },
 { "nomask",	F_NO_MASK, },
 { "object",	F_OBJECT_ID, },
+{ "predef",	F_PREDEF, },
 { "private",	F_PRIVATE, },
 { "program",	F_PROGRAM_ID, },
 { "protected",	F_PROTECTED, },
diff --git a/src/object.c b/src/object.c
index a12a3c81f4e8ea823d5dd667e8dfa23b7be6ffb5..07c1a9650b01edb7868ba03c42290a5d90efd40a 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.10 1997/01/18 21:34:33 hubbe Exp $");
+RCSID("$Id: object.c,v 1.11 1997/01/19 09:08:02 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -684,14 +684,11 @@ int object_equal_p(struct object *a, struct object *b, struct processing *p)
 void cleanup_objects()
 {
   struct object *o, *next;
-  o=first_object;
-  while(o->next) o=o->next;
-  
-  for(;o;o=next)
+  for(o=first_object;o;o=next)
   {
     o->refs++;
     destruct(o);
-    next=o->prev;
+    next=o->next;
     free_object(o);
   }
   destruct_objects_to_destruct();
diff --git a/src/program.c b/src/program.c
index 0a70679f0d17f641f5b5fadaf9b62c8e68d782c3..72c2eeda446c95e0df25fbbd90ff79a846010ec2 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.12 1997/01/16 05:00:48 hubbe Exp $");
+RCSID("$Id: program.c,v 1.13 1997/01/19 09:08:03 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -77,16 +77,47 @@ static INT32 last_line = 0;
 static INT32 last_pc = 0;
 static struct pike_string *last_file = 0;
 dynamic_buffer inherit_names;
+dynamic_buffer used_modules;
 
-#define HASH_ID_IS_LOCAL 1
-#define HASH_ID_IS_GLOBAL 2
-#define HASH_ID_IS_FUNCTION 4
-struct id_hash_entry
+void use_module(struct svalue *s)
 {
-  struct hash_entry link;
-  INT16 id;
-  INT16 flags;
-};
+  low_my_binary_strcat((char *)s,sizeof(struct svalue *),&used_modules);
+}
+
+
+int find_module_identifier(struct pike_string *ident)
+{
+  JMP_BUF tmp;
+  
+  if(SETJMP(tmp))
+  {
+    ONERROR tmp;
+    SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
+    assign_svalue_no_free(sp++, & throw_value);
+    APPLY_MASTER("handle_error", 1);
+    pop_stack();
+    UNSET_ONERROR(tmp);
+    yyerror("Couldn't index module.");
+  }else{
+    struct svalue *modules=(struct svalue *)used_modules.s.str;
+    int e=used_modules.s.len / sizeof(struct svalue *);
+
+    while(--e>=0)
+    {
+      push_svalue(modules+e);
+      push_string(ident);
+      f_index(2);
+      
+      if(!IS_ZERO(sp-1) || sp[-1].subtype != 1)
+      {
+	UNSETJMP(tmp);
+	return 1;
+      }
+    }
+  }
+  UNSETJMP(tmp);
+  return 0;
+}
 
 #define SETUP(X,Y,TYPE,AREA) \
    fake_program.X=(TYPE *)areas[AREA].s.str; \
@@ -138,6 +169,7 @@ void start_new_program()
 
   for(e=0; e<NUM_AREAS; e++) low_reinit_buf(areas + e);
   low_reinit_buf(& inherit_names);
+  low_reinit_buf(& used_modules);
   fake_program.id = ++current_program_id;
 
   inherit.prog=&fake_program;
@@ -146,7 +178,7 @@ void start_new_program()
   inherit.storage_offset=0;
   add_to_mem_block(A_INHERITS,(char *)&inherit,sizeof inherit);
   name=make_shared_string("this");
-  low_my_binary_strcat((char *)&name,sizeof(name),&inherit_names);
+  low_my_binary_strcat((char *)&name,sizeof(name), &inherit_names);
   num_parse_error=0;
 
   local_variables=ALLOC_STRUCT(locals);
@@ -227,25 +259,61 @@ void dump_program_desc(struct program *p)
 }
 #endif
 
-/*
- * Something went wrong.
- * toss resources of program we were building
- */
-void toss_current_program()
+static void toss_compilation_resources()
 {
   struct pike_string **names;
+  struct svalue *modules;
   int e;
-  setup_fake_program();
 
-  low_free_program(&fake_program);
- 
-  for (e=0; e<NUM_AREAS; e++)
-    toss_buffer(areas+e);
+  for (e=0; e<NUM_AREAS; e++) toss_buffer(areas+e);
 
   names=(struct pike_string **)inherit_names.s.str;
   e=inherit_names.s.len / sizeof(struct pike_string *);
-  for(e--;e>=0;e--) if(names[e]) free_string(names[e]);
+  while(--e>=0) if(names[e]) free_string(names[e]);
   toss_buffer(& inherit_names);
+
+  modules=(struct svalue *)used_modules.s.str;
+  e=used_modules.s.len / sizeof(struct svalue *);
+  while(--e>=0) free_svalue(modules+e);
+  toss_buffer(& used_modules);
+
+  /* Clean up */
+  while(local_variables)
+  {
+    struct locals *l;
+    for(e=0;e<local_variables->current_number_of_locals;e++)
+    {
+      free_string(local_variables->variable[e].name);
+      free_string(local_variables->variable[e].type);
+    }
+  
+    if(local_variables->current_type)
+      free_string(local_variables->current_type);
+
+    if(local_variables->current_return_type)
+      free_string(local_variables->current_return_type);
+
+    l=local_variables->next;
+    free((char *)local_variables);
+    local_variables=l;
+  }
+
+  if(last_file)
+  {
+    free_string(last_file);
+    last_file=0;
+  }
+}
+
+/*
+ * Something went wrong.
+ * toss resources of program we were building
+ */
+void toss_current_program()
+{
+  setup_fake_program();
+  low_free_program(&fake_program);
+  toss_compilation_resources();
 }
 
 #ifdef DEBUG
@@ -476,15 +544,9 @@ struct program *end_program()
 
     p+=MY_ALIGN(prog->num_identifier_indexes*sizeof(unsigned short));
 
-    for (i=0; i<NUM_AREAS; i++) toss_buffer(areas+i);
+    toss_compilation_resources();
 
     prog->inherits[0].prog=prog;
-
-    names=(struct pike_string **)inherit_names.s.str;
-    e=inherit_names.s.len / sizeof(struct pike_string *);
-    for(e--;e>=0;e--) if(names[e]) free_string(names[e]);
-    toss_buffer(& inherit_names);
-
     prog->prev=0;
     if(prog->next=first_program)
       first_program->prev=prog;
@@ -502,34 +564,6 @@ struct program *end_program()
     GC_ALLOC();
   }
 
-  /* Clean up */
-  while(local_variables)
-  {
-    int e;
-    struct locals *l;
-    for(e=0;e<local_variables->current_number_of_locals;e++)
-    {
-      free_string(local_variables->variable[e].name);
-      free_string(local_variables->variable[e].type);
-    }
-  
-    if(local_variables->current_type)
-      free_string(local_variables->current_type);
-
-    if(local_variables->current_return_type)
-      free_string(local_variables->current_return_type);
-
-    l=local_variables->next;
-    free((char *)local_variables);
-    local_variables=l;
-  }
-  
-  if(last_file)
-  {
-    free_string(last_file);
-    last_file=0;
-  }
-
 #define PROGRAM_STATE
 #define POP
 #include "compilation.h"
diff --git a/src/program.h b/src/program.h
index 93f8f869f0afae026ccd1bb37bafb59b05573612..115911a3155a610e32a45efd3bf8c0b6efc5227c 100644
--- a/src/program.h
+++ b/src/program.h
@@ -182,7 +182,8 @@ extern struct object fake_object;
 extern struct program fake_program;
 
 /* Prototypes begin here */
-struct id_hash_entry;
+void use_module(struct svalue *s);
+int find_module_identifier(struct pike_string *ident);
 void setup_fake_program();
 void start_new_program();
 void really_free_program(struct program *p);
diff --git a/src/version.c b/src/version.c
index 907297e4ef923d6e1e39271148cf1afc0a4711be..41fd1f63e4dffe4eb489999f60066c539c829f8e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -6,5 +6,5 @@
 void f_version(INT32 args)
 {
   pop_n_elems(args);
-  push_text("Pike v0.4pl3");
+  push_text("Pike v0.4pl4");
 }