diff --git a/src/ChangeLog b/src/ChangeLog
index 7c461f6abe5a59920c5f86edf11fb717e20bebba..e94c664e5ac1997282b425afc69218f8f7d4719f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,16 @@
+Wed Jan 21 11:37:44 1998  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
+
+	* objects can now access variables in their parents
+	* Compiler is now two-pass -> no more prototypes
+	* New efun: cpp()
+	* you can now access a class name from inside itself
+	* fork() now returns an object
+	* new option to pike: -w
+	* keyword varargs removed
+	* inline keyword now enforced
+	* New functions: Stdio.cp(), Process.create_process()
+	* Lot of modifications for NT
+
 Thu Jan  1 16:56:09 1998  Fredrik Hubinette  <hubbe@cytocin.hubbe.net>
 
 	* threads.c: new methods added: wait and status
diff --git a/src/acconfig.h b/src/acconfig.h
index a5bc2a68a08e0cf00f332a4d56ec891cce4bcb82..875f66a88ec7cf9dea0946b0ad912183efb7fb3f 100644
--- a/src/acconfig.h
+++ b/src/acconfig.h
@@ -12,6 +12,9 @@
 /* Define this if you want run time self tests */
 #undef DEBUG
 
+/* Define this if you want malloc debugging */
+#undef DEBUG_MALLOC
+
 @TOP@
 
 /* Enable profiling */
diff --git a/src/array.c b/src/array.c
index 5057bda103c0645dc7184a667141e7b0990325ba..577aafe4b570c5d4409da803429950467a436908 100644
--- a/src/array.c
+++ b/src/array.c
@@ -1560,6 +1560,12 @@ void zap_all_arrays(void)
   a=&empty_array;
   do
   {
+
+#if defined(DEBUG) && defined(DEBUG_MALLOC)
+    if(verbose_debug_exit)
+      debug_dump_array(a);
+#endif
+    
     a->refs++;
     free_svalues(ITEM(a), a->size, a->type_field);
     a->size=0;
@@ -1572,6 +1578,7 @@ void zap_all_arrays(void)
   } while (a != & empty_array);
 }
 
+
 void count_memory_in_arrays(INT32 *num_, INT32 *size_)
 {
   INT32 num=0, size=0;
diff --git a/src/array.h b/src/array.h
index 009bccf099f1088f25fd22c0f82a000ae19f286f..1521461953d14a7de3bb187ea0fada213b2f191b 100644
--- a/src/array.h
+++ b/src/array.h
@@ -63,8 +63,8 @@ struct array *low_allocate_array(INT32 size,INT32 extra_space);
 void really_free_array(struct array *v);
 void array_index_no_free(struct svalue *s,struct array *v,INT32 index);
 void array_index(struct svalue *s,struct array *v,INT32 index);
-void simple_array_index(struct svalue *s,struct array *a,struct svalue *ind);
-void simple_array_index_no_free(struct svalue *s,struct array *a,struct svalue *ind);
+void simple_array_index_no_free(struct svalue *s,
+				struct array *a,struct svalue *ind);
 void array_free_index(struct array *v,INT32 index);
 void array_set_index(struct array *v,INT32 index, struct svalue *s);
 void simple_set_index(struct array *a,struct svalue *ind,struct svalue *s);
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 996623426614d38a22351924c690ad91fc9b2a67..ae891e48af4e102d671b7197742fff5b344d92ab 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.61 1998/01/15 17:54:14 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.62 1998/01/25 08:25:03 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -615,40 +615,17 @@ void f_throw(INT32 args)
   pike_throw();
 }
 
-static struct callback_list exit_callbacks;
-
-struct callback *add_exit_callback(callback_func call,
-				   void *arg,
-				   callback_func free_func)
-{
-  return add_to_callback(&exit_callbacks, call, arg, free_func);
-}
-
 void f_exit(INT32 args)
 {
-  ONERROR tmp;
-  int i;
   if(args < 1)
     error("Too few arguments to exit.\n");
 
   if(sp[-args].type != T_INT)
     error("Bad argument 1 to exit.\n");
 
-  i=sp[-args].u.integer;
-
-#ifdef _REENTRANT
-  if(num_threads>1) exit(i);
-#endif
-
-  SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
-
-  call_callback(&exit_callbacks, (void *)0);
-  free_callback(&exit_callbacks);
-
-  exit_modules();
-
-  UNSET_ONERROR(tmp);
-  exit(i);
+  assign_svalue(&throw_value, sp-args);
+  throw_severity=THROW_EXIT;
+  pike_throw();
 }
 
 void f_time(INT32 args)
diff --git a/src/builtin_functions.h b/src/builtin_functions.h
index f7385358f6721f3855f309fbc091a9afba6eee2b..b67145bb6f96cf67a20a5407671263468705f699 100644
--- a/src/builtin_functions.h
+++ b/src/builtin_functions.h
@@ -23,7 +23,6 @@ void f_random(INT32 args);
 void f_random_seed(INT32 args);
 void f_query_num_arg(INT32 args);
 void f_search(INT32 args);
-void f_call_function(INT32 args);
 void f_backtrace(INT32 args);
 void f_add_constant(INT32 args);
 void f_combine_path(INT32 args);
@@ -35,9 +34,6 @@ void f_allocate(INT32 args);
 void f_rusage(INT32 args);
 void f_this_object(INT32 args);
 void f_throw(INT32 args);
-struct callback *add_exit_callback(callback_func call,
-				   void *arg,
-				   callback_func free_func);
 void f_exit(INT32 args);
 void f_time(INT32 args);
 void f_crypt(INT32 args);
diff --git a/src/cpp.c b/src/cpp.c
index 56a29c2ba21246f014aab0dc6db94d39d53e6ba8..d220474a1aacd3642bc8c23d58a5e84ada4d81a0 100644
--- a/src/cpp.c
+++ b/src/cpp.c
@@ -1989,12 +1989,14 @@ void f_cpp(INT32 args)
   if(this.defines)
     free_hashtable(this.defines, free_one_define);
 
+  free_string(this.current_file);
+
   if(this.compile_errors)
   {
+    toss_buffer(&this.buf);
     error("Cpp() failed\n");
   }else{
     pop_n_elems(args);
-    free_string(this.current_file);
     push_string(low_free_buf(&this.buf));
   }
 }
@@ -2046,4 +2048,9 @@ void exit_cpp()
     pike_predefs=tmp->next;
     free((char *)tmp);
   }
+  free_string(defined_macro->link.s);
+  free((char *)defined_macro);
+
+  free_string(constant_macro->link.s);
+  free((char *)constant_macro);
 }
diff --git a/src/dmalloc.h b/src/dmalloc.h
new file mode 100644
index 0000000000000000000000000000000000000000..a62fcdf1bebc11b89acb0170ac2b431518bf8890
--- /dev/null
+++ b/src/dmalloc.h
@@ -0,0 +1,24 @@
+#ifdef DEBUG_MALLOC
+
+extern int verbose_debug_malloc;
+extern int verbose_debug_exit;
+#define main dbm_main
+extern void *debug_malloc(size_t, const char *, int);
+extern char *debug_xalloc(long, const char *, int);
+extern void *debug_calloc(size_t, size_t, const char *, int);
+extern void *debug_realloc(void *, size_t, const char *, int);
+extern void debug_free(void *, const char *, int);
+extern char *debug_strdup(const char *, const char *, int);
+void *debug_malloc_update_location(void *,const char *, int);
+#define malloc(x) debug_malloc((x), __FILE__, __LINE__)
+#define xalloc(x) debug_xalloc((x), __FILE__, __LINE__)
+#define calloc(x, y) debug_calloc((x), (y), __FILE__, __LINE__)
+#define realloc(x, y) debug_realloc((x), (y), __FILE__, __LINE__)
+#define free(x) debug_free((x), __FILE__, __LINE__)
+#define strdup(x) debug_strdup((x), __FILE__, __LINE__)
+#define DO_IF_DMALLOC(X) X
+#else
+#define DO_IF_DMALLOC(X)
+extern char *xalloc(long);
+#define debug_malloc_update_location(X,Y,Z) (X)
+#endif
diff --git a/src/docode.c b/src/docode.c
index 4110312c1cad4b1dc525c8f3938e87593a0eb15d..c92c110c06928bcea9c46b79cf2d33a4ccd20126 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.24 1998/01/13 22:56:42 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.25 1998/01/25 08:25:05 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "language.h"
@@ -807,7 +807,7 @@ static int do_docode2(node *n,int flags)
       if(current_switch_jumptable[e]==-1)
 	current_switch_jumptable[e]=current_switch_default;
 
-    sp[-1].u.array=order_array(sp[-1].u.array,order);
+    order_array(sp[-1].u.array,order);
 
     reorder((void *)(current_switch_jumptable+1),cases,sizeof(INT32)*2,order);
     free((char *)order);
diff --git a/src/dynamic_buffer.c b/src/dynamic_buffer.c
index be27f8ecc01893f4dc893e93fef77990637d641d..8efd3267539377d2c0b2ad0164a392393158633c 100644
--- a/src/dynamic_buffer.c
+++ b/src/dynamic_buffer.c
@@ -54,7 +54,7 @@ void low_my_binary_strcat(const char *b,INT32 l,dynamic_buffer *buf)
   MEMCPY(low_make_buf_space(l,buf),b,l);
 }
 
-void initialize_buf(dynamic_buffer *buf)
+void debug_initialize_buf(dynamic_buffer *buf)
 {
   buf->s.str=(char *)xalloc((buf->bufsize=BUFFER_BEGIN_SIZE));
   *(buf->s.str)=0;
diff --git a/src/dynamic_buffer.h b/src/dynamic_buffer.h
index 2858274a0a47367f536ec6c28868b27d03375681..d7917786222a153ce895526742fed26944691b0c 100644
--- a/src/dynamic_buffer.h
+++ b/src/dynamic_buffer.h
@@ -25,12 +25,12 @@ struct dynamic_buffer_s
 typedef struct dynamic_buffer_s dynamic_buffer;
 
 /* Prototypes begin here */
-char *low_make_buf_space(INT32 space,dynamic_buffer *buf);
+char *low_make_buf_space(INT32 space, dynamic_buffer *buf);
 void low_my_putchar(char b,dynamic_buffer *buf);
 void low_my_binary_strcat(const char *b,INT32 l,dynamic_buffer *buf);
-void initialize_buf(dynamic_buffer *buf);
+void debug_initialize_buf(dynamic_buffer *buf);
 void low_reinit_buf(dynamic_buffer *buf);
-void low_init_buf_with_string(string s,dynamic_buffer *buf);
+void low_init_buf_with_string(string s, dynamic_buffer *buf);
 string complex_free_buf(void);
 void toss_buffer(dynamic_buffer *buf);
 char *simple_free_buf(void);
@@ -45,4 +45,12 @@ void init_buf_with_string(string s);
 char *return_buf(void);
 /* Prototypes end here */
 
+#ifdef DEBUG_MALLOC
+#define initialize_buf(X) \
+  do { dynamic_buffer *b_=(X); debug_initialize_buf(b_); \
+   debug_malloc_update_location(b_->s.str,__FILE__,__LINE__); } while(0)
+#else
+#define initialize_buf debug_initialize_buf
+#endif
+
 #endif
diff --git a/src/error.c b/src/error.c
index 0f192049c253fa77cf0b613d4bbfd7c67c2001f6..c21871d1b9fb9ca9628596ffefce0f9093c4f294 100644
--- a/src/error.c
+++ b/src/error.c
@@ -24,12 +24,24 @@ JMP_BUF *init_recovery(JMP_BUF *r)
   r->mark_sp=mark_sp - mark_stack;
   r->previous=recoveries;
   r->onerror=0;
+  r->severity=THROW_ERROR;
   recoveries=r;
   return r;
 }
 
-void pike_throw(void) ATTRIBUTE((noreturn))
+void pike_throw() ATTRIBUTE((noreturn))
 {
+  while(recoveries && throw_severity > recoveries->severity)
+  {
+    while(recoveries->onerror)
+    {
+      (*recoveries->onerror->func)(recoveries->onerror->arg);
+      recoveries->onerror=recoveries->onerror->previous;
+    }
+    
+    recoveries=recoveries->previous;
+  }
+
   if(!recoveries)
     fatal("No error recovery context.\n");
 
@@ -63,6 +75,7 @@ void pike_throw(void) ATTRIBUTE((noreturn))
 }
 
 struct svalue throw_value = { T_INT };
+int throw_severity;
 
 void va_error(char *fmt, va_list args) ATTRIBUTE((noreturn))
 {
@@ -98,6 +111,7 @@ void va_error(char *fmt, va_list args) ATTRIBUTE((noreturn))
   free_svalue(& throw_value);
   sp--;
   throw_value = *sp;
+  throw_severity=THROW_ERROR;
 
   in_error=0;
   pike_throw();  /* Hope someone is catching, or we will be out of balls. */
diff --git a/src/error.h b/src/error.h
index 4ca1565d50b79bc9eb345d970e2047d8153f7784..9c275f159e912cbea3aee09819c8321871be05a2 100644
--- a/src/error.h
+++ b/src/error.h
@@ -25,6 +25,9 @@ typedef void (*error_call)(void *);
 struct frame;
 #endif
 
+#define THROW_ERROR 1
+#define THROW_EXIT 1000
+
 typedef struct ONERROR
 {
   struct ONERROR *previous;
@@ -39,11 +42,13 @@ typedef struct JMP_BUF
   struct frame *fp;
   INT32 sp;
   INT32 mark_sp;
+  INT32 severity;
   ONERROR *onerror;
 } JMP_BUF;
 
 extern JMP_BUF *recoveries;
 extern struct svalue throw_value;
+extern int throw_severity;
 
 #define SETJMP(X) setjmp((init_recovery(&X)->recovery))
 #define UNSETJMP(X) recoveries=X.previous;
diff --git a/src/fdlib.c b/src/fdlib.c
index f63504eaef51fb5a99a9ed0ef610f175043c30c4..bb7d1f88aa2399ee0bd7744c85485bb8becb04c8 100644
--- a/src/fdlib.c
+++ b/src/fdlib.c
@@ -7,7 +7,7 @@ long da_handle[MAX_OPEN_FILEDESCRIPTORS];
 int fd_type[MAX_OPEN_FILEDESCRIPTORS];
 int first_free_handle;
 
-#define FDDEBUG(X)
+#define FDDEBUG(X) X
 
 char *fd_info(int fd)
 {
@@ -185,6 +185,7 @@ FD fd_accept(FD fd, struct sockaddr *addr, int *addrlen)
   return new_fd;
 }
 
+
 #define SOCKFUN(NAME,X1,X2) \
 int PIKE_CONCAT(fd_,NAME) X1 { SOCKET ret; \
   FDDEBUG(fprintf(stderr, #NAME " on %d (%d)\n",fd,da_handle[fd])); \
@@ -215,7 +216,28 @@ int PIKE_CONCAT(fd_,NAME) X1 { SOCKET ret; \
 
 
 SOCKFUN2(bind, struct sockaddr *, int)
+#if 1
+int fd_connect (FD fd, struct sockaddr *a, int len)
+{
+  SOCKET ret;
+  FDDEBUG(fprintf(stderr, "connect on %d (%d)\n",fd,da_handle[fd])
+  for(ret=0;ret<len;ret++)
+    fprintf(stderr," %02x",((unsigned char *)a)[ret]);
+  fprintf(stderr,"\n");
+  )
+  if(fd_type[fd] != FD_SOCKET)
+  {
+    errno=ENOTSUPP;
+    return -1; 
+  } 
+  ret=connect((SOCKET)da_handle[fd],a,len); 
+  if(ret == SOCKET_ERROR) errno=WSAGetLastError(); 
+  FDDEBUG(fprintf(stderr, "connect returned %d (%d)\n",ret,errno)); 
+  return (int)ret; 
+}
+#else
 SOCKFUN2(connect, struct sockaddr *, int)
+#endif
 SOCKFUN4(getsockopt,int,int,void*,int*)
 SOCKFUN4(setsockopt,int,int,void*,int)
 SOCKFUN2(getsockname,struct sockaddr *,int *)
@@ -396,10 +418,12 @@ int fd_select(int fds, FD_SET *a, FD_SET *b, FD_SET *c, struct timeval *t)
 int fd_ioctl(FD fd, int cmd, void *data)
 {
   int ret;
+  FDEBUG(fprintf("ioctl(%d (%d,%d,%p)\n",fd,da_handle[fd],cmd,data))
   switch(fd_type[fd])
   {
     case FD_SOCKET:
       ret=ioctlsocket((SOCKET)da_handle[fd], cmd, data);
+      FDDEBUG(fprintf(stderr,"ioctlsocket returned %ld (%d)\n",ret,errno));
       if(ret==SOCKET_ERROR)
       {
 	errno=WSAGetLastError();
diff --git a/src/gc.c b/src/gc.c
index f96489e0c0e8da70b64f51874e37ac7d82910fd1..3f8567e938498805765e11cdac67c4b9af0b08d8 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -317,8 +317,11 @@ void describe_something(void *a, int t)
       fprintf(stderr,"**Program id: %ld\n",(long)(p->id));
       if(!p->num_linenumbers)
       {
+	int e;
 	fprintf(stderr,"**The program was written in C.\n");
-	break;
+	fprintf(stderr,"**identifiers:\n");
+	for(e=0;e<p->num_identifiers;e++)
+	  fprintf(stderr,"*** %s\n",p->identifiers[e].name->str);
       }
 
       for(pos=0;pos<(long)p->num_program && pos<100;pos++)
@@ -338,6 +341,11 @@ void describe_something(void *a, int t)
       debug_dump_array((struct array *)a);
       break;
 
+    case T_MAPPING:
+      fprintf(stderr,"**Describing mapping:\n");
+      debug_dump_mapping((struct mapping *)a);
+      break;
+
     case T_STRING:
     {
       struct pike_string *s=(struct pike_string *)a;
diff --git a/src/global.h b/src/global.h
index 50b9fb55721e6e9bb8a6562f6c1402d4c6d2675e..d5abb067c188aa88919b628388fe79796708abf2 100644
--- a/src/global.h
+++ b/src/global.h
@@ -155,6 +155,7 @@ char *alloca ();
 #endif
 
 #include "port.h"
+#include "dmalloc.h"
 
 
 #ifdef BUFSIZ
diff --git a/src/interpret.c b/src/interpret.c
index 8633eaeb29a0728862ef1d2444052be737764f25..1c645e071f96dc38af4ae7079fb24ea1ac2a39d1 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.60 1998/01/24 18:36:44 per Exp $");
+RCSID("$Id: interpret.c,v 1.61 1998/01/25 08:25:07 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -532,7 +532,6 @@ static int eval_instruction(unsigned char *pc)
       if((nonblock=query_nonblocking(2)))
 	set_nonblocking(2,0);
 
-
       file=get_line(pc-1,fp->context.prog,&linep);
       while((f=STRCHR(file,'/'))) file=f+1;
       fprintf(stderr,"- %s:%4ld:(%lx): %-25s %4ld %4ld\n",
@@ -624,31 +623,38 @@ static int eval_instruction(unsigned char *pc)
       {
 	struct inherit *inherit;
 	struct program *p;
-	INT32 id=GET_ARG();
-	struct object *o=fp->context.parent;
-	INT32 i=fp->context.parent_identifier;
+	struct object *o;
+	INT32 i,id=GET_ARG();
+
+	inherit=&fp->context;
+	
+	o=fp->current_object;
+
+	if(!o)
+	  error("Current object is destructed\n");
 	
 	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)
+	  if(inherit->parent_offset)
 	  {
 	    i=o->parent_identifier;
 	    o=o->parent;
+	    accumulator+=inherit->parent_offset-1;
 	  }else{
 	    i=inherit->parent_identifier;
 	    o=inherit->parent;
 	  }
+	  
+	  if(!o)
+	    error("Parent was lost during cloning.\n");
+	  
+	  if(!(p=o->prog))
+	    error("Attempting to access variable in destructed object\n");
+	  
+	  inherit=INHERIT_FROM_INT(p, i);
+	  
+	  if(!accumulator) break;
+	  --accumulator;
 	}
 
 	low_object_index_no_free(sp,
@@ -663,12 +669,27 @@ static int eval_instruction(unsigned char *pc)
       {
 	struct inherit *inherit;
 	struct program *p;
-	INT32 id=GET_ARG();
-	struct object *o=fp->context.parent;
-	INT32 i=fp->context.parent_identifier;
+	struct object *o;
+	INT32 i,id=GET_ARG();
+
+	inherit=&fp->context;
+	o=fp->current_object;
 	
+	if(!o)
+	  error("Current object is destructed\n");
+
 	while(1)
 	{
+	  if(inherit->parent_offset)
+	  {
+	    i=o->parent_identifier;
+	    o=o->parent;
+	    accumulator+=inherit->parent_offset-1;
+	  }else{
+	    i=inherit->parent_identifier;
+	    o=inherit->parent;
+	  }
+
 	  if(!o)
 	    error("Parent no longer exists\n");
 
@@ -679,15 +700,6 @@ static int eval_instruction(unsigned char *pc)
 
 	  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);
@@ -1563,7 +1575,6 @@ void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2)
       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;
   
diff --git a/src/language.yacc b/src/language.yacc
index 1e858ae3c0e9f9d91ebf2d31920a4b092c846b4b..dc141a3e9b866a895d5d9f3e9a50ce0e73e424b5 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -129,7 +129,6 @@
 %token F_SUB_EQ
 %token F_TYPEOF
 %token F_VAL_LVAL
-%token F_VARARGS 
 %token F_VOID_ID
 %token F_WHILE
 %token F_XOR_EQ
@@ -162,7 +161,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.53 1998/01/20 02:30:35 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.54 1998/01/25 08:25:08 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -280,7 +279,6 @@ int yylex(YYSTYPE *yylval);
 %type <number> F_STATIC
 %type <number> F_STRING_ID
 %type <number> F_SWITCH
-%type <number> F_VARARGS
 %type <number> F_VOID_ID
 %type <number> F_WHILE
 %type <number> arguments
@@ -345,6 +343,7 @@ int yylex(YYSTYPE *yylval);
 %type <n> unused2
 %type <n> while
 %type <n> optional_comma_expr
+%type <n> low_program_ref
 %%
 
 all: program;
@@ -368,7 +367,7 @@ optional_rename_inherit: ':' F_IDENTIFIER { $$=$2; }
   | { $$=0; }
   ;
 
-program_ref: string_constant
+low_program_ref: string_constant
   {
     ref_push_string($1);
     push_string($1);
@@ -377,60 +376,39 @@ program_ref: string_constant
 
     if(sp[-1].type != T_PROGRAM)
       my_yyerror("Couldn't cast string \"%s\" to program",$1->str);
+    $$=mksvaluenode(sp-1);
+    pop_stack();
   }
   | idents
   {
     if(last_identifier)
     {
-      push_string(last_identifier);
+      ref_push_string(last_identifier);
       last_identifier->refs++;
     }else{
       push_constant_text("");
     }
-    
-    resolv_constant($1);
-    switch(sp[-1].type)
-    {
-    case T_OBJECT:
-      if(!sp[-1].u.object->prog)
-      {
-	pop_stack();
-	push_int(0);
-      }else{
-	struct program *p=sp[-1].u.object->prog;
-	p->refs++;
-	pop_stack();
-	push_program(p);
-      }
-      break;
-
-    case T_FUNCTION:
-      if(program_from_function(sp-1))
-	break;
-
-    default:
-      yyerror("Illegal program identifier");
-      pop_stack();
-      push_int(0);
-      
-    case T_PROGRAM:
-      break;
-    }
+    $$=$1;
+  }
+  ;
 
-    free_node($1);
+program_ref: low_program_ref
+  {
+    resolv_program($1);    
   }
   ;
-          
-inheritance: modifiers F_INHERIT program_ref optional_rename_inherit ';'
+      
+inheritance: modifiers F_INHERIT low_program_ref optional_rename_inherit ';'
   {
     if(!(new_program->flags & PROGRAM_PASS_1_DONE))
     {
-      struct pike_string *s=sp[-2].u.string;
+      struct pike_string *s=sp[-1].u.string;
       if($4) s=$4;
-      do_inherit(sp-1,$1,s);
+      compiler_do_inherit($3,$1,s);
     }
     if($4) free_string($4);
-    pop_n_elems(2);
+    pop_n_elems(1);
+    free_node($3);
   }
   ;
 
@@ -544,11 +522,6 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER
     for(; e>=0; e--)
     {
       push_finished_type(compiler_frame->variable[e].type);
-      if($1 & ID_VARARGS)
-      {
-	push_type(T_VOID);
-	push_type(T_OR);
-      }
     }
     push_type(T_FUNCTION);
     
@@ -644,12 +617,11 @@ modifier: F_NO_MASK    { $$ = ID_NOMASK; }
   | F_STATIC     { $$ = ID_STATIC; }
   | F_PRIVATE    { $$ = ID_PRIVATE; }
   | F_PUBLIC     { $$ = ID_PUBLIC; }
-  | F_VARARGS    { $$ = ID_VARARGS; }
   | F_PROTECTED  { $$ = ID_PROTECTED; }
-  | F_INLINE     { $$ = ID_INLINE | ID_NOMASK; }
+  | F_INLINE     { $$ = ID_INLINE; }
   ;
 
-modifiers: modifier_list { $$=current_modifiers=$1; } ;
+modifiers: modifier_list { $$=current_modifiers=$1 | lex.pragmas; } ;
 
 modifier_list: /* empty */ { $$ = 0; }
   | modifier modifier_list { $$ = $1 | $2; }
@@ -892,7 +864,14 @@ lambda: F_LAMBDA
     
     fix_comp_stack($<number>2);
     
-    push_type(T_MIXED);
+
+    $4=mknode(F_ARG_LIST,$4,mknode(F_RETURN,mkintnode(0),0));
+    type=find_return_type($4);
+
+    if(type)
+      push_finished_type(type);
+    else
+      push_type(T_MIXED);
     
     e=$3-1;
     if(varargs)
@@ -919,7 +898,7 @@ lambda: F_LAMBDA
       name=make_shared_string(buf);
       
       f=dooptcode(name,
-		  mknode(F_ARG_LIST,$4,mknode(F_RETURN,mkintnode(0),0)),
+		  $4,
 		  type,
 		  ID_PRIVATE);
     }
@@ -1506,3 +1485,12 @@ int islocal(struct pike_string *str)
       return e;
   return -1;
 }
+
+void cleanup_compiler(void)
+{
+  if(last_identifier)
+  {
+    free_string(last_identifier);
+    last_identifier=0;
+  }
+}
diff --git a/src/las.c b/src/las.c
index 2b8a6092c3afc48727eee184d32f276e2d365e72..b626c7b93b9c70c45f1f801a935ba367d5660a4b 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.42 1998/01/19 18:38:46 hubbe Exp $");
+RCSID("$Id: las.c,v 1.43 1998/01/25 08:25:08 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -124,6 +124,30 @@ INT32 count_args(node *n)
   }
 }
 
+struct pike_string *find_return_type(node *n)
+{
+  struct pike_string *a,*b;
+
+  if(!n) return 0;
+  if(!(n->tree_info & OPT_RETURN)) return 0;
+  if(car_is_node(n))
+    a=find_return_type(CAR(n));
+  else
+    a=0;
+
+  if(cdr_is_node(n))
+    b=find_return_type(CDR(n));
+  else
+    b=0;
+
+  if(a)
+  {
+    if(b && a!=b) return mixed_type_string;
+    return a;
+  }
+  return b;
+}
+
 
 #define NODES 256
 
@@ -535,6 +559,37 @@ void resolv_constant(node *n)
   }
 }
 
+void resolv_program(node *n)
+{
+  resolv_constant(n);
+  switch(sp[-1].type)
+  {
+    case T_OBJECT:
+      if(!sp[-1].u.object->prog)
+      {
+	pop_stack();
+	push_int(0);
+      }else{
+	f_object_program(1);
+      }
+      break;
+      
+    case T_FUNCTION:
+      if(program_from_function(sp-1))
+	break;
+      
+    default:
+      yyerror("Illegal program identifier");
+      pop_stack();
+      push_int(0);
+      
+    case T_PROGRAM:
+      break;
+  }
+}
+
+
+
 node *index_node(node *n, struct pike_string * id)
 {
   node *ret;
diff --git a/src/las.h b/src/las.h
index 49194b5e5560dc4883162b8ac1478d66f18b7470..c6ca978291c4874cd483e9ca6178f23f120e0fa3 100644
--- a/src/las.h
+++ b/src/las.h
@@ -61,8 +61,9 @@ struct compiler_frame
 int car_is_node(node *n);
 int cdr_is_node(node *n);
 INT32 count_args(node *n);
+struct pike_string *find_return_type(node *n);
 struct node_chunk;
-void free_all_nodes(void);
+void free_all_nodes();
 void free_node(node *n);
 node *mknode(short token,node *a,node *b);
 node *mkstrnode(struct pike_string *str);
@@ -78,6 +79,7 @@ node *mkexternalnode(int level,
 		     struct identifier *id);
 node *mkcastnode(struct pike_string *type,node *n);
 void resolv_constant(node *n);
+void resolv_program(node *n);
 node *index_node(node *n, struct pike_string * id);
 int node_is_eq(node *a,node *b);
 node *mkconstantsvaluenode(struct svalue *s);
diff --git a/src/lex.c b/src/lex.c
index 5ded11d4a5d4153bc0adaa32d521f72e0a2ca6eb..c62b6ab02bb1c0fb885a20959e44077c5d010bfe 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.39 1998/01/16 23:02:39 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.40 1998/01/25 08:25:09 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -502,7 +502,11 @@ static int yylex2(YYSTYPE *yylval)
 	  READBUF(C!='\n');
 	  if (strcmp(buf, "all_inline") == 0)
 	  {
-	    lex.pragmas |= PRAGMA_ALL_INLINE;
+	    lex.pragmas |= ID_INLINE;
+	  }
+	  else if (strcmp(buf, "all_nomask") == 0)
+	  {
+	    lex.pragmas |= ID_NOMASK;
 	  }
 	  break;
 	}
@@ -843,9 +847,6 @@ static int yylex2(YYSTYPE *yylval)
 	  case TWO_CHAR('t','y'):
 	    if(ISWORD("typeof")) return F_TYPEOF;
 	  break;
-	  case TWO_CHAR('v','a'):
-	    if(ISWORD("varargs")) return F_VARARGS;
-	  break;
 	  case TWO_CHAR('v','o'):
 	    if(ISWORD("void")) return F_VOID_ID;
 	  break;
diff --git a/src/lex.h b/src/lex.h
index 3432fc4016acd8f17b26aecabc18a40c038c4bdb..15a38a36dd1e58c394c6940db3df0b991405e56d 100644
--- a/src/lex.h
+++ b/src/lex.h
@@ -49,8 +49,6 @@ struct hash_entry;
 struct hash_table;
 #endif
 
-#define PRAGMA_ALL_INLINE 1
-
 struct lex
 {
   char *pos;
diff --git a/src/main.c b/src/main.c
index d4660242d34b19abbfa326dee53d819e97014d15..baf74afd7c682fab7bc930d34eb12a229d667bf7 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.34 1998/01/16 22:33:06 grubba Exp $");
+RCSID("$Id: main.c,v 1.35 1998/01/25 08:25:10 hubbe Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -22,6 +22,7 @@ RCSID("$Id: main.c,v 1.34 1998/01/16 22:33:06 grubba Exp $");
 #include "threads.h"
 #include "dynamic_load.h"
 #include "gc.h"
+#include "multiset.h"
 #include "mapping.h"
 #include "cpp.h"
 
@@ -58,10 +59,19 @@ struct callback *add_post_master_callback(callback_func call,
 }
 
 
+static struct callback_list exit_callbacks;
+
+struct callback *add_exit_callback(callback_func call,
+				   void *arg,
+				   callback_func free_func)
+{
+  return add_to_callback(&exit_callbacks, call, arg, free_func);
+}
+
 int main(int argc, char **argv)
 {
   JMP_BUF back;
-  int e, num;
+  int e, num, do_backend;
   char *p;
   struct array *a;
 #ifdef DECLARE_ENVIRON
@@ -268,28 +278,41 @@ int main(int argc, char **argv)
 
   if(SETJMP(back))
   {
-    ONERROR tmp;
-    SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
-    assign_svalue_no_free(sp, & throw_value);
-    sp++;
-    APPLY_MASTER("handle_error", 1);
+    if(throw_severity == THROW_EXIT)
+    {
+      num=throw_value.u.integer;
+    }else{
+      ONERROR tmp;
+      SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
+      assign_svalue_no_free(sp, & throw_value);
+      sp++;
+      APPLY_MASTER("handle_error", 1);
+      pop_stack();
+      UNSET_ONERROR(tmp);
+      num=10;
+    }
+  }else{
+    back.severity=THROW_EXIT;
+    
+    apply(master(),"_main",2);
     pop_stack();
-    UNSET_ONERROR(tmp);
-    exit(10);
+    
+    backend();
+    num=0;
   }
-
-  apply(master(),"_main",2);
-  pop_stack();
-
   UNSETJMP(back);
 
-  backend();
+  do_exit(num);
+}
+
+void do_exit(int num)
+{
+  call_callback(&exit_callbacks, (void *)0);
+  free_callback(&exit_callbacks);
 
-  push_int(0);
-  f_exit(1);
+  exit_modules();
 
-  /* NOT REACHED */
-  return(-1);	/* To avoid warnings. */
+  exit(num);
 }
 
 
@@ -315,6 +338,7 @@ void low_exit_main(void)
   void cleanup_added_efuns(void);
   void cleanup_pike_types(void);
   void cleanup_program(void);
+  void cleanup_compiler(void);
 
   th_cleanup();
   exit_dynamic_load();
@@ -325,13 +349,82 @@ void low_exit_main(void)
   cleanup_added_efuns();
   cleanup_pike_types();
   cleanup_program();
+  cleanup_compiler();
 
   do_gc();
 
   cleanup_callbacks();
+#if defined(DEBUG) && defined(DEBUG_MALLOC)
+  if(verbose_debug_exit)
+  {
+    INT32 num,size,recount=0;
+
+    count_memory_in_arrays(&num, &size);
+    if(num || size)
+    {
+      recount++;
+      fprintf(stderr,"Arrays left: %d (%d bytes) (zapped)\n",num,size);
+    }
+
+    zap_all_arrays();
+
+    count_memory_in_mappings(&num, &size);
+    if(num || size)
+    {
+      recount++;
+      fprintf(stderr,"Mappings left: %d (%d bytes) (zapped)\n",num,size);
+    }
+
+    zap_all_mappings();
+
+    count_memory_in_multisets(&num, &size);
+    if(num || size)
+      fprintf(stderr,"Multisets left: %d (%d bytes)\n",num,size);
+
+
+    if(recount)
+    {
+      fprintf(stderr,"Garbage collecting..\n");
+      do_gc();
+      
+      count_memory_in_arrays(&num, &size);
+      fprintf(stderr,"Arrays left: %d (%d bytes)\n",num,size);
+      count_memory_in_mappings(&num, &size);
+      fprintf(stderr,"Mappings left: %d (%d bytes)\n",num,size);
+      count_memory_in_multisets(&num, &size);
+      fprintf(stderr,"Multisets left: %d (%d bytes)\n",num,size);
+    }
+    
+
+    count_memory_in_programs(&num, &size);
+    if(num || size)
+      fprintf(stderr,"Programs left: %d (%d bytes)\n",num,size);
+
+    {
+      struct program *p;
+      for(p=first_program;p;p=p->next)
+      {
+	describe_something(p, T_PROGRAM);
+      }
+    }
+
+
+    count_memory_in_objects(&num, &size);
+    if(num || size)
+      fprintf(stderr,"Objects left: %d (%d bytes)\n",num,size);
+
+    count_memory_in_strings(&num, &size);
+    if(num || size)
+      fprintf(stderr,"Strings left: %d (%d bytes) (zapped)\n",num,size);
+
+    cleanup_shared_string_table();
+  }
+#else
+
   zap_all_arrays();
   zap_all_mappings();
 
   cleanup_shared_string_table();
+#endif
 }
 
diff --git a/src/main.h b/src/main.h
index d9362f9734d7b9f4eb7f7be4622aae1fbebc2c94..64e65a99271217f3f1df7b79e001d8e864c0068b 100644
--- a/src/main.h
+++ b/src/main.h
@@ -14,7 +14,11 @@ extern int d_flag, t_flag, a_flag, l_flag, c_flag, p_flag;
 struct callback *add_post_master_callback(callback_func call,
 					  void *arg,
 					  callback_func free_func);
-void main(int argc, char **argv, char **env);
+struct callback *add_exit_callback(callback_func call,
+				   void *arg,
+				   callback_func free_func);
+int main(int argc, char **argv);
+void do_exit(int num);
 void low_init_main(void);
 void exit_main(void);
 void init_main(void);
diff --git a/src/mapping.c b/src/mapping.c
index 62066d19ea553095308cc9b65ded44bebfa0a981..226ccc7f59f1330193b94ca10f264ec67c8deb0d 100644
--- a/src/mapping.c
+++ b/src/mapping.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: mapping.c,v 1.26 1998/01/13 01:51:28 grubba Exp $");
+RCSID("$Id: mapping.c,v 1.27 1998/01/25 08:25:10 hubbe Exp $");
 #include "main.h"
 #include "object.h"
 #include "mapping.h"
@@ -624,17 +624,23 @@ struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op)
 
   ai=mapping_indices(a);
   av=mapping_values(a);
-  zipper=get_set_order(ai);
-  order_array(ai, zipper);
-  order_array(av, zipper);
-  free((char *)zipper);
+  if(ai->size > 1)
+  {
+    zipper=get_set_order(ai);
+    order_array(ai, zipper);
+    order_array(av, zipper);
+    free((char *)zipper);
+  }
 
   bi=mapping_indices(b);
   bv=mapping_values(b);
-  zipper=get_set_order(bi);
-  order_array(bi, zipper);
-  order_array(bv, zipper);
-  free((char *)zipper);
+  if(bi->size > 1)
+  {
+    zipper=get_set_order(bi);
+    order_array(bi, zipper);
+    order_array(bv, zipper);
+    free((char *)zipper);
+  }
 
   zipper=merge(ai,bi,op);
 
@@ -714,7 +720,7 @@ int mapping_equal_p(struct mapping *a, struct mapping *b, struct processing *p)
 void describe_mapping(struct mapping *m,struct processing *p,int indent)
 {
   struct processing doing;
-  INT32 e,d;
+  INT32 e,d,q;
   struct keypair *k;
   char buf[40];
 
@@ -739,15 +745,16 @@ void describe_mapping(struct mapping *m,struct processing *p,int indent)
   sprintf(buf,"([ /* %ld elements */\n",(long) m->size);
   my_strcat(buf);
 
-  d=0;
+  q=0;
 
   LOOP(m)
   {
-    if(d)
+    if(q)
     {
-      my_strcat(",\n");
+      my_putchar(',');
+      my_putchar('\n');
     } else {
-      d=1;
+      q=1;
     }
     for(d=0; d<indent; d++) my_putchar(' ');
     describe_svalue(& k->ind, indent+2, p);
@@ -938,9 +945,6 @@ void check_mapping(struct mapping *m)
   if(m->size > (m->hashsize + 3) * AVG_LINK_LENGTH)
     fatal("Pretty mean hashtable there buster!.\n");
   
-  if(m->size < (m->hashsize - 3) * MIN_LINK_LENGTH)
-    fatal("Hashsize is too small for mapping.\n");
-  
   if(m->size > 0 && (!m->ind_types || !m->val_types))
     fatal("Mapping type fields are... wrong.\n");
 
@@ -1065,6 +1069,37 @@ void gc_free_all_unreferenced_mappings(void)
   }
 }
 
+#ifdef DEBUG
+
+void simple_describe_mapping(struct mapping *m)
+{
+  char *s;
+  init_buf();
+  describe_mapping(m,0,2);
+  s=simple_free_buf();
+  fprintf(stderr,"%s\n",s);
+  free(s);
+}
+
+
+void debug_dump_mapping(struct mapping *m)
+{
+  fprintf(stderr,"Refs=%d, next=%p, prev=%p, size=%d, hashsize=%d\n",
+	  m->refs,
+	  m->next,
+	  m->prev,
+	  m->size,
+	  m->hashsize);
+  fprintf(stderr,"Indices type field = ");
+  debug_dump_type_field(m->ind_types);
+  fprintf(stderr,"\n");
+  fprintf(stderr,"Values type field = ");
+  debug_dump_type_field(m->val_types);
+  fprintf(stderr,"\n");
+  simple_describe_mapping(m);
+}
+#endif
+
 void zap_all_mappings(void)
 {
   INT32 e;
@@ -1075,6 +1110,11 @@ void zap_all_mappings(void)
   {
     m->refs++;
 
+#if defined(DEBUG) && defined(DEBUG_MALLOC)
+    if(verbose_debug_exit)
+      debug_dump_mapping(m);
+#endif
+
     for(e=0;e<m->hashsize;e++)
     {
       while((k=m->hash[e]))
diff --git a/src/mapping.h b/src/mapping.h
index 4efb98b5ac8301a0ce01828912fa3aa074cd8dcc..e077b9b6e55e0ab2c73b37b2aba0844c4198a19e 100644
--- a/src/mapping.h
+++ b/src/mapping.h
@@ -72,6 +72,8 @@ void gc_mark_mapping_as_referenced(struct mapping *m);
 void gc_check_all_mappings(void);
 void gc_mark_all_mappings(void);
 void gc_free_all_unreferenced_mappings(void);
+void simple_describe_mapping(struct mapping *m);
+void debug_dump_mapping(struct mapping *m);
 void zap_all_mappings(void);
 void count_memory_in_mappings(INT32 *num_, INT32 *size_);
 /* Prototypes end here */
diff --git a/src/module.c b/src/module.c
index 24a282a519594e24de15af4144a8cd01b8b557df..0814f40b2a0848c72363c7de72526c3972cc1b40 100644
--- a/src/module.c
+++ b/src/module.c
@@ -36,9 +36,8 @@ void init_modules(void)
 {
   unsigned int e;
   struct mapping *m = allocate_mapping(10);
-  m->refs++;
   push_text("_static_modules");
-  push_mapping(m);
+  ref_push_mapping(m);
   f_add_constant(2);
 
   for(e=0;e<NELEM(module_list);e++)
@@ -54,6 +53,7 @@ void init_modules(void)
     mapping_insert(m, sp-2, sp-1);
     pop_n_elems(2);
   }
+  free_mapping(m);
 }
 
 void exit_modules(void)
diff --git a/src/modules/Image/colortable.c b/src/modules/Image/colortable.c
index 15916b7d4bd94aa2b66f8e945c037cbd9d10ab0b..2fa41aec5cd10b2c864de4fd7235b535f1d418e1 100644
--- a/src/modules/Image/colortable.c
+++ b/src/modules/Image/colortable.c
@@ -1,11 +1,11 @@
 #include <config.h>
 
-/* $Id: colortable.c,v 1.35 1998/01/21 23:51:38 grubba Exp $ */
+/* $Id: colortable.c,v 1.36 1998/01/25 08:26:38 hubbe Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: colortable.c,v 1.35 1998/01/21 23:51:38 grubba Exp $
+**!	$Id: colortable.c,v 1.36 1998/01/25 08:26:38 hubbe Exp $
 **! class colortable
 **!
 **!	This object keeps colortable information,
@@ -21,7 +21,7 @@
 #undef COLORTABLE_REDUCE_DEBUG
 
 #include "global.h"
-RCSID("$Id: colortable.c,v 1.35 1998/01/21 23:51:38 grubba Exp $");
+RCSID("$Id: colortable.c,v 1.36 1998/01/25 08:26:38 hubbe Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -46,6 +46,7 @@ RCSID("$Id: colortable.c,v 1.35 1998/01/21 23:51:38 grubba Exp $");
 
 #include "image.h"
 #include "colortable.h"
+#include "dmalloc.h"
 
 struct program *image_colortable_program;
 extern struct program *image_program;
diff --git a/src/modules/Image/encodings/gif.c b/src/modules/Image/encodings/gif.c
index cec07adab80dcdf8dc9b35cfd0dd3ce2ad957f0e..bebbb87077d45d0142a40258d5fbb7f3f6bb17c2 100644
--- a/src/modules/Image/encodings/gif.c
+++ b/src/modules/Image/encodings/gif.c
@@ -1,9 +1,9 @@
-/* $Id: gif.c,v 1.29 1998/01/21 23:51:39 grubba Exp $ */
+/* $Id: gif.c,v 1.30 1998/01/25 08:27:14 hubbe Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: gif.c,v 1.29 1998/01/21 23:51:39 grubba Exp $
+**!	$Id: gif.c,v 1.30 1998/01/25 08:27:14 hubbe Exp $
 **! submodule GIF
 **!
 **!	This submodule keep the GIF encode/decode capabilities
@@ -31,7 +31,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: gif.c,v 1.29 1998/01/21 23:51:39 grubba Exp $");
+RCSID("$Id: gif.c,v 1.30 1998/01/25 08:27:14 hubbe Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -2135,28 +2135,25 @@ void init_image_gif(void)
 
    /** constants **/
 
-   push_int(GIF_RENDER);
-   add_constant(make_shared_string("RENDER"),sp-1,0);
-   push_int(GIF_EXTENSION);
-   add_constant(make_shared_string("EXTENSION"),sp-1,0);
+   add_integer_constant("RENDERER",GIF_RENDER,0);
+   add_integer_constant("EXTENSION",GIF_EXTENSION,0);
 
-   push_int(GIF_LOOSE_GCE);
-   add_constant(make_shared_string("LOOSE_GCE"),sp-1,0);
-   push_int(GIF_NETSCAPE_LOOP);
-   add_constant(make_shared_string("NETSCAPE_LOOP"),sp-1,0);
+   add_integer_constant("LOOSE_GCE",GIF_LOOSE_GCE,0);
+   add_integer_constant("NETSCAPE_LOOP",GIF_NETSCAPE_LOOP,0);
 
-   push_int(GIF_ERROR_PREMATURE_EOD);
-   add_constant(make_shared_string("ERROR_PREMATURE_EOD"),sp-1,0);
-   push_int(GIF_ERROR_UNKNOWN_DATA);
-   add_constant(make_shared_string("ERROR_UNKNOWN_DATA"),sp-1,0);
-   push_int(GIF_ERROR_TOO_MUCH_DATA);
-   add_constant(make_shared_string("ERROR_TOO_MUCH_DATA"),sp-1,0);
+   add_integer_constant("ERROR_PREMATURE_EOD",GIF_ERROR_PREMATURE_EOD,0);
+   add_integer_constant("ERROR_UNKNOWN_DATA",GIF_ERROR_UNKNOWN_DATA,0);
+   add_integer_constant("ERROR_TOO_MUCH_DATA",GIF_ERROR_TOO_MUCH_DATA,0);
 
    /** done **/
 
    image_gif_module_program=end_program();
    push_object(clone_object(image_gif_module_program,0));
-   add_constant(make_shared_string("GIF"),sp-1,0);
+   {
+     struct pike_string *s=make_shared_string("GIF");
+     add_constant(s,sp-1,0);
+     free_string(s);
+   }
    pop_stack();
 }
 
diff --git a/src/modules/Image/encodings/png.c b/src/modules/Image/encodings/png.c
index 21cdafdeb7de15603ee99b99de254d744593379f..afdca70d523db2cdbb0dd7f3bee8da7eefb50599 100644
--- a/src/modules/Image/encodings/png.c
+++ b/src/modules/Image/encodings/png.c
@@ -1,9 +1,9 @@
-/* $Id: png.c,v 1.1 1997/11/12 03:37:52 mirar Exp $ */
+/* $Id: png.c,v 1.2 1998/01/25 08:27:14 hubbe Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: png.c,v 1.1 1997/11/12 03:37:52 mirar Exp $
+**!	$Id: png.c,v 1.2 1998/01/25 08:27:14 hubbe Exp $
 **! submodule PNG
 **!
 **!	This submodule keep the PNG encode/decode capabilities
@@ -23,7 +23,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: png.c,v 1.1 1997/11/12 03:37:52 mirar Exp $");
+RCSID("$Id: png.c,v 1.2 1998/01/25 08:27:14 hubbe Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -45,13 +45,17 @@ void image_png__module_value(INT32 args)
 
 void init_image_png(void)
 {
+  struct pike_string *s;
+  struct program *p;
    start_new_program();
    
    add_function("_module_value",image_png__module_value,
 		"function(:object)",0);
 
-   push_object(clone_object(end_program(),0));
-   add_constant(make_shared_string("PNG"),sp-1,0);
+   push_object(clone_object(p=end_program(),0));
+   free_program(p);
+   add_constant(s=make_shared_string("PNG"),sp-1,0);
+   free_string(s);
    pop_stack();
 }
 
diff --git a/src/modules/Image/encodings/pnm.c b/src/modules/Image/encodings/pnm.c
index 256207152f3d0045a5e7bf220f8662f6f909fe3e..5ee0c43e11a284655a619b0733b4786a1d6f7e69 100644
--- a/src/modules/Image/encodings/pnm.c
+++ b/src/modules/Image/encodings/pnm.c
@@ -1,9 +1,9 @@
-/* $Id: pnm.c,v 1.11 1998/01/16 22:09:17 grubba Exp $ */
+/* $Id: pnm.c,v 1.12 1998/01/25 08:27:15 hubbe Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: pnm.c,v 1.11 1998/01/16 22:09:17 grubba Exp $
+**!	$Id: pnm.c,v 1.12 1998/01/25 08:27:15 hubbe Exp $
 **! submodule PNM
 **!
 **!	This submodule keeps the PNM encode/decode capabilities
@@ -49,7 +49,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: pnm.c,v 1.11 1998/01/16 22:09:17 grubba Exp $");
+RCSID("$Id: pnm.c,v 1.12 1998/01/25 08:27:15 hubbe Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -609,7 +609,11 @@ void init_image_pnm(void)
 
    image_pnm_module_program=end_program();
    push_object(clone_object(image_pnm_module_program,0));
-   add_constant(make_shared_string("PNM"),sp-1,0);
+   {
+     struct pike_string *s=make_shared_string("PNM");
+     add_constant(s,sp-1,0);
+     free_string(s);
+   }
    pop_stack();
 }
 
diff --git a/src/modules/Image/encodings/x.c b/src/modules/Image/encodings/x.c
index dfc0ef0bc74a9958923098fd366415183f532800..d8ce3ebf17102b8ff8d3984414e0a16e04715c02 100644
--- a/src/modules/Image/encodings/x.c
+++ b/src/modules/Image/encodings/x.c
@@ -1,9 +1,9 @@
-/* $Id: x.c,v 1.4 1998/01/19 23:51:24 grubba Exp $ */
+/* $Id: x.c,v 1.5 1998/01/25 08:27:15 hubbe Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: x.c,v 1.4 1998/01/19 23:51:24 grubba Exp $
+**!	$Id: x.c,v 1.5 1998/01/25 08:27:15 hubbe Exp $
 **! submodule X
 **!
 **!	This submodule handles encoding and decoding of
@@ -29,7 +29,7 @@
 #include <winsock.h>
 #endif
 
-RCSID("$Id: x.c,v 1.4 1998/01/19 23:51:24 grubba Exp $");
+RCSID("$Id: x.c,v 1.5 1998/01/25 08:27:15 hubbe Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -668,6 +668,7 @@ struct program *image_x_module_program=NULL;
 
 void init_image_x(void)
 {
+  struct pike_string *s;
    start_new_program();
    
    add_function("encode_truecolor",x_encode_truecolor,
@@ -679,7 +680,8 @@ void init_image_x(void)
 
    image_x_module_program=end_program();
    push_object(clone_object(image_x_module_program,0));
-   add_constant(make_shared_string("X"),sp-1,0);
+   add_constant(s=make_shared_string("X"),sp-1,0);
+   free_string(s);
    pop_stack();
 }
 
diff --git a/src/modules/Yp/yp.c b/src/modules/Yp/yp.c
index 163afc9212dc8856e54d18bc953341a068f6ceaf..71fffa5c3a72396458b79f2f6796847135df63c4 100644
--- a/src/modules/Yp/yp.c
+++ b/src/modules/Yp/yp.c
@@ -216,11 +216,12 @@ void pike_module_init(void)
   add_function("map", f_map, "function(string,function|array(function):void)", 0);
   add_function("order", f_order, "function(string:int)", 0);
 
-  add_program_constant("Domain", end_program(), 0);
+  end_class("Domain", 0);
 }
 
 void pike_module_exit(void)
 {
+  
 }
 #else
 
diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c
index fdb99d8b7ad2fb954324f5dcba85fd201caac8b0..63a226996382fbcedba6a0549e20e71e02d71796 100644
--- a/src/modules/files/efuns.c
+++ b/src/modules/files/efuns.c
@@ -60,6 +60,8 @@
 # endif
 #endif
 
+#include "dmalloc.h"
+
 struct array *encode_stat(struct stat *s)
 {
   struct array *a;
diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index ea96e5e793ae2b2b060a14a1f1e6bce087e33dbe..209693236553c90f10534f879ed50387597e6b1e 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -6,7 +6,7 @@
 #define READ_BUFFER 8192
 
 #include "global.h"
-RCSID("$Id: file.c,v 1.68 1998/01/21 23:51:41 grubba Exp $");
+RCSID("$Id: file.c,v 1.69 1998/01/25 08:28:00 hubbe Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -75,6 +75,9 @@ RCSID("$Id: file.c,v 1.68 1998/01/21 23:51:41 grubba Exp $");
 #include <netdb.h>
 #endif
 
+#include "dmalloc.h"
+
+
 #ifndef SEEK_SET
 #define SEEK_SET 0
 #endif
diff --git a/src/modules/files/socket.c b/src/modules/files/socket.c
index a05a3196877d18ab69210b2f041d9229eeda2cd7..1f89819ea4d78e12ff6ca32b88619ee5d1e04066 100644
--- a/src/modules/files/socket.c
+++ b/src/modules/files/socket.c
@@ -57,6 +57,8 @@
 #include <sys/socketvar.h>
 #endif
 
+#include "dmalloc.h"
+
 struct port
 {
   int fd;
@@ -227,7 +229,7 @@ static void port_bind(INT32 args)
   addr.sin_family = AF_INET;
 
   THREADS_ALLOW();
-  tmp=fd_bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 || fd_listen(fd, 16384) < 0;
+  tmp=fd_bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 || fd_listen(fd, 5) < 0;
   THREADS_DISALLOW();
 
   if(tmp)
diff --git a/src/modules/files/socktest.pike b/src/modules/files/socktest.pike
index 0094853eb4bcc3a82c0289eea003212179b1009f..9b65cb5db27d93921bccc16a0dc746636fb9d8b7 100755
--- a/src/modules/files/socktest.pike
+++ b/src/modules/files/socktest.pike
@@ -1,6 +1,6 @@
 #!/usr/local/bin/pike
 
-/* $Id: socktest.pike,v 1.6 1998/01/13 23:01:25 hubbe Exp $ */
+/* $Id: socktest.pike,v 1.7 1998/01/25 08:28:01 hubbe Exp $ */
 
 import Stdio;
 import String;
@@ -90,7 +90,7 @@ class Socket {
     input_buffer+=foo;
   }
 
-  varargs void create(object o)
+  void create(object|void o)
   {
     daemon->got_callback();
     daemon->start();
@@ -152,6 +152,7 @@ array(object(Socket)) stdtest()
   if(!sock2)
   {
     werror("Accept returned 0\n");
+    sleep(1);
     exit(1);
   }
   sock2=Socket(sock2);
@@ -278,7 +279,7 @@ void accept_callback()
   object o=port1::accept();
   if(!o)
   {
-    perror("Accept failed");
+    werror("Accept failed");
   }
   o=Socket(o);
   o->expected_data=strmult("foobar",4711);
@@ -286,17 +287,20 @@ void accept_callback()
 
 int main()
 {
-  for(portno1=2001;portno1<65536;portno1++)
-    if(port1::bind(portno1, accept_callback))
-      break;
-
-  if(portno1==65536) perror("Bind failed.\n");
+  if(!port1::bind(0, accept_callback))
+  {
+    werror("Bind failed.\n");
+    exit(1);
+  }
+  sscanf(port1::query_address(),"%*s %d",portno1);
 
-  for(portno2=2001;portno2<65536;portno2++)
-    if(port2::bind(portno2))
-      break;
+  if(!port2::bind(0))
+  {
+    werror("Bind failed.\n");
+    exit(1);
+  }
 
-  if(portno2==65536) perror("Bind failed.\n");
+  sscanf(port2::query_address(),"%*s %d",portno2);
 
   werror("Doing simple tests. ");
   stdtest();
diff --git a/src/modules/spider/accesseddb.c b/src/modules/spider/accesseddb.c
index 691b28ce1c835adf4ec55a584fe965710508dd39..98695a64128358243cab7c5179cbb1d73f5ba7ed 100644
--- a/src/modules/spider/accesseddb.c
+++ b/src/modules/spider/accesseddb.c
@@ -54,6 +54,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#include "dmalloc.h"
 #include "accesseddb.h"
 
 #define COOKIE 0x11223344
diff --git a/src/modules/spider/dumudp.c b/src/modules/spider/dumudp.c
index 93120f80feebedcd2e4566d143b0efb570f674e0..2beb5172677b1f04cc2d46160cbd91a0385ed977 100644
--- a/src/modules/spider/dumudp.c
+++ b/src/modules/spider/dumudp.c
@@ -1,7 +1,7 @@
 #include "config.h"
 
 #include "global.h"
-RCSID("$Id: dumudp.c,v 1.31 1998/01/21 19:57:17 hubbe Exp $");
+RCSID("$Id: dumudp.c,v 1.32 1998/01/25 08:28:24 hubbe Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -77,6 +77,8 @@ RCSID("$Id: dumudp.c,v 1.31 1998/01/21 19:57:17 hubbe Exp $");
 #include <netdb.h>
 #endif
 
+#include "dmalloc.h"
+
 struct dumudp {
   int fd;
   struct svalue read_callback;
diff --git a/src/modules/spider/spider.c b/src/modules/spider/spider.c
index 0f37b6684435b4b5beaa011e09d938f8a7dca0c6..5c0d310ecfd398e53b7fea77eafc8bd2b222ce22 100644
--- a/src/modules/spider/spider.c
+++ b/src/modules/spider/spider.c
@@ -40,7 +40,7 @@
 #include "threads.h"
 #include "operators.h"
 
-RCSID("$Id: spider.c,v 1.50 1998/01/16 22:33:15 grubba Exp $");
+RCSID("$Id: spider.c,v 1.51 1998/01/25 08:28:24 hubbe Exp $");
 
 #ifdef HAVE_PWD_H
 #include <pwd.h>
@@ -79,6 +79,8 @@ RCSID("$Id: spider.c,v 1.50 1998/01/16 22:33:15 grubba Exp $");
 
 #include <errno.h>
 
+#include "dmalloc.h"
+
 #include "accesseddb.h"
 
 #define MAX_PARSE_RECURSE 102
diff --git a/src/modules/system/system.c b/src/modules/system/system.c
index e05e1dd1821bb04320a9628795a19cdd63887a90..e449f02a87a29e43afd69a491d5c2d64f67358ca 100644
--- a/src/modules/system/system.c
+++ b/src/modules/system/system.c
@@ -1,5 +1,5 @@
 /*
- * $Id: system.c,v 1.38 1998/01/21 19:59:11 hubbe Exp $
+ * $Id: system.c,v 1.39 1998/01/25 08:28:45 hubbe Exp $
  *
  * System-call module for Pike
  *
@@ -14,7 +14,7 @@
 #include "system.h"
 
 #include "global.h"
-RCSID("$Id: system.c,v 1.38 1998/01/21 19:59:11 hubbe Exp $");
+RCSID("$Id: system.c,v 1.39 1998/01/25 08:28:45 hubbe Exp $");
 #ifdef HAVE_WINSOCK2_H
 #include <winsock2.h>
 #endif
@@ -68,6 +68,7 @@ RCSID("$Id: system.c,v 1.38 1998/01/21 19:59:11 hubbe Exp $");
 #include <sys/stat.h>
 #endif /* HAVE_SYS_STAT_H */
 
+#include "dmalloc.h"
 /*
  * Functions
  */
diff --git a/src/multiset.c b/src/multiset.c
index 2ff4603447ccc707a48e991833f76c8ba1b7c1e2..be87bc9a2895861fccb8dfedc617d27f8493765b 100644
--- a/src/multiset.c
+++ b/src/multiset.c
@@ -66,6 +66,7 @@ void really_free_multiset(struct multiset *l)
 static void order_multiset(struct multiset *l)
 {
   INT32 *order;
+  if(l->ind->size < 2) return;
   order = get_set_order(l->ind);
   l->ind = order_array(l->ind, order);
   free((char *)order);
@@ -316,3 +317,4 @@ void count_memory_in_multisets(INT32 *num_, INT32 *size_)
   *num_=num;
   *size_=size;
 }
+
diff --git a/src/object.c b/src/object.c
index 9fbae6a701da157b814b25e857099b924be9c2b3..3ea12bf3045863a02121d7966f2a5257c67034b3 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.32 1998/01/15 05:59:42 hubbe Exp $");
+RCSID("$Id: object.c,v 1.33 1998/01/25 08:25:12 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -201,15 +201,10 @@ struct object *get_master(void)
       error("Couldn't load master program. (%s)\n",master_file);
     }
   }
-  master_object=clone_object(master_program,0);
+  master_object=low_clone(master_program);
 
   call_c_initializers(master_object);
   call_pike_initializers(master_object,0);
-
-  apply_lfun(master_object,LFUN___INIT,0);
-  pop_stack();
-  apply_lfun(master_object,LFUN_CREATE,0);
-  pop_stack();
   
   inside = 0;
   return master_object;
diff --git a/src/peep.c b/src/peep.c
index 0339a6054714bd67b25b2d2c0b5859a41ca43ee6..67847598727b49b6a1f2452b2650e34e4173fc2d 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -159,9 +159,9 @@ void assemble(void)
 	max_label = c->arg;
 
 
-  labels=(INT32 *)xalloc(sizeof(INT32) * (max_label+1));
-  jumps=(INT32 *)xalloc(sizeof(INT32) * (max_label+1));
-  uses=(INT32 *)xalloc(sizeof(INT32) * (max_label+1));
+  labels=(INT32 *)xalloc(sizeof(INT32) * (max_label+2));
+  jumps=(INT32 *)xalloc(sizeof(INT32) * (max_label+2));
+  uses=(INT32 *)xalloc(sizeof(INT32) * (max_label+2));
 
   for(e=0;e<=max_label;e++)
   {
diff --git a/src/pike_memory.c b/src/pike_memory.c
index e5d158ad153c6b2019755b8e81777e0bf4b82d58..5b4b88783d881ef31e1e6008a878975fcb5c7f4a 100644
--- a/src/pike_memory.c
+++ b/src/pike_memory.c
@@ -8,17 +8,6 @@
 #include "error.h"
 #include "pike_macros.h"
 
-char *xalloc(SIZE_T size)
-{
-  char *ret;
-  if(!size) return 0;
-
-  ret=(char *)malloc(size);
-  if(ret) return ret;
-
-  error("Out of memory.\n");
-  return 0;
-}
 
 /* strdup() is used by several modules, so let's provide it */
 #ifndef HAVE_STRDUP
@@ -94,6 +83,7 @@ void reorder(char *memory, INT32 nitems, INT32 size,INT32 *order)
 {
   INT32 e;
   char *tmp;
+  if(nitems<2) return;
   tmp=xalloc(size * nitems);
 #undef DOSIZE
 #define DOSIZE(X,Y)				\
@@ -406,3 +396,301 @@ void memfill(char *to,
     }
   }
 }
+
+#ifdef DEBUG_MALLOC
+
+#undef xalloc
+#undef malloc
+#undef free
+#undef realloc
+#undef calloc
+#undef xalloc
+#undef strdup
+#undef main
+
+int verbose_debug_malloc = 0;
+int verbose_debug_exit = 1;
+
+#define BSIZE 16382
+#define HSIZE 65599
+
+struct memloc
+{
+  struct memloc *next;
+  const char *filename;
+  int line;
+  int times;
+};
+
+struct memhdr
+{
+  struct memhdr *next;
+  size_t size;
+  void *data;
+  struct memloc *locations;
+};
+
+static struct memhdr *hash[HSIZE];
+
+struct memhdr_block
+{
+  struct memhdr_block *next;
+  struct memhdr memhdrs[BSIZE];
+};
+
+static struct memhdr_block *memhdr_blocks=0;
+static struct memhdr *free_memhdrs=0;
+
+static struct memhdr *alloc_memhdr(void)
+{
+  struct memhdr *tmp;
+  if(!free_memhdrs)
+  {
+    struct memhdr_block *n;
+    int e;
+    n=(struct memhdr_block *)malloc(sizeof(struct memhdr_block));
+    if(!n)
+    {
+      fprintf(stderr,"Fatal: out of memory.\n");
+      verbose_debug_exit=0;
+      exit(17);
+    }
+    n->next=memhdr_blocks;
+    memhdr_blocks=n;
+
+    for(e=0;e<BSIZE;e++)
+    {
+      n->memhdrs[e].next=free_memhdrs;
+      free_memhdrs=n->memhdrs+e;
+    }
+  }
+
+  tmp=free_memhdrs;
+  free_memhdrs=tmp->next;
+  return tmp;
+}
+
+struct memloc_block
+{
+  struct memloc_block *next;
+  struct memloc memlocs[BSIZE];
+};
+
+static struct memloc_block *memloc_blocks=0;
+static struct memloc *free_memlocs=0;
+
+static struct memloc *alloc_memloc(void)
+{
+  struct memloc *tmp;
+  if(!free_memlocs)
+  {
+    struct memloc_block *n;
+    int e;
+    n=(struct memloc_block *)malloc(sizeof(struct memloc_block));
+    if(!n)
+    {
+      fprintf(stderr,"Fatal: out of memory.\n");
+      verbose_debug_exit=0;
+      exit(17);
+    }
+    n->next=memloc_blocks;
+    memloc_blocks=n;
+
+    for(e=0;e<BSIZE;e++)
+    {
+      n->memlocs[e].next=free_memlocs;
+      free_memlocs=n->memlocs+e;
+    }
+  }
+
+  tmp=free_memlocs;
+  free_memlocs=tmp->next;
+  return tmp;
+}
+
+static struct memhdr *find_memhdr(void *p)
+{
+  struct memhdr *mh;
+  unsigned long h=(long)p;
+  h%=HSIZE;
+  for(mh=hash[h]; mh; mh=mh->next)
+    if(mh->data==p)
+      return mh;
+  return NULL;
+}
+
+static void add_location(struct memhdr *mh, const char *fn, int line)
+{
+  struct memloc *ml;
+  for(ml=mh->locations;ml;ml=ml->next)
+    if(ml->filename==fn && ml->line==line)
+      return;
+
+  ml=alloc_memloc();
+  ml->line=line;
+  ml->filename=fn;
+  ml->next=mh->locations;
+  ml->times++;
+  mh->locations=ml;
+}
+
+static void make_memhdr(void *p, int s, const char *fn, int line)
+{
+  struct memhdr *mh=alloc_memhdr();
+  struct memloc *ml=alloc_memloc();
+  unsigned long h=(long)p;
+  h%=HSIZE;
+  mh->next=hash[h];
+  mh->data=p;
+  mh->size=s;
+  mh->locations=ml;
+  ml->filename=fn;
+  ml->line=line;
+  ml->next=0;
+  ml->times=1;
+  hash[h]=mh;
+}
+
+static int remove_memhdr(void *p)
+{
+  struct memhdr **prev,*mh;
+  unsigned long h=(long)p;
+  h%=HSIZE;
+  for(prev=hash+h;(mh=*prev);prev=&(mh->next))
+  {
+    if(mh->data==p)
+    {
+      struct memloc *ml;
+      while((ml=mh->locations))
+      {
+	mh->locations=ml->next;
+	ml->next=free_memlocs;
+	free_memlocs=ml;
+      }
+      *prev=mh->next;
+      mh->next=free_memhdrs;
+      free_memhdrs=mh;
+      
+      return 1;
+    }
+  }
+  return 0;
+}
+
+void *debug_malloc(size_t s, const char *fn, int line)
+{
+  void *m=malloc(s);
+  if(m) make_memhdr(m, s, fn, line);
+
+  if(verbose_debug_malloc)
+    fprintf(stderr, "malloc(%d) => %p  (%s:%d)\n", s, m, fn, line);
+
+  return m;
+}
+
+char *debug_xalloc(long size, const char *fn, int line)
+{
+  char *ret;
+  if(!size) return 0;
+
+  ret=(char *)debug_malloc(size,fn, line);
+  if(ret) return ret;
+
+  error("Out of memory.\n");
+  return 0;
+}
+
+void *debug_calloc(size_t a, size_t b, const char *fn, int line)
+{
+  void *m=calloc(a, b);
+
+  if(m) make_memhdr(m, a*b, fn, line);
+
+  if(verbose_debug_malloc)
+    fprintf(stderr, "calloc(%d,%d) => %p  (%s:%d)\n", a, b, m, fn, line);
+
+  return m;
+}
+
+void *debug_realloc(void *p, size_t s, const char *fn, int line)
+{
+  void *m;
+  m=realloc(p, s);
+  if(m) {
+    if(p) remove_memhdr(p);
+    make_memhdr(m, s, fn, line);
+  }
+  if(verbose_debug_malloc)
+    fprintf(stderr, "realloc(%p,%d) => %p  (%s:%d)\n", p, s, m, fn,line);
+  return m;
+}
+
+void debug_free(void *p, const char *fn, int line)
+{
+  remove_memhdr(p);
+  free(p);
+  if(verbose_debug_malloc)
+    fprintf(stderr, "free(%p) (%s:%d)\n", p, fn,line);
+}
+
+char *debug_strdup(const char *s, const char *fn, int line)
+{
+  char *m=strdup(s);
+
+  if(m) make_memhdr(m, strlen(s)+1, fn, line);
+
+  if(verbose_debug_malloc)
+    fprintf(stderr, "strdup(\"%s\") => %p  (%s:%d)\n", s, m, fn, line);
+  return m;
+}
+
+static void cleanup_memhdrs()
+{
+  unsigned long h;
+  if(verbose_debug_exit)
+  {
+    for(h=0;h<HSIZE;h++)
+    {
+      struct memhdr *m;
+      for(m=hash[h];m;m=m->next)
+      {
+	struct memloc *l;
+	fprintf(stderr, "LEAK: (%p) %d bytes (%ld refs?)\n",m->data, m->size,(long)*(INT32 *)m->data);
+	for(l=m->locations;l;l=l->next)
+	  fprintf(stderr,"  *** %s:%d (%d times)\n",l->filename, l->line, l->times);
+      }
+    }
+  }
+}
+
+int main(int argc, char *argv[])
+{
+  extern int dbm_main(int, char **);
+  atexit(cleanup_memhdrs);
+  return dbm_main(argc, argv);
+}
+
+void * debug_malloc_update_location(void *p,const char *fn, int line)
+{
+  struct memhdr *mh=find_memhdr(p);
+  if(mh)
+    add_location(mh, fn, line);
+  return p;
+}
+
+
+#else
+
+char *xalloc(long size)
+{
+  char *ret;
+  if(!size) return 0;
+
+  ret=(char *)malloc(size);
+  if(ret) return ret;
+
+  error("Out of memory.\n");
+  return 0;
+}
+
+#endif
diff --git a/src/pike_memory.h b/src/pike_memory.h
index e53a9fe6ef9d676fa3f6634ceed07be7f49ab81f..5e97061800d1ae43d18ab367c90f2463725d4b39 100644
--- a/src/pike_memory.h
+++ b/src/pike_memory.h
@@ -34,7 +34,6 @@ struct mem_searcher
 };
 
 /* Prototypes begin here */
-char *xalloc(SIZE_T size);
 void swap(char *a, char *b, INT32 size);
 void reverse(char *memory, INT32 nitems, INT32 size);
 void reorder(char *memory, INT32 nitems, INT32 size,INT32 *order);
diff --git a/src/pike_types.c b/src/pike_types.c
index ffc041098081be6acd1701744e6344d20989442c..f83fc612bbb56241ba4276763ce73a4b417bf557 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: pike_types.c,v 1.28 1998/01/16 22:33:07 grubba Exp $");
+RCSID("$Id: pike_types.c,v 1.29 1998/01/25 08:25:13 hubbe Exp $");
 #include <ctype.h>
 #include "svalue.h"
 #include "pike_types.h"
@@ -212,7 +212,7 @@ void push_finished_type(struct pike_string *type)
   for(e=type->len-1;e>=0;e--) push_type(type->str[e]);
 }
 
-struct pike_string *pop_unfinished_type(void)
+struct pike_string *debug_pop_unfinished_type(void)
 {
   int len,e;
   struct pike_string *s;
@@ -226,7 +226,7 @@ struct pike_string *pop_unfinished_type(void)
   return s;
 }
 
-struct pike_string *pop_type(void)
+struct pike_string *debug_pop_type(void)
 {
   struct pike_string *s;
   s=pop_unfinished_type();
diff --git a/src/pike_types.h b/src/pike_types.h
index bf7934a3d1cbde7a36286ac97adbffd86d6402ee..00646b53a404fa1a692040e0e340bf65bdfc0a3e 100644
--- a/src/pike_types.h
+++ b/src/pike_types.h
@@ -66,8 +66,8 @@ void type_stack_reverse(void);
 void push_type_int(unsigned INT32 i);
 void push_unfinished_type(char *s);
 void push_finished_type(struct pike_string *type);
-struct pike_string *pop_unfinished_type(void);
-struct pike_string *pop_type(void);
+struct pike_string *debug_pop_unfinished_type(void);
+struct pike_string *debug_pop_type(void);
 struct pike_string *parse_type(char *s);
 void stupid_describe_type(char *a,INT32 len);
 void simple_describe_type(struct pike_string *s);
@@ -87,4 +87,13 @@ char *get_name_of_type(int t);
 void cleanup_pike_types(void);
 /* Prototypes end here */
 
+#ifdef DEBUG_MALLOC
+#define pop_type() ((struct pike_string *)debug_malloc_update_location(debug_pop_type(),__FILE__,__LINE__))
+#define pop_unfinished_type() \
+ ((struct pike_string *)debug_malloc_update_location(debug_pop_unfinished_type(),__FILE__,__LINE__))
+#else
+#define pop_type debug_pop_type
+#define pop_unfinished_type debug_pop_unfinished_type
+#endif
+
 #endif
diff --git a/src/program.c b/src/program.c
index 2ef634b5cb13eb84d75ef0f89c5d97df1707aade..3c5ea79646ad5bd0b328892e5faeb2e7c841ab63 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.53 1998/01/22 00:51:04 grubba Exp $");
+RCSID("$Id: program.c,v 1.54 1998/01/25 08:25:14 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -185,8 +185,7 @@ struct node_s *find_module_identifier(struct pike_string *ident)
     while(--e>=0)
     {
       push_svalue(modules+e);
-      push_string(ident);
-      ident->refs++;
+      ref_push_string(ident);
       f_index(2);
       
       if(!IS_UNDEFINED(sp-1))
@@ -250,7 +249,8 @@ struct program *id_to_program(INT32 id)
   h=id & (ID_TO_PROGRAM_CACHE_SIZE-1);
 
   if((p=id_to_program_cache[h]))
-    if(p->id==id) return p;
+    if(p->id==id)
+      return p;
   
   if(id) 
     {
@@ -258,11 +258,7 @@ struct program *id_to_program(INT32 id)
 	{
 	  if(id==p->id)
 	    {
-	      if(id_to_program_cache[h])
-		free_program(id_to_program_cache[h]);
-	      
 	      id_to_program_cache[h]=p;
-	      p->refs++;
 	      return p;
 	    }
 	}
@@ -434,6 +430,7 @@ void low_start_new_program(struct program *p,
     i.inherit_level=0;
     i.parent=0;
     i.parent_identifier=0;
+    i.parent_offset=1;
     i.name=0;
     add_to_inherits(i);
   }
@@ -728,17 +725,16 @@ struct program *end_first_pass(int finish)
   if(init_node)
   {
     union idptr tmp;
-    struct pike_string *s;
-    s=make_shared_string("__INIT");
     dooptcode(s,
 	      mknode(F_ARG_LIST,
 		     init_node,mknode(F_RETURN,mkintnode(0),0)),
 	      function_type_string,
 	      0);
-    free_string(s);
     init_node=0;
   }
 
+  free_string(s);
+
   pop_compiler_frame(); /* Pop __INIT local variables */
 
   exit_type_stack();
@@ -894,16 +890,17 @@ void rename_last_inherit(struct pike_string *n)
 /*
  * make this program inherit another program
  */
-void do_inherit(struct svalue *prog,
-		INT32 flags,
-		struct pike_string *name)
+void low_inherit(struct program *p,
+		 struct object *parent,
+		 int parent_identifier,
+		 int parent_offset,
+		 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)
   {
@@ -925,10 +922,13 @@ void do_inherit(struct svalue *prog,
     inherit.inherit_level ++;
     if(!e)
     {
-      if(prog->type == T_FUNCTION)
+      if(parent)
       {
-	inherit.parent=prog->u.object;
-	inherit.parent_identifier=prog->subtype;
+	inherit.parent=parent;
+	inherit.parent_identifier=parent_identifier;
+	inherit.parent_offset=0;
+      }else{
+	inherit.parent_offset+=parent_offset;
       }
     }
     if(inherit.parent) inherit.parent->refs++;
@@ -989,6 +989,71 @@ void do_inherit(struct svalue *prog,
   }
 }
 
+void do_inherit(struct svalue *s,
+		INT32 flags,
+		struct pike_string *name)
+{
+  struct program *p=program_from_svalue(s);
+  low_inherit(p,
+	      s->type == T_FUNCTION ? s->u.object : 0,
+	      s->subtype,
+	      0,
+	      flags,
+	      name);
+}
+
+void compiler_do_inherit(node *n,
+			 INT32 flags,
+			 struct pike_string *name)
+{
+  switch(n->token)
+  {
+    case F_EXTERNAL:
+    {
+      struct identifier *i;
+      struct program *p=parent_compilation(n->u.integer.a);
+      INT32 numid=n->u.integer.b;
+      
+      if(!p)
+      {
+	yyerror("Failed to resolv external constant.\n");
+	return;
+      }
+
+      i=ID_FROM_INT(p, numid);
+    
+      if(IDENTIFIER_IS_CONSTANT(i->identifier_flags))
+      {
+	struct svalue *s=PROG_FROM_INT(new_program, numid)->constants + i->func.offset;
+	if(s->type != T_PROGRAM)
+	{
+	  yyerror("Inherit identifier is not a program");
+	  return;
+	}else{
+	  p=s->u.program;
+	}
+      }else{
+	yyerror("Inherit identifier is not a constant program");
+	return;
+      }
+
+      low_inherit(p,
+		  0,
+		  0,
+		  n->u.integer.a,
+		  flags,
+		  name);
+      break;
+    }
+
+    default:
+      resolv_program(n);
+      do_inherit(sp-1, flags, name);
+      pop_stack();
+  }
+}
+			 
+
 void simple_do_inherit(struct pike_string *s,
 		       INT32 flags,
 		       struct pike_string *name)
@@ -1092,7 +1157,7 @@ int define_variable(struct pike_string *name,
 		    struct pike_string *type,
 		    INT32 flags)
 {
-  int n;
+  int n, run_time_type;
 
 #ifdef DEBUG
   if(name!=debug_findstring(name))
@@ -1126,30 +1191,32 @@ int define_variable(struct pike_string *name,
     if(PROG_FROM_INT(new_program, n) == new_program)
       my_yyerror("Variable '%s' defined twice.",name->str);
 
-    if(ID_FROM_INT(new_program, n)->type != type)
-      my_yyerror("Illegal to redefine inherited variable with different type.");
-
-    if(ID_FROM_INT(new_program, n)->identifier_flags != flags)
-      my_yyerror("Illegal to redefine inherited variable with different type.");
+    if(!(IDENTIFIERP(n)->id_flags & ID_INLINE))
+    {
+      if(ID_FROM_INT(new_program, n)->type != type)
+	my_yyerror("Illegal to redefine inherited variable with different type.");
+      
+      if(ID_FROM_INT(new_program, n)->identifier_flags != flags)
+	my_yyerror("Illegal to redefine inherited variable with different type.");
+      return n;
+    }
+  }
 
-  } else {
-    int run_time_type=compile_type_to_runtime_type(type);
+  run_time_type=compile_type_to_runtime_type(type);
 
-    switch(run_time_type)
-    {
+  switch(run_time_type)
+  {
     case T_FUNCTION:
     case T_PROGRAM:
       run_time_type = T_MIXED;
-    }
-
-    n=low_define_variable(name,type,flags,
-			  add_storage(run_time_type == T_MIXED ?
-				      sizeof(struct svalue) :
-				      sizeof(union anything)),
-			  run_time_type);
-				      
-
   }
+  
+  n=low_define_variable(name,type,flags,
+			add_storage(run_time_type == T_MIXED ?
+				    sizeof(struct svalue) :
+				    sizeof(union anything)),
+			run_time_type);
+  
 
   return n;
 }
@@ -1240,11 +1307,16 @@ int add_constant(struct pike_string *name,
     if(PROG_FROM_INT(new_program, n) == new_program)
       my_yyerror("Identifier '%s' defined twice.",name->str);
 
-    new_program->identifier_references[n]=ref;
-  } else {
-    n=new_program->num_identifier_references;
-    add_to_identifier_references(ref);
+    if(!(IDENTIFIERP(n)->id_flags & ID_INLINE))
+    {
+      /* override */
+      new_program->identifier_references[n]=ref;
+
+      return n;
+    }
   }
+  n=new_program->num_identifier_references;
+  add_to_identifier_references(ref);
 
   return n;
 }
@@ -1355,7 +1427,6 @@ INT32 define_function(struct pike_string *name,
 
   i=isidentifier(name);
 
-
   if(i >= 0)
   {
     /* already defined */
@@ -1383,65 +1454,70 @@ INT32 define_function(struct pike_string *name,
       my_yyerror("Illegal to redefine 'nomask' function %s.",name->str);
     }
 
-    /* We modify the old definition if it is in this program */
-    if(ref.inherit_offset==0)
+    if(!(ref.id_flags & ID_INLINE))
     {
-      if(func)
-	funp->func = *func;
-      else
-	funp->func.offset = -1;
-
-      funp->identifier_flags=function_flags;
-    }else{
-      /* Otherwise we make a new definition */
-      copy_shared_string(fun.name, name);
-      copy_shared_string(fun.type, type);
-
-      fun.run_time_type=T_FUNCTION;
-
-      fun.identifier_flags=function_flags;
-
-      if(func)
-	fun.func = *func;
-      else
-	fun.func.offset = -1;
-
-      ref.identifier_offset=new_program->num_identifiers;
-      add_to_identifiers(fun);
+      /* We modify the old definition if it is in this program */
+      if(ref.inherit_offset==0)
+      {
+	if(func)
+	  funp->func = *func;
+	else
+	  funp->func.offset = -1;
+	
+	funp->identifier_flags=function_flags;
+      }else{
+	/* Otherwise we make a new definition */
+	copy_shared_string(fun.name, name);
+	copy_shared_string(fun.type, type);
+	
+	fun.run_time_type=T_FUNCTION;
+	
+	fun.identifier_flags=function_flags;
+	
+	if(func)
+	  fun.func = *func;
+	else
+	  fun.func.offset = -1;
+	
+	ref.identifier_offset=new_program->num_identifiers;
+	add_to_identifiers(fun);
+      }
+      
+      ref.inherit_offset = 0;
+      ref.id_flags = flags;
+      new_program->identifier_references[i]=ref;
+      return i;
     }
+  }
 
-    ref.inherit_offset = 0;
-    ref.id_flags = flags;
-    new_program->identifier_references[i]=ref;
-  }else{
-    /* define it */
-
-    copy_shared_string(fun.name, name);
-    copy_shared_string(fun.type, type);
-
-    fun.identifier_flags=function_flags;
-
-    fun.run_time_type=T_FUNCTION;
-
-    if(func)
-      fun.func = *func;
-    else
-      fun.func.offset = -1;
+  /* define a new function */
 
-    i=new_program->num_identifiers;
+  copy_shared_string(fun.name, name);
+  copy_shared_string(fun.type, type);
+  
+  fun.identifier_flags=function_flags;
+  
+  fun.run_time_type=T_FUNCTION;
+  
+  if(func)
+    fun.func = *func;
+  else
+    fun.func.offset = -1;
+  
+  i=new_program->num_identifiers;
 #ifdef PROFILING
-    fun.num_calls = 0;
+  fun.num_calls = 0;
 #endif /* PROFILING */
+  
+  add_to_identifiers(fun);
+  
+  ref.id_flags = flags;
+  ref.identifier_offset = i;
+  ref.inherit_offset = 0;
+  
+  i=new_program->num_identifier_references;
+  add_to_identifier_references(ref);
 
-    add_to_identifiers(fun);
-
-    ref.id_flags = flags;
-    ref.identifier_offset = i;
-    ref.inherit_offset = 0;
-
-    i=new_program->num_identifier_references;
-    add_to_identifier_references(ref);
-  }
   return i;
 }
 
@@ -1746,6 +1822,8 @@ struct program *compile(struct pike_string *prog)
   if(p && !num_parse_error)
   {
     low_start_new_program(p,0,0);
+    free_program(p);
+    p=0;
     compiler_pass=2;
     lex.pos=prog->str;
     yyparse();  /* Parse da program again */
@@ -1819,8 +1897,8 @@ void check_all_programs(void)
 
 void cleanup_program(void)
 {
-#ifdef FIND_FUNCTION_HASHSIZE
   int e;
+#ifdef FIND_FUNCTION_HASHSIZE
   for(e=0;e<FIND_FUNCTION_HASHSIZE;e++)
   {
     if(cache[e].name)
@@ -1830,6 +1908,7 @@ void cleanup_program(void)
     }
   }
 #endif
+
 }
 
 #ifdef GC2
diff --git a/src/program.h b/src/program.h
index 7e2aee546425911ec87ea30cb620e7ffd933573f..de26fe64c2f59d27a91f903e570bc184a0fcab55 100644
--- a/src/program.h
+++ b/src/program.h
@@ -100,8 +100,8 @@ union idptr
 #define IDENTIFIER_PIKE_FUNCTION 1
 #define IDENTIFIER_C_FUNCTION 2
 #define IDENTIFIER_FUNCTION 3
-#define IDENTIFIER_VARARGS 4
-#define IDENTIFIER_CONSTANT 8
+#define IDENTIFIER_CONSTANT 4
+#define IDENTIFIER_VARARGS 8
 
 #define IDENTIFIER_IS_FUNCTION(X) ((X) & IDENTIFIER_FUNCTION)
 #define IDENTIFIER_IS_CONSTANT(X) ((X) & IDENTIFIER_CONSTANT)
@@ -131,10 +131,9 @@ struct identifier
 #define ID_NOMASK    0x04
 #define ID_PUBLIC    0x08
 #define ID_PROTECTED 0x10
-#define ID_VARARGS   0x20
-#define ID_INLINE    0x40
-#define ID_HIDDEN    0x80 /* needed? */
-#define ID_INHERITED 0x100
+#define ID_INLINE    0x20
+#define ID_HIDDEN    0x40 /* needed? */
+#define ID_INHERITED 0x80
 
 struct reference
 {
@@ -149,6 +148,7 @@ struct inherit
   INT16 inherit_level; /* really needed? */
   INT16 identifier_level;
   INT16 parent_identifier;
+  INT16 parent_offset;
   INT32 storage_offset;
   struct object *parent;
   struct program *prog;
@@ -250,9 +250,18 @@ 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 svalue *prog,
+void low_inherit(struct program *p,
+		 struct object *parent,
+		 int parent_identifier,
+		 int parent_offset,
+		 INT32 flags,
+		 struct pike_string *name);
+void do_inherit(struct svalue *s,
 		INT32 flags,
 		struct pike_string *name);
+void compiler_do_inherit(node *n,
+			 INT32 flags,
+			 struct pike_string *name);
 void simple_do_inherit(struct pike_string *s,
 		       INT32 flags,
 		       struct pike_string *name);
diff --git a/src/stralloc.c b/src/stralloc.c
index 2ff1752a106cffc76ec023f71c8e1f312193f533..576674f22e31cae9f6dce0f81d70eff17750d39d 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -127,7 +127,7 @@ static void rehash(void)
 /* note that begin_shared_string expects the _exact_ size of the string,
  * not the maximum size
  */
-struct pike_string *begin_shared_string(int len)
+struct pike_string *debug_begin_shared_string(int len)
 {
   struct pike_string *t;
   t=(struct pike_string *)xalloc(len + sizeof(struct pike_string));
@@ -168,7 +168,7 @@ struct pike_string *end_shared_string(struct pike_string *s)
   return s;
 }
 
-struct pike_string * make_shared_binary_string(const char *str,int len)
+struct pike_string * debug_make_shared_binary_string(const char *str,int len)
 {
   struct pike_string *s;
   int h=StrHash(str,len);
@@ -186,7 +186,7 @@ struct pike_string * make_shared_binary_string(const char *str,int len)
   return s;
 }
 
-struct pike_string *make_shared_string(const char *str)
+struct pike_string *debug_make_shared_string(const char *str)
 {
   return make_shared_binary_string(str, strlen(str));
 }
@@ -221,6 +221,12 @@ void really_free_string(struct pike_string *s)
   free((char *)s);
 }
 
+void debug_free_string(struct pike_string *s)
+{
+  if(--s->refs<=0)
+    really_free_string(s);
+}
+
 
 /*
  * String table status
@@ -642,10 +648,31 @@ void init_shared_string_table(void)
   MEMSET((char *)base_table,0,sizeof(struct pike_string *)*htable_size);
 }
 
+#ifdef DEBUG_MALLOC
+struct shared_string_location *all_shared_string_locations;
+#endif
+
+
 void cleanup_shared_string_table(void)
 {
   unsigned INT32 e;
   struct pike_string *s,*next;
+
+#if defined(DEBUG) && defined(DEBUG_MALLOC)
+  while(all_shared_string_locations)
+  {
+    struct shared_string_location *x=all_shared_string_locations;
+    all_shared_string_locations=x->next;
+    free_string(x->s);
+    x->s=0;
+  }
+
+  if(verbose_debug_exit)
+  {
+    fprintf(stderr,"Leaked strings \n");
+    dump_stralloc_strings();
+  }
+#endif
   for(e=0;e<htable_size;e++)
   {
     for(s=base_table[e];s;s=next)
@@ -660,12 +687,18 @@ void cleanup_shared_string_table(void)
     base_table[e]=0;
   }
   free((char *)base_table);
+  base_table=0;
+  num_strings=0;
 }
 
 void count_memory_in_strings(INT32 *num, INT32 *size)
 {
   unsigned INT32 e, num_=0, size_=0;
-  if(!base_table) return;
+  if(!base_table)
+  {
+    *num=*size=0;
+    return;
+  }
   size_+=htable_size * sizeof(struct pike_string *);
   for(e=0;e<htable_size;e++)
   {
diff --git a/src/stralloc.h b/src/stralloc.h
index d35dd6265802ebb07fcd4e9147f6176a2c2d5d01..35388541b24878b6a4debbdfe55c0cd41df7bca2 100644
--- a/src/stralloc.h
+++ b/src/stralloc.h
@@ -33,19 +33,46 @@ struct pike_string *debug_findstring(const struct pike_string *foo);
 
 #define reference_shared_string(s) (s)->refs++
 #define copy_shared_string(to,s) ((to)=(s))->refs++
+
+
+#ifdef DEBUG_MALLOC
+struct shared_string_location
+{
+  struct pike_string *s;
+  struct shared_string_location *next;
+};
+
+extern struct shared_string_location *all_shared_string_locations;
+
+#define MAKE_CONSTANT_SHARED_STRING(var, text) do {	\
+  static struct shared_string_location str_;		\
+  if(!str_.s) { 					\
+    str_.s=make_shared_string((text));			\
+    str_.next=all_shared_string_locations;		\
+    all_shared_string_locations=&str_;			\
+  }							\
+ copy_shared_string((var),str_.s);			\
+}while(0)
+
+
+#else
 #define MAKE_CONSTANT_SHARED_STRING(var, text)	\
  do { static struct pike_string *str_;		\
     if(!str_) str_=make_shared_string((text));	\
     copy_shared_string((var), str_);		\
  }while(0)
 
+#endif
+
+
+
 /* Prototypes begin here */
 struct pike_string *binary_findstring(const char *foo, INT32 l);
 struct pike_string *findstring(const char *foo);
-struct pike_string *begin_shared_string(int len);
+struct pike_string *debug_begin_shared_string(int len);
 struct pike_string *end_shared_string(struct pike_string *s);
-struct pike_string * make_shared_binary_string(const char *str,int len);
-struct pike_string *make_shared_string(const char *str);
+struct pike_string * debug_make_shared_binary_string(const char *str,int len);
+struct pike_string *debug_make_shared_string(const char *str);
 void unlink_pike_string(struct pike_string *s);
 void really_free_string(struct pike_string *s);
 struct pike_string *add_string_status(int verbose);
@@ -76,4 +103,17 @@ void count_memory_in_strings(INT32 *num, INT32 *size);
 void gc_mark_all_strings(void);
 /* Prototypes end here */
 
+#ifdef DEBUG_MALLOC
+#define make_shared_string(X) \
+ ((struct pike_string *)debug_malloc_update_location(debug_make_shared_string(X),__FILE__,__LINE__))
+#define make_shared_binary_string(X,Y) \
+ ((struct pike_string *)debug_malloc_update_location(debug_make_shared_binary_string((X),(Y)),__FILE__,__LINE__))
+#define begin_shared_string(X) \
+ ((struct pike_string *)debug_malloc_update_location(debug_begin_shared_string(X),__FILE__,__LINE__))
+#else
+#define make_shared_string debug_make_shared_string
+#define make_shared_binary_string debug_make_shared_binary_string
+#define begin_shared_string debug_begin_shared_string
+#endif
+
 #endif /* STRALLOC_H */
diff --git a/src/testsuite.in b/src/testsuite.in
index 444c296361b61227eaaf9fe2a206c9c12c78910d..b7ca74092b33e74776dd1f98140ff213d9360f13 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,4 @@
-test_true([["$Id: testsuite.in,v 1.67 1998/01/20 02:30:39 hubbe Exp $"]])
+test_true([["$Id: testsuite.in,v 1.68 1998/01/25 08:25:15 hubbe Exp $"]])
 test_eq(1e1,10.0)
 test_eq(1E1,10.0)
 test_eq(1e+1,10.0)
@@ -12,6 +12,9 @@ test_eq([[cpp("#define MAX(X,Y) ((X)>(Y)?(X):(Y))\n#define MAX3(X,Y,Z) MAX(MAX(X
 
 test_program([[class foo { program x() { return class {}; }}; class bar { inherit foo; program x() { return class {}; }} int a() { return foo()->x != bar()->x(); }]])
 
+// Testing the 'inline' keyword
+test_program([[class foo { inline int c() { return time(); } int d() { return c(); } }; class bar { inherit foo; int c() { return 0; } } int a() { return !bar()->d(); }]],0)
+
 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)
diff --git a/src/threads.c b/src/threads.c
index 18d755981391ab48617ea706acac79700b348d6b..98f621e4d184a6b6f6af52a059a30f23086d9600 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.52 1998/01/15 05:59:43 hubbe Exp $");
+RCSID("$Id: threads.c,v 1.53 1998/01/25 08:25:16 hubbe Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -181,14 +181,22 @@ void *new_thread_func(void * data)
   THREADS_FPRINTF((stderr,"THREAD %08x INITED\n",(unsigned int)thread_id));
   if(SETJMP(back))
   {
-    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);
+    if(throw_severity < THROW_EXIT)
+    {
+      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);
+    }
+    if(throw_severity == THROW_EXIT)
+    {
+      do_exit(throw_value.u.integer);
+    }
   } else {
     INT32 args=arg.args->size;
+    back.severity=THROW_EXIT;
     push_array_items(arg.args);
     arg.args=0;
     f_call_function(args);