diff --git a/src/dmalloc.h b/src/dmalloc.h
index 15e3c699df64ca2c1a32fba7b693ea40f2ac5127..f22bed7da25058c113025c0594bedc27127b3d78 100644
--- a/src/dmalloc.h
+++ b/src/dmalloc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: dmalloc.h,v 1.24 2000/04/08 02:01:08 hubbe Exp $
+ * $Id: dmalloc.h,v 1.25 2000/04/15 05:05:28 hubbe Exp $
  */
 
 extern char *debug_xalloc(long);
@@ -10,7 +10,8 @@ extern char *debug_xalloc(long);
 struct memhdr;
 
 void dump_memhdr_locations(struct memhdr *from,
-			   struct memhdr *notfrom);
+			   struct memhdr *notfrom,
+			   int indent);
 struct memhdr *alloc_memhdr(void);
 void really_free_memhdr(struct memhdr *mh);
 void add_marks_to_memhdr(struct memhdr *to,void *ptr);
@@ -53,7 +54,7 @@ char *dmalloc_find_name(void *p);
 #define debug_malloc_touch(X) debug_malloc_update_location((X),DMALLOC_LOCATION())
 #define debug_malloc_pass(X) debug_malloc_update_location((X),DMALLOC_LOCATION())
 #define xalloc(X) ((char *)debug_malloc_pass(debug_xalloc(X)))
-void debug_malloc_dump_references(void *x);
+void debug_malloc_dump_references(void *x, int indent, int depth, int flags);
 #define dmalloc_touch(TYPE,X) ((TYPE)debug_malloc_update_location((X),DMALLOC_LOCATION()))
 #define dmalloc_touch_svalue(X) do { struct svalue *_tmp = (X); if ((X)->type <= MAX_REF_TYPE) { debug_malloc_touch(_tmp->u.refs); } } while(0)
 
@@ -70,7 +71,7 @@ struct memory_map;
 void dmalloc_set_mmap(void *ptr, struct memory_map *m);
 void dmalloc_set_mmap_template(void *ptr, struct memory_map *m);
 void dmalloc_set_mmap_from_template(void *p, void *p2);
-void dmalloc_describe_location(void *p, int offset);
+void dmalloc_describe_location(void *p, int offset, int indent);
 struct memory_map *dmalloc_alloc_mmap(char *name, int line);
 void dmalloc_add_mmap_entry(struct memory_map *m,
 			    char *name,
@@ -90,7 +91,7 @@ void dmalloc_add_mmap_entry(struct memory_map *m,
 #define DMALLOC_LINE_ARGS 
 #define DMALLOC_POS 
 #define DMALLOC_PROXY_ARGS
-#define debug_malloc_dump_references(X)
+#define debug_malloc_dump_references(X,x,y,z)
 #define xalloc debug_xalloc
 #define dbm_main main
 #define DO_IF_DMALLOC(X)
diff --git a/src/gc.c b/src/gc.c
index ac625937e73b35c97766d7841bc4fff183663b28..b5c73ad5b1e8cdac47b938f1e12e079ec7a4064e 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -29,7 +29,7 @@ struct callback *gc_evaluator_callback=0;
 
 #include "block_alloc.h"
 
-RCSID("$Id: gc.c,v 1.64 2000/04/15 01:04:01 mast Exp $");
+RCSID("$Id: gc.c,v 1.65 2000/04/15 05:05:28 hubbe Exp $");
 
 /* Run garbage collect approximate every time we have
  * 20 percent of all arrays, objects and programs is
@@ -128,18 +128,31 @@ static char *found_where="";
 static void *found_in=0;
 static int found_in_type=0;
 void *gc_svalue_location=0;
-
-#ifdef PIKE_DEBUG
 static char *fatal_after_gc=0;
-#endif
 
+#define DESCRIBE_MEM 1
+#define DESCRIBE_NO_REFS 2
+#define DESCRIBE_SHORT 4
+#define DESCRIBE_NO_DMALLOC 8
 
-void describe_location(void *memblock, int type, void *location)
+/* type == -1 means that memblock is a char* and should be
+ * really be printed..
+ */
+void describe_location(void *real_memblock,
+		       int real_type,
+		       void *location,
+		       int indent,
+		       int depth,
+		       int flags)
 {
   struct program *p;
+  void *memblock=0;
+  int type=real_type;
   if(!location) return;
 /*  fprintf(stderr,"**Location of (short) svalue: %p\n",location); */
 
+  if(real_type!=-1) real_memblock=memblock;
+
 #ifdef DEBUG_MALLOC
   if(memblock == 0 || type == -1)
   {
@@ -148,20 +161,25 @@ void describe_location(void *memblock, int type, void *location)
   }
 #endif
 
-  if(type==T_UNKNOWN) type=attempt_to_identify(memblock);
+  if(type==T_UNKNOWN)
+    type=attempt_to_identify(memblock);
 
   if(memblock)
-    fprintf(stderr,"  <from %s %p offset %ld>\n",
+    fprintf(stderr,"%*s-> from %s %p offset %ld\n",
+	    indent,"",
 	    get_name_of_type(type),
 	    memblock,
 	    ((long)location - (long)memblock));
   else
-    fprintf(stderr,"  <at location %p in unknown memblock (mmaped?)>\n",
+    fprintf(stderr,"%*s-> at location %p in unknown memblock (mmaped?)\n",
+	    indent,"",
 	    location);
 
 
-  if(memblock) describe_something(memblock,type,1);
+  if(memblock && depth>0)
+    describe_something(memblock,type,indent+2,depth-1,flags | DESCRIBE_MEM);
 
+ again:
   switch(type)
   {
     case T_UNKNOWN:
@@ -169,59 +187,66 @@ void describe_location(void *memblock, int type, void *location)
       {
 	if(memblock == (void *)p->program)
 	{
-	  fprintf(stderr,"    **In memory block for program at %p\n",p);
+	  fprintf(stderr,"%*s  **In memory block for program at %p\n",
+		  indent,"",
+		  p);
 	  memblock=p;
 	  type=T_PROGRAM;
-	  goto describe_program_location;
+	  goto again;
 	}
       }
       break;
       
     case T_PROGRAM:
-  describe_program_location:
     {
       long e;
-      struct program *p=(struct program *)memblock;
       char *ptr=(char *)location;
+      p=(struct program *)memblock;
 
       if(location == (void *)&p->prev)
-	fprintf(stderr,"    **In p->prev\n");
+	fprintf(stderr,"%*s  **In p->prev\n",indent,"");
 
       if(location == (void *)&p->next)
-	fprintf(stderr,"    **In p->next\n");
+	fprintf(stderr,"%*s  **In p->next\n",indent,"");
 
-      if(ptr >= (char *)p->inherits  && ptr<(char*)(p->inherits+p->num_inherits)) 
+      if(p->inherits &&
+	 ptr >= (char *)p->inherits  &&
+	 ptr<(char*)(p->inherits+p->num_inherits)) 
       {
 	e=((long)ptr - (long)(p->inherits)) / sizeof(struct inherit);
-	fprintf(stderr,"    **In p->inherits[%ld] (%s)\n",
+	fprintf(stderr,"%*s  **In p->inherits[%ld] (%s)\n",indent,"",
 		e,
 		p->inherits[e].name ? p->inherits[e].name->str : "no name");
 	return;
       }
 
-      if(ptr >= (char *)p->constants  && ptr<(char*)(p->constants+p->num_constants))
+      if(p->constants &&
+	 ptr >= (char *)p->constants  &&
+	 ptr<(char*)(p->constants+p->num_constants))
       {
 	e=((long)ptr - (long)(p->constants)) / sizeof(struct program_constant);
-	fprintf(stderr,"    **In p->constants[%ld] (%s)\n",
+	fprintf(stderr,"%*s  **In p->constants[%ld] (%s)\n",indent,"",
 		e,
 		p->constants[e].name ? p->constants[e].name->str : "no name");
 	return;
       }
 
 
-      if(ptr >= (char *)p->identifiers  && ptr<(char*)(p->identifiers+p->num_identifiers))
+      if(p->identifiers && 
+	 ptr >= (char *)p->identifiers  &&
+	 ptr<(char*)(p->identifiers+p->num_identifiers))
       {
 	e=((long)ptr - (long)(p->identifiers)) / sizeof(struct identifier);
-	fprintf(stderr,"    **In p->identifiers[%ld] (%s)\n",
+	fprintf(stderr,"%*s  **In p->identifiers[%ld] (%s)\n",indent,"",
 		e,
-		p->identifiers[e].name ? p->constants[e].name->str : "no name");
+		p->identifiers[e].name ? p->identifiers[e].name->str : "no name");
 	return;
       }
 
 #define FOO(NTYP,TYP,NAME) \
-    if(location == (void *)&p->NAME) fprintf(stderr,"    **In p->" #NAME "\n"); \
+    if(location == (void *)&p->NAME) fprintf(stderr,"%*s  **In p->" #NAME "\n",indent,""); \
     if(ptr >= (char *)p->NAME  && ptr<(char*)(p->NAME+p->PIKE_CONCAT(num_,NAME))) \
-      fprintf(stderr,"    **In p->" #NAME "[%ld]\n",((long)ptr - (long)(p->NAME)) / sizeof(TYP));
+      fprintf(stderr,"%*s  **In p->" #NAME "[%ld]\n",indent,"",((long)ptr - (long)(p->NAME)) / sizeof(TYP));
 #include "program_areas.h"
       
       return;
@@ -232,10 +257,10 @@ void describe_location(void *memblock, int type, void *location)
       struct object *o=(struct object *)memblock;
       struct program *p;
 
-      if(location == (void *)&o->parent) fprintf(stderr,"    **In o->parent\n");
-      if(location == (void *)&o->prog)  fprintf(stderr,"    **In o->prog\n");
-      if(location == (void *)&o->next)  fprintf(stderr,"    **In o->next\n");
-      if(location == (void *)&o->prev)  fprintf(stderr,"    **In o->prev\n");
+      if(location == (void *)&o->parent) fprintf(stderr,"%*s  **In o->parent\n",indent,"");
+      if(location == (void *)&o->prog)  fprintf(stderr,"%*s  **In o->prog\n",indent,"");
+      if(location == (void *)&o->next)  fprintf(stderr,"%*s  **In o->next\n",indent,"");
+      if(location == (void *)&o->prev)  fprintf(stderr,"%*s  **In o->prev\n",indent,"");
 
       p=o->prog;
 
@@ -243,7 +268,7 @@ void describe_location(void *memblock, int type, void *location)
       {
 	p=id_to_program(o->program_id);
 	if(p)
-	  fprintf(stderr,"    **(We are lucky, found program for destructed object)\n");
+	  fprintf(stderr,"%*s  **(We are lucky, found program for destructed object)\n",indent,"");
       }
 
       if(p)
@@ -261,14 +286,14 @@ void describe_location(void *memblock, int type, void *location)
 	    
 	    if(location == (void *)(base + id->func.offset))
 	    {
-	      fprintf(stderr,"    **In variable %s\n",id->name->str);
+	      fprintf(stderr,"%*s  **In variable %s\n",indent,"",id->name->str);
 	    }
 	  }
 
 	  if((char *)location >= base && (char *)location <= base +
 	     ( tmp.prog->storage_needed - tmp.prog->inherits[0].storage_offset ))
 	  {
-	    fprintf(stderr,"    **In storage for inherit %d",e);
+	    fprintf(stderr,"%*s  **In storage for inherit %d",indent,"",e);
 	    if(tmp.name)
 	      fprintf(stderr," (%s)",tmp.name->str);
 	    fprintf(stderr,"\n");
@@ -283,7 +308,7 @@ void describe_location(void *memblock, int type, void *location)
     {
       struct array *a=(struct array *)memblock;
       struct svalue *s=(struct svalue *)location;
-      fprintf(stderr,"    **In index %ld\n",(long)(s-ITEM(a)));
+      fprintf(stderr,"%*s  **In index %ld\n",indent,"",(long)(s-ITEM(a)));
       return;
     }
   }
@@ -292,8 +317,8 @@ void describe_location(void *memblock, int type, void *location)
 static void gdb_gc_stop_here(void *a)
 {
   fprintf(stderr,"***One ref found%s.\n",found_where?found_where:"");
-  describe_something(found_in, found_in_type, 0);
-  describe_location(found_in , found_in_type, gc_svalue_location);
+  describe_something(found_in, found_in_type, 2, 1, DESCRIBE_NO_DMALLOC);
+  describe_location(found_in , found_in_type, gc_svalue_location,2,1,0);
   fprintf(stderr,"----------end------------\n");
 }
 
@@ -338,39 +363,47 @@ int debug_gc_check(void *x, TYPE_T t, void *data)
   return ret;
 }
 
-void low_describe_something(void *a, int t, int dm)
+void low_describe_something(void *a,
+			    int t,
+			    int indent,
+			    int depth,
+			    int flags)
 {
   struct program *p=(struct program *)a;
 
+  if(depth<0) return;
+
   switch(t)
   {
     case T_FUNCTION:
       if(attempt_to_identify(a) != T_OBJECT)
       {
-	fprintf(stderr,"**Builtin function!\n");
+	fprintf(stderr,"%*s**Builtin function!\n",indent,"");
 	break;
       }
 
     case T_OBJECT:
       p=((struct object *)a)->prog;
-      fprintf(stderr,"**Parent identifier: %d\n",((struct object *)a)->parent_identifier);
-      fprintf(stderr,"**Program id: %ld\n",((struct object *)a)->program_id);
+      fprintf(stderr,"%*s**Parent identifier: %d\n",indent,"",((struct object *)a)->parent_identifier);
+      fprintf(stderr,"%*s**Program id: %ld\n",indent,"",((struct object *)a)->program_id);
 
       if( ((struct object *)a)->parent)
       {
-	fprintf(stderr,"**Describing object's parent:\n");
-	describe_something( ((struct object *)a)->parent, t, 1);
+	fprintf(stderr,"%*s**Describing object's parent:\n",indent,"");
+	describe_something( ((struct object *)a)->parent, t, indent+2,depth-1,
+			    (flags | DESCRIBE_SHORT | DESCRIBE_NO_REFS )
+			    & ~ (DESCRIBE_MEM));
       }else{
-	fprintf(stderr,"**There is no parent (any longer?)\n");
+	fprintf(stderr,"%*s**There is no parent (any longer?)\n",indent,"");
       }
       if(!p)
       {
-	fprintf(stderr,"**The object is destructed.\n");
+	fprintf(stderr,"%*s**The object is destructed.\n",indent,"");
 	p=id_to_program(((struct object *)a)->program_id);
 
 	if(!p) break;
       }
-      fprintf(stderr,"**Attempting to describe program object was instantiated from:\n");
+      fprintf(stderr,"%*s**Attempting to describe program object was instantiated from:\n",indent,"");
       
     case T_PROGRAM:
     {
@@ -378,17 +411,17 @@ void low_describe_something(void *a, int t, int dm)
       INT32 line,pos;
       int foo=0;
 
-      fprintf(stderr,"**Program id: %ld\n",(long)(p->id));
+      fprintf(stderr,"%*s**Program id: %ld\n",indent,"",(long)(p->id));
       if(p->flags & PROGRAM_HAS_C_METHODS)
       {
-	fprintf(stderr,"**The program was written in C.\n");
+	fprintf(stderr,"%*s**The program was written in C.\n",indent,"");
       }
       for(pos=0;pos<100;pos++)
       {
 	tmp=get_line(p->program+pos, p, &line);
 	if(tmp && line)
 	{
-	  fprintf(stderr,"**Location: %s:%ld\n",tmp,(long)line);
+	  fprintf(stderr,"%*s**Location: %s:%ld\n",indent,"",tmp,(long)line);
 	  foo=1;
 	  break;
 	}
@@ -398,7 +431,7 @@ void low_describe_something(void *a, int t, int dm)
 #if 0
       if(!foo && p->num_linenumbers>1 && EXTRACT_UCHAR(p->linenumbers)=='\177')
       {
-	fprintf(stderr,"**From file: %s\n",p->linenumbers+1);
+	fprintf(stderr,"%*s**From file: %s\n",indent,"",p->linenumbers+1);
 	foo=1;
       }
 #endif
@@ -406,93 +439,90 @@ void low_describe_something(void *a, int t, int dm)
       if(!foo)
       {
 	int e;
-#if 0
-	fprintf(stderr,"**identifiers:\n");
-	for(e=0;e<p->num_identifiers;e++)
-	  fprintf(stderr,"**** %s\n",p->identifiers[e].name->str);
-#else
-	fprintf(stderr,"**identifiers:\n");
+	fprintf(stderr,"%*s**identifiers:\n",indent,"");
 	for(e=0;e<p->num_identifier_references;e++)
-	  fprintf(stderr,"**** %s\n",ID_FROM_INT(p,e)->name->str);
+	  fprintf(stderr,"%*s**** %s\n",indent,"",ID_FROM_INT(p,e)->name->str);
 	
-#endif
-
-	fprintf(stderr,"**num inherits: %d\n",p->num_inherits);
+	fprintf(stderr,"%*s**num inherits: %d\n",indent,"",p->num_inherits);
       }
+
+      if(flags & DESCRIBE_MEM)
+      {
 #define FOO(NUMTYPE,TYPE,NAME) \
-      fprintf(stderr,"* " #NAME " %p[%d]\n",p->NAME,p->PIKE_CONCAT(num_,NAME));
+      fprintf(stderr,"%*s* " #NAME " %p[%d]\n",indent,"",p->NAME,p->PIKE_CONCAT(num_,NAME));
 #include "program_areas.h"
+      }
 
       break;
     }
       
     case T_ARRAY:
-      fprintf(stderr,"**Describing array:\n");
+      fprintf(stderr,"%*s**Describing array:\n",indent,"");
       debug_dump_array((struct array *)a);
       break;
 
     case T_MAPPING:
-      fprintf(stderr,"**Describing mapping:\n");
+      fprintf(stderr,"%*s**Describing mapping:\n",indent,"");
       debug_dump_mapping((struct mapping *)a);
-      fprintf(stderr,"**Describing mapping data block:\n");
-      describe_something( ((struct mapping *)a)->data, -2, dm);
+      fprintf(stderr,"%*s**Describing mapping data block:\n",indent,"");
+      describe_something( ((struct mapping *)a)->data, -2, indent+2,depth-1,flags);
       break;
 
     case T_STRING:
     {
       struct pike_string *s=(struct pike_string *)a;
-      fprintf(stderr,"**String length is %d:\n",s->len);
+      fprintf(stderr,"%*s**String length is %d:\n",indent,"",s->len);
       if(s->len>77)
       {
-	fprintf(stderr,"** \"%60s ...\"\n",s->str);
+	fprintf(stderr,"%*s** \"%60s ...\"\n",indent,"",s->str);
       }else{
-	fprintf(stderr,"** \"%s\"\n",s->str);
+	fprintf(stderr,"%*s** \"%s\"\n",indent,"",s->str);
       }
       break;
     }
   }
 }
 
-void describe_something(void *a, int t, int dm)
+void describe_something(void *a, int t, int indent, int depth, int flags)
 {
   struct program *p=(struct program *)a;
   if(!a) return;
 
   if(t==-1)
   {
-    fprintf(stderr,"**Location description: %s\n",(char *)a);
+    fprintf(stderr,"%*s**Location description: %s\n",indent,"",(char *)a);
     return;
   }
 
 #ifdef DEBUG_MALLOC
   if (((int)a) == 0x55555555) {
-    fprintf(stderr,"**Location: %p  Type: %s  Zapped pointer\n",a,
+    fprintf(stderr,"%*s**Location: %p  Type: %s  Zapped pointer\n",indent,"",a,
 	    get_name_of_type(t));
   } else
 #endif /* DEBUG_MALLOC */
   if (((int)a) & 3) {
-    fprintf(stderr,"**Location: %p  Type: %s  Missaligned address\n",a,
+    fprintf(stderr,"%*s**Location: %p  Type: %s  Missaligned address\n",indent,"",a,
 	    get_name_of_type(t));
   } else {
-    fprintf(stderr,"**Location: %p  Type: %s  Refs: %d\n",a,
+    fprintf(stderr,"%*s**Location: %p  Type: %s  Refs: %d\n",indent,"",a,
 	    get_name_of_type(t),
 	    *(INT32 *)a);
   }
 
-  low_describe_something(a,t,dm);
+  low_describe_something(a,t,indent,depth,flags);
 
 #ifdef DEBUG_MALLOC
-  if(dm)
-    debug_malloc_dump_references(a);
+  if(!(flags & DESCRIBE_NO_DMALLOC))
+    debug_malloc_dump_references(a,indent+2,depth-1,flags);
 #endif
 
   
-  fprintf(stderr,"*******************\n");
+  fprintf(stderr,"%*s*******************\n",indent,"");
 }
 
 void describe(void *x)
 {
-  describe_something(x, attempt_to_identify(x),1);
+  describe_something(x, attempt_to_identify(x), 0, 2, 0);
 }
 
 void debug_describe_svalue(struct svalue *s)
@@ -527,7 +557,7 @@ void debug_describe_svalue(struct svalue *s)
 	}
       }
   }
-  describe_something(s->u.refs,s->type,1);
+  describe_something(s->u.refs,s->type,0,2,0);
 }
 
 #endif
@@ -684,7 +714,7 @@ int debug_gc_is_referenced(void *a)
     d_flag=0;
 
     fprintf(stderr,"**Something has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)refs,(long)xrefs);
-    describe_something(a, t, 1);
+    describe_something(a, t, 0,2,0);
 
     locate_references(a);
 
@@ -728,7 +758,7 @@ int gc_external_mark3(void *a, void *in, char *where)
       {
 	fprintf(stderr,"EXTERNAL Reference to object to free%s!\n",in?(char *)in:"");
 	fprintf(stderr,"    has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)m->refs,(long)m->xrefs);
-	if(where) describe_location(0,T_UNKNOWN,where);
+	if(where) describe_location(0,T_UNKNOWN,where,4,1,0);
 	describe(a);
 	locate_references(a);
 	fprintf(stderr,"##### Continuing search for more bugs....\n");
@@ -779,7 +809,7 @@ int debug_gc_do_free(void *a)
 	      "**gc_is_referenced failed, object has %ld references,\n"
 	      "** while gc() found %ld + %ld external. (type=%d, flags=%d)\n",
 	      (long)*(INT32 *)a,(long)refs,(long)xrefs,t,m->flags);
-      describe_something(a, t, 1);
+      describe_something(a, t, 4,1,0);
 
       locate_references(a);
       
@@ -799,6 +829,7 @@ void do_gc(void)
   double tmp;
   INT32 tmp2;
   double multiplier;
+#ifdef HAVE_GETHRTIME
 #ifdef PIKE_DEBUG
 #ifdef HAVE_GETHRTIME
   hrtime_t gcstarttime;
@@ -897,6 +928,7 @@ void do_gc(void)
 
   exit_gc();
 
+  Pike_in_gc=5;
   destruct_objects_to_destruct();
   
   objects_freed -= (double) num_objects;
@@ -919,14 +951,16 @@ void do_gc(void)
 
 #ifdef PIKE_DEBUG
   if(t_flag)
+  {
+#ifdef HAVE_GETHRTIME
     fprintf(stderr,"done (freed %ld of %ld objects), %ld ms.\n",
 	    (long)(tmp2-num_objects),(long)tmp2,
-#ifdef HAVE_GETHRTIME
-	    (long)((gethrtime() - gcstarttime)/1000000)
+	    (long)((gethrtime() - gcstarttime)/1000000));
 #else
-	    0l
+    fprintf(stderr,"done (freed %ld of %ld objects)\n",
+	    (long)(tmp2-num_objects),(long)tmp2);
 #endif
-	   );
+  }
 #endif
 
 #ifdef ALWAYS_GC
diff --git a/src/gc.h b/src/gc.h
index 1015f01417c56bcfe73e6f80aa77cbd8bc81887b..76fd020560905eedb49e8a908ecee311ffa719c5 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: gc.h,v 1.28 2000/04/14 16:05:27 mast Exp $
+ * $Id: gc.h,v 1.29 2000/04/15 05:05:28 hubbe Exp $
  */
 #ifndef GC_H
 #define GC_H
@@ -48,12 +48,12 @@ struct callback *debug_add_gc_callback(callback_func call,
 				 callback_func free_func);
 void dump_gc_info(void);
 TYPE_T attempt_to_identify(void *something);
-void describe_location(void *memblock, int type, void *location);
+void describe_location(void *memblock, int type, void *location,int indent, int depth, int flags);
 void debug_gc_xmark_svalues(struct svalue *s, int num, char *fromwhere);
 TYPE_FIELD debug_gc_check_svalues(struct svalue *s, int num, TYPE_T t, void *data);
 void debug_gc_check_short_svalue(union anything *u, TYPE_T type, TYPE_T t, void *data);
 int debug_gc_check(void *x, TYPE_T t, void *data);
-void describe_something(void *a, int t, int dm);
+void describe_something(void *a, int t, int indent, int depth, int flags);
 void describe(void *x);
 void debug_describe_svalue(struct svalue *s);
 INT32 real_gc_check(void *a);
diff --git a/src/interpreter.h b/src/interpreter.h
index 436ff8462a5010bc4fa7d735bb56a24894b73df1..6b39a9fb644c989a996243f806ded3f10bb7d085 100644
--- a/src/interpreter.h
+++ b/src/interpreter.h
@@ -276,7 +276,7 @@ static int eval_instruction(unsigned char *pc)
 #ifdef DEBUG_MALLOC
 	  if (inherit->storage_offset == 0x55555555) {
 	    fprintf(stderr, "The inherit %p has been zapped!\n", inherit);
-	    debug_malloc_dump_references(inherit);
+	    debug_malloc_dump_references(inherit,0,2,0);
 	    fprintf(stderr, "It was extracted from the program %p %d\n", p, i);
 	    describe(p);
 	    fprintf(stderr, "Which was in turn taken from the object %p\n", o);
diff --git a/src/las.c b/src/las.c
index a726973154cc18f3f41e77ffc4581991384ea842..dfc198978c28f763e630039ab56c1e6c14dd9bbd 100644
--- a/src/las.c
+++ b/src/las.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: las.c,v 1.174 2000/04/06 09:03:59 hubbe Exp $");
+RCSID("$Id: las.c,v 1.175 2000/04/15 05:05:28 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -380,7 +380,7 @@ void free_all_nodes(void)
 			tmp, tmp->current_file->str, tmp->line_number,
 			tmp->token);
 
-		debug_malloc_dump_references(tmp);
+		debug_malloc_dump_references(tmp,0,2,0);
 
 		if(tmp->token==F_CONSTANT)
 		  print_tree(tmp);
diff --git a/src/main.c b/src/main.c
index 92ebcccdd423dd7ecf6ea473af93d80671443463..a71390ef52ae8122cfdbe858077047a7718c1102 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: main.c,v 1.88 2000/04/08 01:09:56 hubbe Exp $");
+RCSID("$Id: main.c,v 1.89 2000/04/15 05:05:28 hubbe Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -676,7 +676,7 @@ void low_exit_main(void)
     {
       struct program *p;
       for(p=first_program;p;p=p->next)
-	describe_something(p, T_PROGRAM, 1);
+	describe_something(p, T_PROGRAM, 0,2,0);
     }
 
 
@@ -687,7 +687,7 @@ void low_exit_main(void)
     {
       struct object *o;
       for(o=first_object;o;o=o->next)
-	describe_something(o, T_OBJECT, 1);
+	describe_something(o, T_OBJECT, 0,2,0);
     }
 
     cleanup_shared_string_table();
diff --git a/src/mapping.c b/src/mapping.c
index fd19c3f43727f12d5b02550f7405ee78e998bd07..fe77bad5d161e6715e574a40e1991cea0696c37d 100644
--- a/src/mapping.c
+++ b/src/mapping.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: mapping.c,v 1.72 2000/04/12 18:40:12 hubbe Exp $");
+RCSID("$Id: mapping.c,v 1.73 2000/04/15 05:05:28 hubbe Exp $");
 #include "main.h"
 #include "object.h"
 #include "mapping.h"
@@ -1707,7 +1707,13 @@ void check_mapping(struct mapping *m)
     fatal("Mapping ->next->prev != mapping.\n");
 
   if(m->debug_size != md->size)
-    fatal("Mapping zapping detected!\n");
+  {
+    fprintf(stderr,"--MAPPING ZAPPING, mapping:\n");
+    describe(m);
+    fprintf(stderr,"--MAPPING ZAPPING, mapping data:\n");
+    describe(md);
+    fatal("Mapping zapping detected (%d != %d)!\n",m->debug_size,md->size);
+  }
 
   if(m->prev)
   {
@@ -1858,7 +1864,7 @@ void gc_check_all_mappings(void)
 #ifdef DEBUG_MALLOC
     if (((int)m->data) == 0x55555555) {
       fprintf(stderr, "** Zapped mapping in list of active mappings!\n");
-      describe_something(m, T_MAPPING, 1);
+      describe_something(m, T_MAPPING, 0,2,0);
       fatal("Zapped mapping in list of active mappings!\n");
     }
 #endif /* DEBUG_MALLOC */
diff --git a/src/object.c b/src/object.c
index 09085831228317532d2e0ba1bfe467f0a0741a84..af08e577665adbba1e677f178baa32ad6e8425c7 100644
--- a/src/object.c
+++ b/src/object.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: object.c,v 1.108 2000/04/14 19:35:29 grubba Exp $");
+RCSID("$Id: object.c,v 1.109 2000/04/15 05:05:28 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -115,11 +115,8 @@ struct object *low_clone(struct program *p)
   add_ref(p);
   o->parent=0;
   o->parent_identifier=0;
-  o->next=first_object;
-  o->prev=0;
-  if(first_object)
-    first_object->prev=o;
-  first_object=o;
+
+  DOUBLELINK(first_object,o);
   o->refs=1;
 
 #ifdef PIKE_DEBUG
@@ -541,29 +538,25 @@ static struct callback *destruct_object_evaluator_callback =0;
  */
 void destruct_objects_to_destruct(void)
 {
+  struct object *my_list=0;
   struct object *o, *next;
 
   while((o=objects_to_destruct))
   {
-#ifdef PIKE_DEBUG
-    if(o->refs)
-      fatal("Object to be destructed grew extra references.\n");
-#endif
     /* Link object back to list of objects */
-    objects_to_destruct=o->next;
+    DOUBLEUNLINK(objects_to_destruct,o);
     
-    if(first_object)
-      first_object->prev=o;
-
-    o->next=first_object;
-    first_object=o;
-    o->prev=0;
-
+    /* link */
+    DOUBLELINK(first_object,o);
+    
+    /* call destroy, keep one ref */
     add_ref(o);
+    call_destroy(o,0);
+    
     destruct(o);
     free_object(o);
   }
-  objects_to_destruct=0;
+
   if(destruct_object_evaluator_callback)
   {
     remove_callback(destruct_object_evaluator_callback);
@@ -572,7 +565,7 @@ void destruct_objects_to_destruct(void)
 }
 
 
-/* really_free_objects:
+/* really_free_object:
  * This function is called when an object runs out of references.
  * It frees the object if it is destructed, otherwise it moves it to
  * a separate list of objects which will be destructed later.
@@ -580,6 +573,7 @@ void destruct_objects_to_destruct(void)
 
 void really_free_object(struct object *o)
 {
+  debug_malloc_touch(o);
   if(o->prog && (o->prog->flags & PROGRAM_DESTRUCT_IMMEDIATE))
   {
     add_ref(o);
@@ -587,12 +581,9 @@ void really_free_object(struct object *o)
     if(--o->refs > 0) return;
   }
 
-  if(o->prev)
-    o->prev->next=o->next;
-  else
-    first_object=o->next;
+  debug_malloc_touch(o);
 
-  if(o->next) o->next->prev=o->prev;
+  DOUBLEUNLINK(first_object,o);
 
   if(o->prog)
   {
@@ -603,9 +594,8 @@ void really_free_object(struct object *o)
 			(callback_func)destruct_objects_to_destruct,
 			0,0);
     }
-    o->next=objects_to_destruct;
-    o->prev=0;
-    objects_to_destruct=o;
+
+    DOUBLELINK(objects_to_destruct,o);
   } else {
     if(o->parent)
     {
@@ -1002,7 +992,11 @@ void cleanup_objects(void)
   {
     add_ref(o);
     if(o->prog && !(o->prog->flags & PROGRAM_NO_EXPLICIT_DESTRUCT))
+    {
+      debug_malloc_touch(o);
+      call_destroy(o,1);
       low_destruct(o,1);
+    }
     SET_NEXT_AND_FREE(o,free_object);
   }
   free_object(master_object);
@@ -1214,6 +1208,7 @@ void gc_mark_all_objects(void)
 void gc_free_all_unreferenced_objects(void)
 {
   struct object *o,*next;
+  extern int Pike_in_gc;
 
 #ifdef PIKE_DEBUG
   if(d_flag)
@@ -1232,15 +1227,15 @@ void gc_free_all_unreferenced_objects(void)
   }
 #endif
 
+  Pike_in_gc=4;  /* Allow thread switches, god help us */
+
   for(o=first_object;o;o=next)
   {
+    next=o->next;
     if(gc_do_free(o))
     {
       add_ref(o);
       call_destroy(o,0);
-      SET_NEXT_AND_FREE(o,free_object);
-    }else{
-      next=o->next;
     }
   }
 
@@ -1248,8 +1243,7 @@ void gc_free_all_unreferenced_objects(void)
   {
     if(gc_do_free(o))
     {
-      add_ref(o);
-      destruct(o);
+      low_destruct(o,1);
       SET_NEXT_AND_FREE(o,free_object);
     }else{
       next=o->next;
@@ -1481,12 +1475,18 @@ void check_object(struct object *o)
   if(o == fake_object) return;
 
   if(o->next && o->next->prev !=o)
+  {
+    describe(o);
     fatal("Object check: o->next->prev != o\n");
+  }
   
   if(o->prev)
   {
     if(o->prev->next != o)
+    {
+      describe(o);
       fatal("Object check: o->prev->next != o\n");
+    }
     
     if(o == first_object)
       fatal("Object check: o->prev !=0 && first_object == o\n");
@@ -1522,9 +1522,11 @@ void check_all_objects(void)
     SET_NEXT_AND_FREE(o,free_object);
   }
 
+#if 0
   for(o=objects_to_destruct;o;o=o->next)
     if(o->refs)
       fatal("Object to be destructed has references.\n");
+#endif
 
 }
 
diff --git a/src/pike_macros.h b/src/pike_macros.h
index 997b6a2da858c943f67c6c09d4a98e585beabc64..1382101461439f90b97d255aed1af4c780954918 100644
--- a/src/pike_macros.h
+++ b/src/pike_macros.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: pike_macros.h,v 1.14 2000/04/08 01:09:33 hubbe Exp $
+ * $Id: pike_macros.h,v 1.15 2000/04/15 05:05:28 hubbe Exp $
  */
 #ifndef MACROS_H
 #define MACROS_H
@@ -72,5 +72,27 @@
   }						\
   free_program(p);				\
 }while(0)
-  
+
+#define DOUBLELINK(first_object, o) do {	\
+  o->next=first_object;				\
+  o->prev=0;					\
+  if(first_object) first_object->prev=o;	\
+  first_object=o;				\
+}while(0)
+
+#define DOUBLEUNLINK(first_object,o) do{	\
+  if(o->prev) {					\
+    o->prev->next=o->next;			\
+  }else {					\
+    DO_IF_DEBUG(				\
+      if(first_object != o)			\
+        fatal("Linked in wrong list!\n");	\
+    )						\
+    first_object=o->next;			\
+  }						\
+						\
+  if(o->next) o->next->prev=o->prev;		\
+}while(0)
+
+
 #endif
diff --git a/src/pike_memory.c b/src/pike_memory.c
index 0e4680582a2d446549a80e2059fc9a424685b48d..14b0b1c4b6ad1f9e3a2fd1d24124473b9f0c2212 100644
--- a/src/pike_memory.c
+++ b/src/pike_memory.c
@@ -10,7 +10,7 @@
 #include "pike_macros.h"
 #include "gc.h"
 
-RCSID("$Id: pike_memory.c,v 1.64 2000/04/12 18:40:12 hubbe Exp $");
+RCSID("$Id: pike_memory.c,v 1.65 2000/04/15 05:05:28 hubbe Exp $");
 
 /* strdup() is used by several modules, so let's provide it */
 #ifndef HAVE_STRDUP
@@ -825,7 +825,7 @@ void check_pad(struct memhdr *mh, int freeok)
     if(!freeok)
     {
       fprintf(stderr,"Access to free block: %p (size %ld)!\n",mem, ~mh->size);
-      dump_memhdr_locations(mh, 0);
+      dump_memhdr_locations(mh, 0, 0);
       abort();
     }else{
       size = ~size;
@@ -1363,7 +1363,7 @@ void dmalloc_check_block_free(void *p)
   if(mh && mh->size>=0 && !(mh->flags & MEM_IGNORE_LEAK))
   {
     fprintf(stderr,"Freeing storage for small block still in use %p.\n",p);
-    debug_malloc_dump_references(p);
+    debug_malloc_dump_references(p,0,2,0);
   }
 
   mt_unlock(&debug_malloc_mutex);
@@ -1417,8 +1417,8 @@ void *__wrap_strdup(const char *s)
 
 
 void low_dump_memhdr_locations(struct memhdr *from,
-			   struct memhdr *notfrom,
-			   int indent)
+			       struct memhdr *notfrom,
+			       int indent)
 {
   struct memloc *l;
   if(!from) return;
@@ -1447,15 +1447,16 @@ void low_dump_memhdr_locations(struct memhdr *from,
 }
 
 void dump_memhdr_locations(struct memhdr *from,
-			   struct memhdr *notfrom)
+			   struct memhdr *notfrom,
+			   int indent)
 {
-  low_dump_memhdr_locations(from,notfrom, 2);
+  low_dump_memhdr_locations(from,notfrom, indent);
 }
 
-static void low_dmalloc_describe_location(struct memhdr *mh, int offset);
+static void low_dmalloc_describe_location(struct memhdr *mh, int offset, int indent);
 
 
-static void find_references_to(void *block)
+static void find_references_to(void *block, int indent, int depth, int flags)
 {
   unsigned long h;
   struct memhdr *m;
@@ -1477,9 +1478,9 @@ static void find_references_to(void *block)
 	    if(p[e] == block)
 	    {
 /*	      fprintf(stderr,"  <from %p word %d>\n",p,e); */
-	      describe_location(p,T_UNKNOWN,p+e);
+	      describe_location(p,T_UNKNOWN,p+e, indent,depth,flags);
 
-	      low_dmalloc_describe_location(m, e * sizeof(void *));
+	      low_dmalloc_describe_location(m, e * sizeof(void *), indent);
 
 	      m->flags |= MEM_WARN_ON_FREE;
 	    }
@@ -1495,7 +1496,7 @@ static void find_references_to(void *block)
 void dmalloc_find_references_to(void *block)
 {
   mt_lock(&debug_malloc_mutex);
-  find_references_to(block);
+  find_references_to(block, 2, 1, 0);
   mt_unlock(&debug_malloc_mutex);
 }
 
@@ -1505,8 +1506,6 @@ void *dmalloc_find_memblock_base(void *ptr)
   struct memhdr *m;
   char *lookfor=(char *)ptr;
 
-  mt_lock(&debug_malloc_mutex);
-
   for(h=0;h<(unsigned long)memhdr_hash_table_size;h++)
   {
     for(m=memhdr_hash_table[h];m;m=m->next)
@@ -1517,7 +1516,7 @@ void *dmalloc_find_memblock_base(void *ptr)
       
       if( ! ((sizeof(void *)-1) & (long) p ))
       {
-	if( m->data <= lookfor && lookfor < m->data + m->size)
+	if( p <= lookfor && lookfor < p + m->size)
 	{
 	  mt_unlock(&debug_malloc_mutex);
 	  return m->data;
@@ -1526,11 +1525,11 @@ void *dmalloc_find_memblock_base(void *ptr)
     }
   }
 
-  mt_unlock(&debug_malloc_mutex);
   return 0;
 }
 
-void debug_malloc_dump_references(void *x)
+/* FIXME: lock the mutex */
+void debug_malloc_dump_references(void *x, int indent, int depth, int flags)
 {
   struct memhdr *mh=my_find_memhdr(x,0);
   if(!mh) return;
@@ -1538,19 +1537,20 @@ void debug_malloc_dump_references(void *x)
   {
     if(mh->flags & MEM_IGNORE_LEAK)
     {
-      fprintf(stderr,"<<<This leak has been ignored>>>\n");
+      fprintf(stderr,"%*s<<<This leak has been ignored>>>\n",indent,"");
     }
     else if(mh->flags & MEM_REFERENCED)
     {
-      fprintf(stderr,"<<<Possibly referenced>>>\n");
-      find_references_to(x);
+      fprintf(stderr,"%*s<<<Possibly referenced>>>\n",indent,"");
+      if(!(flags & 2))
+	find_references_to(x,indent+2,depth-1,flags);
     }
     else
     {
-      fprintf(stderr,"<<<=- No known references to this block -=>>>\n");
+      fprintf(stderr,"%*s<<<=- No known references to this block -=>>>\n",indent,"");
     }
   }
-  dump_memhdr_locations(mh,0);
+  dump_memhdr_locations(mh,0, indent+2);
 }
 
 void list_open_fds(void)
@@ -1573,7 +1573,7 @@ void list_open_fds(void)
 	{
 	  fprintf(stderr,"Filedescriptor %ld\n",PTR2FD(p));
 
-	  dump_memhdr_locations(m, 0);
+	  dump_memhdr_locations(m, 0, 0);
 	}
       }
     }
@@ -1673,7 +1673,7 @@ void cleanup_memhdrs(void)
 	  }
 	}else{
 #ifdef PIKE_DEBUG
-	  describe_something(p, attempt_to_identify(p),0);
+	  describe_something(p, attempt_to_identify(p),0,2,8);
 #endif
 	}
 	mt_lock(&debug_malloc_mutex);
@@ -1691,8 +1691,8 @@ void cleanup_memhdrs(void)
 	  break;
 	}
 	
-	find_references_to(p);
-	dump_memhdr_locations(m, 0);
+	find_references_to(p,0,2,0);
+	dump_memhdr_locations(m, 0,0);
       }
     }
 
@@ -1996,7 +1996,7 @@ static void very_low_dmalloc_describe_location(struct memory_map *m,
 					       int indent)
 {
   struct memory_map_entry *e;
-  fprintf(stderr,"%*s ** In memory map %s:\n",indent,"",m->name+2);
+  fprintf(stderr,"%*s ** In memory description %s:\n",indent,"",m->name+2);
   for(e=m->entries;e;e=e->next)
   {
     if(e->offset <= offset && e->offset + e->size * e->count > offset)
@@ -2004,10 +2004,12 @@ static void very_low_dmalloc_describe_location(struct memory_map *m,
       int num=(offset - e->offset)/e->size;
       int off=offset-e->size*num-e->offset;
       fprintf(stderr,"%*s    Found in member: %s[%d] + %d (offset=%d size=%d)\n",
-	      off,
 	      indent,"",
+	      e->name,
 	      num,
-	      e->name,e->offset,e->size);
+	      off,
+	      e->offset,
+	      e->size);
 
       if(e->recur)
       {
@@ -2019,7 +2021,7 @@ static void very_low_dmalloc_describe_location(struct memory_map *m,
   }
 }
 
-static void low_dmalloc_describe_location(struct memhdr *mh, int offset)
+static void low_dmalloc_describe_location(struct memhdr *mh, int offset, int indent)
 {
   struct memloc *l;
   for(l=mh->locations;l;l=l->next)
@@ -2027,18 +2029,18 @@ static void low_dmalloc_describe_location(struct memhdr *mh, int offset)
     if(l->location[0]=='M')
     {
       struct memory_map *m = (struct memory_map *)(l->location - 1);
-      very_low_dmalloc_describe_location(m, offset,4);
+      very_low_dmalloc_describe_location(m, offset, indent);
     }
   }
 }
 
-void dmalloc_describe_location(void *p, int offset)
+void dmalloc_describe_location(void *p, int offset, int indent)
 {
   if(p)
   {
     struct memhdr *mh;
     mt_lock(&debug_malloc_mutex);
-    if((mh=my_find_memhdr(p,0))) low_dmalloc_describe_location(mh, offset);
+    if((mh=my_find_memhdr(p,0))) low_dmalloc_describe_location(mh, offset, indent);
     mt_unlock(&debug_malloc_mutex);
   }
 }
@@ -2079,7 +2081,7 @@ void dmalloc_add_mmap_entry(struct memory_map *m,
   e->count=count?count:1;
   e->next=m->entries;
   e->recur=recur;
-  e->recur=recur_offset;
+  e->recur_offset=recur_offset;
   m->entries=e;
   mt_unlock(&debug_malloc_mutex);
 }
diff --git a/src/program.c b/src/program.c
index 4504e2f16270f04adb35cd9663bdbf82dd5e993a..e6cc2a8f44f96e8144e9e29321a5c249dddb3cd2 100644
--- a/src/program.c
+++ b/src/program.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: program.c,v 1.225 2000/04/13 12:16:14 grubba Exp $");
+RCSID("$Id: program.c,v 1.226 2000/04/15 05:05:28 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -546,6 +546,30 @@ int program_function_index_compare(const void *a,const void *b)
 		    ID_FROM_INT(new_program, *(unsigned short *)b)->name);
 }
 
+#ifdef PIKE_DEBUG
+char *find_program_name(struct program *p, INT32 *line)
+{
+  INT32 pos;
+
+#ifdef DEBUG_MALLOC
+  char *tmp=dmalloc_find_name(p);
+  *line=0;
+  if(tmp) return tmp;
+#endif
+
+  /* Didn't find a given name, revert to ad-hoc method */
+	
+  for(pos=0;pos<100;pos++)
+  {
+    tmp=get_line(p->program+pos, p, line);
+    if(tmp && *line) return tmp;
+    if(pos+1>=(long)p->num_program) break;
+  }
+  *line=0;
+  return 0;
+}
+#endif
+
 void fixate_program(void)
 {
   INT32 i,e,t;
@@ -600,8 +624,23 @@ void fixate_program(void)
   {
 #define DBSTR(X) ((X)?(X)->str:"")
     int e,v;
-    struct memory_map *m=dmalloc_alloc_mmap( DBSTR(lex.current_file),
-					     lex.current_line);
+    INT32 line;
+    char *tmp;
+    struct memory_map *m=0;;
+    if(lex.current_file && 
+       lex.current_file->str &&
+       lex.current_file->len &&
+       !strcmp(lex.current_file->str,"-"))
+    {
+      m=dmalloc_alloc_mmap( DBSTR(lex.current_file), lex.current_line);
+    }
+    else if( (tmp=find_program_name(new_program, &line)) )
+    {
+      m=dmalloc_alloc_mmap( tmp, line);
+    }else{
+      m=dmalloc_alloc_mmap( "program id", new_program->id);
+    }
+
     for(e=0;e<new_program->num_inherits;e++)
     {
       struct inherit *i=new_program->inherits+e;
@@ -624,21 +663,11 @@ void fixate_program(void)
       if(i->name)
       {
 	tmp=i->name->str;
-      }else if(!(tmp=dmalloc_find_name(i->prog))){
-	/* Didn't find a given name, revert to ad-hoc method */
-	INT32 line,pos;
-	
-	for(pos=0;pos<100;pos++)
-	{
-	  tmp=get_line(i->prog->program+pos, i->prog, &line);
-	  if(tmp && line) break;
-	  if(pos+1>=(long)i->prog->num_program) break;
-	}
-	if(!(tmp && line))
-	{
-	  sprintf(buffer,"inherit[%d]",e);
-	  tmp=buffer;
-	}
+      }
+      else if(!(tmp=find_program_name(i->prog, &line)))
+      {
+	sprintf(buffer,"inherit[%d]",e);
+	tmp=buffer;
       }
       dmalloc_add_mmap_entry(m,
 			     tmp,
diff --git a/src/stralloc.c b/src/stralloc.c
index cf4e55788907253efe263cf76b5dd2b1053c8386..1110f29202e8db501e908e8a3cc7f4a41099b625 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -25,7 +25,7 @@
 #define HUGE HUGE_VAL
 #endif /*!HUGE*/
 
-RCSID("$Id: stralloc.c,v 1.81 2000/04/01 07:27:02 hubbe Exp $");
+RCSID("$Id: stralloc.c,v 1.82 2000/04/15 05:05:28 hubbe Exp $");
 
 #define BEGIN_HASH_SIZE 997
 #define MAX_AVG_LINK_LENGTH 3
@@ -258,10 +258,10 @@ static void locate_problem(int (*isproblem)(struct pike_string *))
   }
 
   DM(fprintf(stderr,"Plausible problem location(s):\n"));
-  DM(dump_memhdr_locations(yes,0));
+  DM(dump_memhdr_locations(yes,0,0));
 
   DM(fprintf(stderr,"More Plausible problem location(s):\n"));
-  DM(dump_memhdr_locations(yes,no));
+  DM(dump_memhdr_locations(yes,no,0));
 }
 
 static int has_zero_refs(struct pike_string *s)
diff --git a/src/svalue.h b/src/svalue.h
index 6af8292baa64fea547a7e52f83b52a7f270e85cb..d951060da282f3e68f62368d1c9a7cade09452a8 100644
--- a/src/svalue.h
+++ b/src/svalue.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: svalue.h,v 1.50 2000/04/12 10:39:09 grubba Exp $
+ * $Id: svalue.h,v 1.51 2000/04/15 05:05:28 hubbe Exp $
  */
 #ifndef SVALUE_H
 #define SVALUE_H
@@ -250,9 +250,20 @@ do{ \
 }while(0)
 
 #ifdef PIKE_DEBUG
+extern void describe(void *); /* defined in gc.c */
 #define check_type(T) if(T > MAX_TYPE && T!=T_LVALUE && T!=T_SHORT_LVALUE && T!=T_VOID && T!=T_DELETED && T!=T_ARRAY_LVALUE) fatal("Type error: %d\n",T)
-#define check_refs(S) if((S)->type < MAX_REF_TYPE && (!(S)->u.refs || (S)->u.refs[0] < 0)) fatal("Svalue to object without references.\n")
-#define check_refs2(S,T) if((T) < MAX_REF_TYPE && (S)->refs && (S)->refs[0] <= 0) fatal("Svalue to object without references.\n")
+
+#define check_refs(S) do {\
+ if((S)->type < MAX_REF_TYPE && (!(S)->u.refs || (S)->u.refs[0] < 0)) { \
+ describe((S)->u.refs); \
+ fatal("Svalue to object without references.\n"); \
+} }while(0)
+
+#define check_refs2(S,T) do { \
+if((T) < MAX_REF_TYPE && (S)->refs && (S)->refs[0] <= 0) {\
+ describe((S)->refs); \
+ fatal("(short) Svalue to object without references.\n"); \
+} }while(0)
 
 #ifdef DEBUG_MALLOC
 #define add_ref(X) ((INT32 *)debug_malloc_pass( &((X)->refs)))[0]++
diff --git a/src/threads.c b/src/threads.c
index 6af340da93ed76522bd28228d84ad506577b8e57..23d3b57ad61dfc067e0d864302e6fea892ca835c 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.118 2000/04/12 16:54:42 hubbe Exp $");
+RCSID("$Id: threads.c,v 1.119 2000/04/15 05:05:28 hubbe Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -579,8 +579,8 @@ TH_RETURN_TYPE new_thread_func(void * data)
       THREAD_T self = th_self();
 
       if( thread_id && !th_equal( OBJ2THREAD(thread_id)->id, self) )
-	fatal("Current thread is wrong. %x %x\n",
-	      OBJ2THREAD(thread_id)->id, self);
+	fatal("Current thread is wrong. %lx %lx\n",
+	      (long)OBJ2THREAD(thread_id)->id, (long)self);
 	
       if(thread_for_id(th_self()) != thread_id)
 	fatal("thread_for_id() (or thread_id) failed in new_thread_func! "
diff --git a/src/threads.h b/src/threads.h
index b7360482687fb2ee0ebd845ddacb1c711775926f..6e4580e8c88fab11f1d2e2ef842ef4516ea19caa 100644
--- a/src/threads.h
+++ b/src/threads.h
@@ -1,5 +1,5 @@
 /*
- * $Id: threads.h,v 1.80 2000/04/14 17:44:45 mast Exp $
+ * $Id: threads.h,v 1.81 2000/04/15 05:05:28 hubbe Exp $
  */
 #ifndef THREADS_H
 #define THREADS_H
@@ -469,7 +469,7 @@ struct thread_state {
      DO_IF_DEBUG({ \
        if(thread_for_id(th_self()) != thread_id) \
 	 fatal("thread_for_id() (or thread_id) failed! %p != %p\n",thread_for_id(th_self()),thread_id); \
-       if (Pike_in_gc == 1 || Pike_in_gc == 2) \
+       if (Pike_in_gc >0 && Pike_in_gc <4) \
 	 fatal("Threads allowed during garbage collection.\n"); \
      }) \
      if(num_threads > 1 && !threads_disabled) { \
@@ -504,7 +504,7 @@ struct thread_state {
      DO_IF_DEBUG({ \
        if(thread_for_id(th_self()) != thread_id) \
 	 fatal("thread_for_id() (or thread_id) failed! %p != %p\n",thread_for_id(th_self()),thread_id); \
-       if (Pike_in_gc == 1 || Pike_in_gc == 2) \
+       if (Pike_in_gc >0 && Pike_in_gc <4) \
 	 fatal("Threads allowed during garbage collection.\n"); \
      }) \
      if(num_threads > 1 && !threads_disabled) { \