From 3c0c282ac55f12128086d8ff4e92ee1d6187fdb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Mon, 26 Jan 1998 12:01:58 -0800
Subject: [PATCH] many minor memory leaks fixed

Rev: NT/.cvsignore:1.3
Rev: src/array.c:1.23
Rev: src/dmalloc.h:1.2
Rev: src/dynamic_buffer.c:1.7
Rev: src/dynamic_buffer.h:1.5
Rev: src/dynamic_load.c:1.23
Rev: src/error.h:1.10
Rev: src/interpret.c:1.62
Rev: src/interpret.h:1.17
Rev: src/language.yacc:1.55
Rev: src/las.c:1.45
Rev: src/las.h:1.12
Rev: src/lex.c:1.41
Rev: src/main.c:1.37
Rev: src/main.h:1.5
Rev: src/modules/Gmp/mpz_glue.c:1.25
Rev: src/modules/Image/font.c:1.27
Rev: src/object.c:1.34
Rev: src/object.h:1.14
Rev: src/operators.c:1.23
Rev: src/pike_memory.c:1.5
Rev: src/pike_types.c:1.30
Rev: src/pike_types.h:1.8
Rev: src/program.c:1.55
Rev: src/program.h:1.28
Rev: src/stralloc.c:1.25
Rev: src/stralloc.h:1.13
Rev: src/svalue.h:1.10
Rev: src/threads.c:1.54
---
 NT/.cvsignore              |   1 +
 NT/.gitignore              |   1 +
 src/array.c                |   8 +-
 src/dmalloc.h              |   6 +-
 src/dynamic_buffer.c       |   6 +-
 src/dynamic_buffer.h       |  18 ++-
 src/dynamic_load.c         |   2 +
 src/error.h                |   2 +
 src/interpret.c            |   7 +-
 src/interpret.h            |  25 ++--
 src/language.yacc          | 233 ++++++++++++++++++++++---------------
 src/las.c                  |  78 ++++++++++++-
 src/las.h                  |   5 +
 src/lex.c                  |  24 +++-
 src/main.c                 |  24 ++--
 src/main.h                 |   4 +-
 src/modules/Gmp/mpz_glue.c |  11 +-
 src/modules/Image/font.c   |   5 +-
 src/object.c               |  18 ++-
 src/object.h               |   8 +-
 src/operators.c            |   7 +-
 src/pike_memory.c          |  30 ++++-
 src/pike_types.c           |  11 +-
 src/pike_types.h           |   3 +
 src/program.c              |  20 ++--
 src/program.h              |  12 +-
 src/stralloc.c             |  11 +-
 src/stralloc.h             |  10 +-
 src/svalue.h               |   4 +-
 src/threads.c              |   4 +-
 30 files changed, 412 insertions(+), 186 deletions(-)

diff --git a/NT/.cvsignore b/NT/.cvsignore
index 0676347fc2..cb995873dd 100644
--- a/NT/.cvsignore
+++ b/NT/.cvsignore
@@ -25,3 +25,4 @@ test3.lib
 test3.mk1
 test3.tgt
 test4.c
+testsuite
diff --git a/NT/.gitignore b/NT/.gitignore
index cd2d92df2c..95aa3ebd8e 100644
--- a/NT/.gitignore
+++ b/NT/.gitignore
@@ -25,3 +25,4 @@
 /test3.mk1
 /test3.tgt
 /test4.c
+/testsuite
diff --git a/src/array.c b/src/array.c
index 577aafe4b5..fe1fe0db5d 100644
--- a/src/array.c
+++ b/src/array.c
@@ -1138,11 +1138,7 @@ node *make_node_from_array(struct array *a)
 	break;
     if(e == a->size)
     {
-      return mkefuncallnode("allocate",
-			    mknode(F_ARG_LIST,
-				   mkintnode(a->size),
-				   mkstrnode(make_shared_string("mixed"))
-				   ));
+      return mkefuncallnode("allocate",mkintnode(a->size));
     }
   }
   if(check_that_array_is_constant(a))
@@ -1562,7 +1558,7 @@ void zap_all_arrays(void)
   {
 
 #if defined(DEBUG) && defined(DEBUG_MALLOC)
-    if(verbose_debug_exit)
+    if(verbose_debug_exit && a!=&empty_array)
       debug_dump_array(a);
 #endif
     
diff --git a/src/dmalloc.h b/src/dmalloc.h
index a62fcdf1be..815a42a437 100644
--- a/src/dmalloc.h
+++ b/src/dmalloc.h
@@ -2,7 +2,6 @@
 
 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);
@@ -17,8 +16,13 @@ void *debug_malloc_update_location(void *,const char *, int);
 #define free(x) debug_free((x), __FILE__, __LINE__)
 #define strdup(x) debug_strdup((x), __FILE__, __LINE__)
 #define DO_IF_DMALLOC(X) X
+#define debug_malloc_touch(X) debug_malloc_update_location((X),__FILE__,__LINE__)
+#define debug_malloc_pass(X) debug_malloc_update_location((X),__FILE__,__LINE__)
 #else
+#define dbm_main main
 #define DO_IF_DMALLOC(X)
 extern char *xalloc(long);
 #define debug_malloc_update_location(X,Y,Z) (X)
+#define debug_malloc_touch(X)
+#define debug_malloc_pass(X) (X)
 #endif
diff --git a/src/dynamic_buffer.c b/src/dynamic_buffer.c
index 8efd326753..155be97951 100644
--- a/src/dynamic_buffer.c
+++ b/src/dynamic_buffer.c
@@ -110,7 +110,7 @@ char *simple_free_buf(void)
   return complex_free_buf().str;
 }
 
-struct pike_string *low_free_buf(dynamic_buffer *buf)
+struct pike_string *debug_low_free_buf(dynamic_buffer *buf)
 {
   struct pike_string *q;
   if(!buf->s.str) return 0;
@@ -121,14 +121,14 @@ struct pike_string *low_free_buf(dynamic_buffer *buf)
   return q;
 }
 
-struct pike_string *free_buf(void) { return low_free_buf(&buff); }
+struct pike_string *debug_free_buf(void) { return low_free_buf(&buff); }
 char *make_buf_space(INT32 space) { return low_make_buf_space(space,&buff); }
 void my_putchar(char b) { low_my_putchar(b,&buff); }
 void my_binary_strcat(const char *b,INT32 l) { low_my_binary_strcat(b,l,&buff); }
 void my_strcat(const char *b) { my_binary_strcat(b,strlen(b)); }
 void init_buf(void) { low_reinit_buf(&buff); }
 void init_buf_with_string(string s) { low_init_buf_with_string(s,&buff); }
-char *return_buf(void)
+char *debug_return_buf(void)
 {
   my_putchar(0);
   return buff.s.str;
diff --git a/src/dynamic_buffer.h b/src/dynamic_buffer.h
index d791778622..6b6892f3a6 100644
--- a/src/dynamic_buffer.h
+++ b/src/dynamic_buffer.h
@@ -34,23 +34,35 @@ 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);
-struct pike_string *low_free_buf(dynamic_buffer *buf);
-struct pike_string *free_buf(void);
+struct pike_string *debug_low_free_buf(dynamic_buffer *buf);
+struct pike_string *debug_free_buf(void);
 char *make_buf_space(INT32 space);
 void my_putchar(char b);
 void my_binary_strcat(const char *b,INT32 l);
 void my_strcat(const char *b);
 void init_buf(void);
 void init_buf_with_string(string s);
-char *return_buf(void);
+char *debug_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)
+#define low_free_buf(X) \
+  ((struct pike_string *)debug_malloc_touch(debug_low_free_buf(X)))
+
+#define free_buf() \
+  ((struct pike_string *)debug_malloc_touch(debug_free_buf()))
+
+#define return_buf() \
+  ((char *)debug_malloc_touch(debug_return_buf()))
+
 #else
 #define initialize_buf debug_initialize_buf
+#define low_free_buf debug_low_free_buf
+#define free_buf debug_free_buf
+#define return_buf debug_return_buf
 #endif
 
 #endif
diff --git a/src/dynamic_load.c b/src/dynamic_load.c
index 75565d8621..b5a9ce8463 100644
--- a/src/dynamic_load.c
+++ b/src/dynamic_load.c
@@ -157,7 +157,9 @@ void exit_dynamic_load(void)
     struct module_list *tmp=dynamic_module_list;
     dynamic_module_list=tmp->next;
     (*tmp->exit)();
+#ifndef DEBUG_MALLOC
     dlclose(tmp->module);
+#endif
     free((char *)tmp);
   }
 #endif
diff --git a/src/error.h b/src/error.h
index 9c275f159e..acc5186cfc 100644
--- a/src/error.h
+++ b/src/error.h
@@ -55,6 +55,7 @@ extern int throw_severity;
 
 #define SET_ONERROR(X,Y,Z) \
   do{ \
+     if(!recoveries) break; \
      X.func=(error_call)(Y); \
      X.arg=(void *)(Z); \
      X.previous=recoveries->onerror; \
@@ -63,6 +64,7 @@ extern int throw_severity;
 
 #ifdef DEBUG
 #define UNSET_ONERROR(X) do {\
+  if(!recoveries) break; \
   if(recoveries->onerror != &(X)) fatal("UNSET_ONERROR out of sync.\n"); \
   recoveries->onerror=(X).previous; \
   } while(0)
diff --git a/src/interpret.c b/src/interpret.c
index 1c645e071f..6db1c6c13e 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.61 1998/01/25 08:25:07 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.62 1998/01/26 19:59:53 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -1816,6 +1816,11 @@ static int o_catch(unsigned char *pc)
   }
 }
 
+void f_call_function(INT32 args)
+{
+  mega_apply(APPLY_STACK,args,0,0);
+}
+
 int apply_low_safe_and_stupid(struct object *o, INT32 offset)
 {
   JMP_BUF tmp;
diff --git a/src/interpret.h b/src/interpret.h
index 8a7d46afc1..3e69ce67ce 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -34,23 +34,23 @@ struct frame
 
 #define pop_stack() do{ free_svalue(--sp); debug_check_stack(); }while(0)
 
-#define push_program(P) do{ struct program *_=(P); sp->u.program=_; sp++->type=T_PROGRAM; }while(0)
+#define push_program(P) do{ struct program *_=(P); debug_malloc_touch(_); sp->u.program=_; sp++->type=T_PROGRAM; }while(0)
 #define push_int(I) do{ INT32 _=(I); sp->u.integer=_;sp->type=T_INT;sp++->subtype=NUMBER_NUMBER; }while(0)
-#define push_mapping(M) do{ struct mapping *_=(M); sp->u.mapping=_; sp++->type=T_MAPPING; }while(0)
-#define push_array(A) do{ struct array *_=(A); sp->u.array=_ ;sp++->type=T_ARRAY; }while(0)
-#define push_multiset(L) do{ struct multiset *_=(L); sp->u.multiset=_; sp++->type=T_MULTISET; }while(0)
-#define push_string(S) do{ struct pike_string *_=(S); sp->subtype=0; sp->u.string=_; sp++->type=T_STRING; }while(0)
-#define push_object(O) do{ struct object  *_=(O); sp->u.object=_; sp++->type=T_OBJECT; }while(0)
+#define push_mapping(M) do{ struct mapping *_=(M); debug_malloc_touch(_); sp->u.mapping=_; sp++->type=T_MAPPING; }while(0)
+#define push_array(A) do{ struct array *_=(A); debug_malloc_touch(_); sp->u.array=_ ;sp++->type=T_ARRAY; }while(0)
+#define push_multiset(L) do{ struct multiset *_=(L); debug_malloc_touch(_); sp->u.multiset=_; sp++->type=T_MULTISET; }while(0)
+#define push_string(S) do{ struct pike_string *_=(S); debug_malloc_touch(_); sp->subtype=0; sp->u.string=_; sp++->type=T_STRING; }while(0)
+#define push_object(O) do{ struct object  *_=(O); debug_malloc_touch(_); sp->u.object=_; sp++->type=T_OBJECT; }while(0)
 #define push_float(F) do{ float _=(F); sp->u.float_number=_; sp++->type=T_FLOAT; }while(0)
 #define push_text(T) push_string(make_shared_string((T)))
 #define push_constant_text(T) do{ sp->subtype=0; MAKE_CONSTANT_SHARED_STRING(sp->u.string,T); sp++->type=T_STRING; }while(0)
 
-#define ref_push_program(P) do{ struct program *_=(P); _->refs++; sp->u.program=_; sp++->type=T_PROGRAM; }while(0)
-#define ref_push_mapping(M) do{ struct mapping *_=(M); _->refs++; sp->u.mapping=_; sp++->type=T_MAPPING; }while(0)
-#define ref_push_array(A) do{ struct array *_=(A); _->refs++; sp->u.array=_ ;sp++->type=T_ARRAY; }while(0)
-#define ref_push_multiset(L) do{ struct multiset *_=(L); _->refs++; sp->u.multiset=_; sp++->type=T_MULTISET; }while(0)
-#define ref_push_string(S) do{ struct pike_string *_=(S); _->refs++; sp->subtype=0; sp->u.string=_; sp++->type=T_STRING; }while(0)
-#define ref_push_object(O) do{ struct object  *_=(O); _->refs++; sp->u.object=_; sp++->type=T_OBJECT; }while(0)
+#define ref_push_program(P) do{ struct program *_=(P); debug_malloc_touch(_); _->refs++; sp->u.program=_; sp++->type=T_PROGRAM; }while(0)
+#define ref_push_mapping(M) do{ struct mapping *_=(M); debug_malloc_touch(_); _->refs++; sp->u.mapping=_; sp++->type=T_MAPPING; }while(0)
+#define ref_push_array(A) do{ struct array *_=(A); debug_malloc_touch(_); _->refs++; sp->u.array=_ ;sp++->type=T_ARRAY; }while(0)
+#define ref_push_multiset(L) do{ struct multiset *_=(L); debug_malloc_touch(_); _->refs++; sp->u.multiset=_; sp++->type=T_MULTISET; }while(0)
+#define ref_push_string(S) do{ struct pike_string *_=(S); debug_malloc_touch(_); _->refs++; sp->subtype=0; sp->u.string=_; sp++->type=T_STRING; }while(0)
+#define ref_push_object(O) do{ struct object  *_=(O); debug_malloc_touch(_); _->refs++; sp->u.object=_; sp++->type=T_OBJECT; }while(0)
 
 #define push_svalue(S) do { struct svalue *_=(S); assign_svalue_no_free(sp,_); sp++; }while(0)
 
@@ -118,6 +118,7 @@ void reset_evaluator(void);
 struct backlog;
 void dump_backlog(void);
 void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2);
+void f_call_function(INT32 args);
 int apply_low_safe_and_stupid(struct object *o, INT32 offset);
 void safe_apply_low(struct object *o,int fun,int args);
 void safe_apply(struct object *o, char *fun ,INT32 args);
diff --git a/src/language.yacc b/src/language.yacc
index dc141a3e9b..24e77a9118 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -161,7 +161,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.54 1998/01/25 08:25:08 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.55 1998/01/26 19:59:54 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -221,12 +221,7 @@ static void __yy_memcpy(char *to, char *from, int count);
 {
   int number;
   FLOAT_TYPE fnum;
-  unsigned int address;		/* Address of an instruction */
-  struct pike_string *string;
-  char *str;
-  unsigned short type;
   struct node_s *n;
-  struct efun *efun;
 }
 
 %{
@@ -235,15 +230,6 @@ int yylex(YYSTYPE *yylval);
 
 %type <fnum> F_FLOAT
 
-%type <string> F_IDENTIFIER
-%type <string> F_STRING
-%type <string> cast
-%type <string> simple_type
-%type <string> low_string
-%type <string> optional_identifier
-%type <string> optional_rename_inherit
-%type <string> string_constant
-
 %type <number> F_ARRAY_ID
 %type <number> F_BREAK
 %type <number> F_CASE
@@ -293,6 +279,14 @@ int yylex(YYSTYPE *yylval);
 
 /* The following symbos return type information */
 
+%type <n> cast
+%type <n> simple_type
+%type <n> string_constant
+%type <n> string
+%type <n> F_STRING
+%type <n> optional_rename_inherit
+%type <n> optional_identifier
+%type <n> F_IDENTIFIER
 %type <n> assoc_pair
 %type <n> block
 %type <n> failsafe_block
@@ -336,7 +330,6 @@ int yylex(YYSTYPE *yylval);
 %type <n> sscanf
 %type <n> statement
 %type <n> statements
-%type <n> string
 %type <n> switch
 %type <n> typeof
 %type <n> unused
@@ -356,10 +349,17 @@ optional_semi_colon: /* empty */
   | ';' 
   ;
 
-string_constant: low_string
-  | string_constant '+' low_string
+string_constant: string
+  | string_constant '+' string
   {
-    $$=add_and_free_shared_strings($1,$3);
+    struct pike_string *a,*b;
+    copy_shared_string(a,$1->u.sval.u.string);
+    copy_shared_string(b,$3->u.sval.u.string);
+    free_node($1);
+    free_node($3);
+    a=add_and_free_shared_strings(a,b);
+    $$=mkstrnode(a);
+    free_string(a);
   }
   ;
 
@@ -369,13 +369,14 @@ optional_rename_inherit: ':' F_IDENTIFIER { $$=$2; }
 
 low_program_ref: string_constant
   {
-    ref_push_string($1);
-    push_string($1);
+    ref_push_string($1->u.sval.u.string);
+    ref_push_string($1->u.sval.u.string);
     ref_push_string(lex.current_file);
     SAFE_APPLY_MASTER("handle_inherit", 2);
 
     if(sp[-1].type != T_PROGRAM)
-      my_yyerror("Couldn't cast string \"%s\" to program",$1->str);
+      my_yyerror("Couldn't cast string \"%s\" to program",$1->u.sval.u.string->str);
+    free_node($1);
     $$=mksvaluenode(sp-1);
     pop_stack();
   }
@@ -384,7 +385,6 @@ low_program_ref: string_constant
     if(last_identifier)
     {
       ref_push_string(last_identifier);
-      last_identifier->refs++;
     }else{
       push_constant_text("");
     }
@@ -394,7 +394,8 @@ low_program_ref: string_constant
 
 program_ref: low_program_ref
   {
-    resolv_program($1);    
+    resolv_program($1);
+    free_node($1);
   }
   ;
       
@@ -403,10 +404,10 @@ inheritance: modifiers F_INHERIT low_program_ref optional_rename_inherit ';'
     if(!(new_program->flags & PROGRAM_PASS_1_DONE))
     {
       struct pike_string *s=sp[-1].u.string;
-      if($4) s=$4;
+      if($4) s=$4->u.sval.u.string;
       compiler_do_inherit($3,$1,s);
     }
-    if($4) free_string($4);
+    if($4) free_node($4);
     pop_n_elems(1);
     free_node($3);
   }
@@ -435,7 +436,7 @@ constant_name: F_IDENTIFIER '=' expr0
     {
       if(compiler_pass==2)
 	yyerror("Constant definition is not constant.");
-      add_constant($1,0, current_modifiers); /* Prototype */
+      add_constant($1->u.sval.u.string,0, current_modifiers); /* Prototype */
     } else {
       tmp=eval_low($3);
       if(tmp < 1)
@@ -443,12 +444,12 @@ constant_name: F_IDENTIFIER '=' expr0
 	yyerror("Error in constant definition.");
       }else{
 	pop_n_elems(tmp-1);
-	add_constant($1,sp-1,current_modifiers);
+	add_constant($1->u.sval.u.string,sp-1,current_modifiers);
 	pop_stack();
       }
     }
     if($3) free_node($3);
-    free_string($1);
+    free_node($1);
   }
   ;
 
@@ -471,11 +472,14 @@ type_or_error: simple_type
   {
     if(compiler_frame->current_type)
       free_string(compiler_frame->current_type); 
-    compiler_frame->current_type=$1;
+    copy_shared_string(compiler_frame->current_type,$1->u.sval.u.string);
+    free_node($1);
   }
   | /* empty */
   {
     yyerror("Missing type.");
+    if(compiler_frame->current_type)
+      free_string(compiler_frame->current_type); 
     copy_shared_string(compiler_frame->current_type,
 		       mixed_type_string);
   }
@@ -524,13 +528,17 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER
       push_finished_type(compiler_frame->variable[e].type);
     }
     push_type(T_FUNCTION);
-    
-    $<string>$=pop_type();
+
+    {
+      struct pike_string *s=pop_type();
+      $<n>$=mkstrnode(s);
+      free_string(s);
+    }
 
     if(compiler_pass==1)
     {
-      define_function($4,
-		      $<string>$,
+      define_function($4->u.sval.u.string,
+		      $<n>$->u.sval.u.string,
 		      $1,
 		      IDENTIFIER_PIKE_FUNCTION,
 		      0);
@@ -550,15 +558,15 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER
 	  }
       }
 
-      dooptcode($4, $10, $<string>9, $1);
+      dooptcode($4->u.sval.u.string, $10, $<n>9->u.sval.u.string, $1);
 #ifdef DEBUG
       if(recoveries && sp-evaluator_stack < recoveries->sp)
 	fatal("Stack error (underflow)\n");
 #endif
     }
     pop_compiler_frame();
-    free_string($4);
-    free_string($<string>9);
+    free_node($4);
+    free_node($<n>9);
   }
   | modifiers type_or_error name_list ';' {}
   | inheritance {}
@@ -589,14 +597,21 @@ new_arg_name: type optional_dot_dot_dot optional_identifier
       push_type(T_ARRAY);
       varargs=1;
     }
+
     if(!$3)
-      MAKE_CONSTANT_SHARED_STRING($3,"");
+    {
+      struct pike_string *s;
+      MAKE_CONSTANT_SHARED_STRING(s,"");
+      $3=mkstrnode(s);
+      free_string(s);
+    }
 
-    if(islocal($3) >= 0)
+    if(islocal($3->u.sval.u.string) >= 0)
       my_yyerror("Variable '%s' appears twice in argument list.",
-		 $3->str);
+		 $3->u.sval.u.string->str);
     
-    add_local_name($3, pop_type());
+    add_local_name($3->u.sval.u.string, pop_type());
+    free_node($3);
   }
   ;
 
@@ -631,15 +646,25 @@ optional_stars: optional_stars '*' { $$=$1 + 1; }
   | /* empty */ { $$=0; }
   ;
 
-cast: '(' type ')' { $$=pop_type(); }
+cast: '(' type ')'
+    {
+      struct pike_string *s=pop_type();
+      $$=mkstrnode(s);
+      free_string(s);
+    }
     ;
   
 type: type '*' { push_type(T_ARRAY); }
   | type2
   ;
 
-simple_type: type2 { $$=pop_type(); }
-           ;
+simple_type: type2
+  {
+    struct pike_string *s=pop_type();
+    $$=mkstrnode(s);
+    free_string(s);
+  }
+  ;
 
 type2: type2 '|' type3 { push_type(T_OR); }
   | type3
@@ -756,9 +781,9 @@ new_name: optional_stars F_IDENTIFIER
     push_finished_type(compiler_frame->current_type);
     while($1--) push_type(T_ARRAY);
     type=pop_type();
-    define_variable($2, type, current_modifiers);
+    define_variable($2->u.sval.u.string, type, current_modifiers);
     free_string(type);
-    free_string($2);
+    free_node($2);
   }
   | optional_stars F_IDENTIFIER '='
   {
@@ -766,7 +791,7 @@ new_name: optional_stars F_IDENTIFIER
     push_finished_type(compiler_frame->current_type);
     while($1--) push_type(T_ARRAY);
     type=pop_type();
-    $<number>$=define_variable($2, type, current_modifiers);
+    $<number>$=define_variable($2->u.sval.u.string, type, current_modifiers);
     free_string(type);
   }
   expr0
@@ -775,7 +800,7 @@ new_name: optional_stars F_IDENTIFIER
 		     mkcastnode(void_type_string,
 				mknode(F_ASSIGN,$5,
 				       mkidentifiernode($<number>4))));
-    free_string($2);
+    free_node($2);
   }
   ;
 
@@ -784,15 +809,17 @@ new_local_name: optional_stars F_IDENTIFIER
   {
     push_finished_type(compiler_frame->current_type);
     while($1--) push_type(T_ARRAY);
-    add_local_name($2, pop_type());
-    $$=mknode(F_ASSIGN,mkintnode(0), mklocalnode(islocal($2)));
+    add_local_name($2->u.sval.u.string, pop_type());
+    $$=mknode(F_ASSIGN,mkintnode(0), mklocalnode(islocal($2->u.sval.u.string)));
+    free_node($2);
   }
   | optional_stars F_IDENTIFIER '=' expr0
   {
     push_finished_type(compiler_frame->current_type);
     while($1--) push_type(T_ARRAY);
-    add_local_name($2, pop_type());
-    $$=mknode(F_ASSIGN,$4,mklocalnode(islocal($2)));
+    add_local_name($2->u.sval.u.string, pop_type());
+    $$=mknode(F_ASSIGN,$4,mklocalnode(islocal($2->u.sval.u.string)));
+    free_node($2);
   }
   ;
 
@@ -918,19 +945,22 @@ class: modifiers F_CLASS optional_identifier
   {
     if(!$3)
     {
+      struct pike_string *s;
       char buffer[42];
       sprintf(buffer,"__class_%ld",local_class_counter++);
-      $3=make_shared_string(buffer);
+      s=make_shared_string(buffer);
+      $3=mkstrnode(s);
+      free_string(s);
       $1|=ID_PRIVATE;
     }
     if(compiler_pass==1)
     {
-      low_start_new_program(0, $3, $1);
+      low_start_new_program(0, $3->u.sval.u.string, $1);
     }else{
       int i;
       struct program *p;
       struct identifier *id;
-      i=isidentifier($3);
+      i=isidentifier($3->u.sval.u.string);
       if(i<0)
       {
 	low_start_new_program(new_program,0,0);
@@ -943,7 +973,7 @@ class: modifiers F_CLASS optional_identifier
 	  s=PROG_FROM_INT(new_program,i)->constants+id->func.offset;
 	  if(s->type==T_PROGRAM)
 	  {
-	    low_start_new_program(s->u.program, $3, $1);
+	    low_start_new_program(s->u.program, $3->u.sval.u.string, $1);
 	  }else{
 	    yyerror("Pass 2: constant redefined!");
 	    low_start_new_program(new_program, 0,0);
@@ -963,14 +993,16 @@ class: modifiers F_CLASS optional_identifier
     else
       p=end_program();
 
-    $$=mkidentifiernode(isidentifier($3));
+    $$=mkidentifiernode(isidentifier($3->u.sval.u.string));
 
     if(!p)
       yyerror("Class definition failed.");
     else
       free_program(p);
 
-    free_string($3);
+    free_node($3);
+    check_tree($$,0);
+
   }
   ;
 
@@ -1178,8 +1210,8 @@ expr1: expr2
 expr2: expr3
   | cast expr2
   {
-    $$=mkcastnode($1,$2);
-    free_string($1);
+    $$=mkcastnode($1->u.sval.u.string,$2);
+    free_node($1);
   }
   | F_INC expr4       { $$=mknode(F_INC,$2,0); }
   | F_DEC expr4       { $$=mknode(F_DEC,$2,0); }
@@ -1218,19 +1250,18 @@ expr4: string
     { $$=mkefuncallnode("aggregate_multiset",$2); }
   | expr4 F_ARROW F_IDENTIFIER
   {
-    $$=mknode(F_ARROW,$1,mkstrnode($3));
-    free_string($3);
+    $$=mknode(F_ARROW,$1,$3);
   }
   ;
 
 idents: low_idents
   | idents '.' F_IDENTIFIER
   {
-    $$=index_node($1, $3);
+    $$=index_node($1, $3->u.sval.u.string);
     free_node($1);
     if(last_identifier) free_string(last_identifier);
-    copy_shared_string(last_identifier, $3);
-    free_string($3);
+    copy_shared_string(last_identifier, $3->u.sval.u.string);
+    free_node($3);
   }
   ;
 
@@ -1239,20 +1270,20 @@ low_idents: F_IDENTIFIER
     int i;
     struct efun *f;
     if(last_identifier) free_string(last_identifier);
-    copy_shared_string(last_identifier, $1);
-    if((i=islocal($1))>=0)
+    copy_shared_string(last_identifier, $1->u.sval.u.string);
+    if((i=islocal(last_identifier))>=0)
     {
       $$=mklocalnode(i);
-    }else if((i=isidentifier($1))>=0){
+    }else if((i=isidentifier(last_identifier))>=0){
       $$=mkidentifiernode(i);
-    }else if(!($$=find_module_identifier($1))){
+    }else if(!($$=find_module_identifier(last_identifier))){
       $$=0;
       if(!num_parse_error)
       {
 	if(get_master())
 	   {
-	     reference_shared_string($1);
-	     push_string($1);
+	     reference_shared_string(last_identifier);
+	     push_string(last_identifier);
 	     ref_push_string(lex.current_file);
 	     SAFE_APPLY_MASTER("resolv", 2);
 	
@@ -1266,7 +1297,7 @@ low_idents: F_IDENTIFIER
 	     else if(IS_ZERO(sp-1) && sp[-1].subtype==1)
 	     {
 	       if(compiler_pass==2)
-		 my_yyerror("'%s' undefined.", $1->str);
+		 my_yyerror("'%s' undefined.", last_identifier->str);
 	       else
 		 $$=mknode(F_UNDEFINED,0,0);
 	     }else{
@@ -1276,14 +1307,14 @@ low_idents: F_IDENTIFIER
 	   }else{
 	     if(compiler_pass==2)
 	     {
-	       my_yyerror("'%s' undefined.", $1->str);
+	       my_yyerror("'%s' undefined.", last_identifier->str);
 	     }else{
 	       $$=mknode(F_UNDEFINED,0,0);
 	     }
 	   }
       }
     }
-    free_string($1);
+    free_node($1);
   }
   | F_PREDEF F_COLON_COLON F_IDENTIFIER
   {
@@ -1295,27 +1326,30 @@ low_idents: F_IDENTIFIER
 #endif /* __CHECKER__ */
     tmp.u.mapping=get_builtin_constants();
     tmp2=mkconstantsvaluenode(&tmp);
-    $$=index_node(tmp2, $3);
+    $$=index_node(tmp2, $3->u.sval.u.string);
     free_node(tmp2);
-    free_string($3);
+    free_node($3);
   }
   | F_IDENTIFIER F_COLON_COLON F_IDENTIFIER
   {
     int f;
     struct reference *idp;
 
-    f=reference_inherited_identifier($1,$3);
+    f=reference_inherited_identifier($1->u.sval.u.string,
+				     $3->u.sval.u.string);
     idp=new_program->identifier_references+f;
     if (f<0)
     {
-      my_yyerror("Undefined identifier %s::%s", $1->str,$3->str);
+      my_yyerror("Undefined identifier %s::%s", 
+		 $1->u.sval.u.string->str,
+		 $3->u.sval.u.string->str);
       $$=mkintnode(0);
     } else {
       $$=mkidentifiernode(f);
     }
 
-    free_string($1);
-    free_string($3);
+    free_node($1);
+    free_node($3);
   }
   | F_COLON_COLON F_IDENTIFIER
   {
@@ -1325,7 +1359,7 @@ low_idents: F_IDENTIFIER
     for(e=1;e<(int)new_program->num_inherits;e++)
     {
       if(new_program->inherits[e].inherit_level!=1) continue;
-      i=low_reference_inherited_identifier(e,$2);
+      i=low_reference_inherited_identifier(e,$2->u.sval.u.string);
       if(i==-1) continue;
       if($$)
       {
@@ -1340,7 +1374,7 @@ low_idents: F_IDENTIFIER
     }else{
       if($$->token==F_ARG_LIST) $$=mkefuncallnode("aggregate",$$);
     }
-    free_string($2);
+    free_node($2);
   }
   ;
 
@@ -1374,14 +1408,13 @@ gauge: F_GAUGE catch_arg
 
 typeof: F_TYPEOF '(' expr0 ')'
   {
+    struct pike_string *s;
     node *tmp;
     tmp=mknode(F_ARG_LIST,$3,0);
-    if($3 && $3->type)
-    {
-       $$=mkstrnode(describe_type($3->type));
-    }else{
-       $$=mkstrnode(describe_type(mixed_type_string));
-    }
+
+    s=describe_type( $3 && $3->type ? $3->type : mixed_type_string);
+    $$=mkstrnode(s);
+    free_string(s);
     free_node(tmp);
   } ;
  
@@ -1400,24 +1433,29 @@ sscanf: F_SSCANF '(' expr0 ',' expr0 lvalue_list ')'
 lvalue: expr4
   | type F_IDENTIFIER
   {
-    add_local_name($2,pop_type());
-    $$=mklocalnode(islocal($2));
+    add_local_name($2->u.sval.u.string,pop_type());
+    $$=mklocalnode(islocal($2->u.sval.u.string));
+    free_node($2);
   }
 
 lvalue_list: /* empty */ { $$ = 0; }
   | ',' lvalue lvalue_list { $$ = mknode(F_LVALUE_LIST,$2,$3); }
   ;
 
-low_string: F_STRING 
-  | low_string F_STRING
+string: F_STRING 
+  | string F_STRING
   {
-    $$=add_and_free_shared_strings($1,$2);
+    struct pike_string *a,*b;
+    copy_shared_string(a,$1->u.sval.u.string);
+    copy_shared_string(b,$2->u.sval.u.string);
+    free_node($1);
+    free_node($2);
+    a=add_and_free_shared_strings(a,b);
+    $$=mkstrnode(a);
+    free_string(a);
   }
   ;
 
-string: low_string { $$=mkstrnode($1); free_string($1); } ;
-
-
 %%
 
 void yyerror(char *str)
@@ -1456,10 +1494,11 @@ void yyerror(char *str)
   }
 }
 
-/* argument must be a shared string (no need to free it) */
+/* argument must be a shared string */
 void add_local_name(struct pike_string *str,
 		    struct pike_string *type)
 {
+  reference_shared_string(str);
   if (compiler_frame->current_number_of_locals == MAX_LOCAL)
   {
     yyerror("Too many local variables");
diff --git a/src/las.c b/src/las.c
index b876d4e1b0..26a0e69bc5 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.44 1998/01/26 02:34:50 grubba Exp $");
+RCSID("$Id: las.c,v 1.45 1998/01/26 19:59:54 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -73,9 +73,45 @@ int cdr_is_node(node *n)
   }
 }
 
+#ifdef DEBUG
+void check_tree(node *n, int depth)
+{
+  if(!d_flag) return;
+  if(!n) return;
+  if(n->token==USHRT_MAX)
+    fatal("Free node in tree.\n");
+
+  if(!(depth & 1023))
+  {
+    node *q;
+    for(q=n->parent;q;q=q->parent)
+      if(q->parent==n)
+	fatal("Cyclic node structure found.\n");
+  }
+  depth++;
+
+  if(car_is_node(n))
+  {
+    if(CAR(n)->parent != n)
+      fatal("Parent is wrong.\n");
+
+    check_tree(CAR(n),depth);
+  }
+
+  if(cdr_is_node(n))
+  {
+    if(CDR(n)->parent != n)
+      fatal("Parent is wrong.\n");
+
+    check_tree(CDR(n),depth);
+  }
+}
+#endif
+
 INT32 count_args(node *n)
 {
   int a,b;
+  check_tree(n,0);
   if(!n) return 0;
   switch(n->token)
   {
@@ -129,6 +165,8 @@ struct pike_string *find_return_type(node *n)
 {
   struct pike_string *a,*b;
 
+  check_tree(n,0);
+
   if(!n) return 0;
   if(!(n->tree_info & OPT_RETURN)) return 0;
   if(car_is_node(n))
@@ -169,9 +207,10 @@ void free_all_nodes()
     struct node_chunk *tmp2;
     int e=0;
 
-
+#ifndef DEBUG
     if(cumulative_parse_error)
     {
+#endif
       
       for(tmp2=node_chunks;tmp2;tmp2=tmp2->next) e+=NODES;
       for(tmp=free_nodes;tmp;tmp=CAR(tmp)) e--;
@@ -192,7 +231,9 @@ void free_all_nodes()
 #ifdef DEBUG
 	      if(!cumulative_parse_error)
 	      {
-		fprintf(stderr,"Free node at %p.\n",tmp);
+		fprintf(stderr,"Free node at %p, (%s:%d) (token=%d).\n",tmp, tmp->current_file->str, tmp->line_number, tmp->token);
+		if(tmp->token==F_CONSTANT)
+		  print_tree(tmp);
 	      }
 	      else
 #endif
@@ -201,6 +242,7 @@ void free_all_nodes()
 		/* Make sure we don't free any nodes twice */
 		if(car_is_node(tmp)) CAR(tmp)=0;
 		if(cdr_is_node(tmp)) CDR(tmp)=0;
+		debug_malloc_touch(tmp->type);
 		free_node(tmp);
 	      }
 	    }
@@ -211,7 +253,9 @@ void free_all_nodes()
 	  fatal("Failed to free %d nodes when compiling!\n",e2);
 #endif
       }
+#ifndef DEBUG
     }
+#endif
     while(node_chunks)
     {
       tmp2=node_chunks;
@@ -242,6 +286,9 @@ void free_node(node *n)
   }
   n->token=USHRT_MAX;
   if(n->type) free_string(n->type);
+#ifdef DEBUG
+  if(n->current_file) free_string(n->current_file);
+#endif
   CAR(n)=free_nodes;
   free_nodes=n;
 }
@@ -267,6 +314,9 @@ static node *mkemptynode(void)
   free_nodes=CAR(res);
   res->token=0;
   res->line_number=lex.current_line;
+#ifdef DEBUG
+  copy_shared_string(res->current_file, lex.current_file);
+#endif
   res->type=0;
   res->node_info=0;
   res->tree_info=0;
@@ -277,6 +327,8 @@ static node *mkemptynode(void)
 node *mknode(short token,node *a,node *b)
 {
   node *res;
+  check_tree(a,0);
+  check_tree(b,0);
   res = mkemptynode();
   CAR(res) = a;
   CDR(res) = b;
@@ -342,7 +394,11 @@ node *mknode(short token,node *a,node *b)
   if(b) b->parent = res;
 
   if(!num_parse_error && compiler_pass==2)
+  {
+    check_tree(res,0);
     optimize(res);
+    check_tree(res,0);
+  }
 
 #ifdef DEBUG
   if(d_flag > 3)
@@ -454,6 +510,7 @@ node *mkidentifiernode(int i)
   CDR(res)=0;
 #endif
   res->u.number = i;
+  check_tree(res,0);
   return res;
 }
 
@@ -505,6 +562,8 @@ void resolv_constant(node *n)
   struct program *p;
   INT32 numid;
 
+  check_tree(n,0);
+
   if(!n)
   {
     push_int(0);
@@ -562,6 +621,8 @@ void resolv_constant(node *n)
 
 void resolv_program(node *n)
 {
+  check_tree(n,0);
+
   resolv_constant(n);
   switch(sp[-1].type)
   {
@@ -595,6 +656,9 @@ node *index_node(node *n, struct pike_string * id)
 {
   node *ret;
   JMP_BUF tmp;
+
+  check_tree(n,0);
+
   if(SETJMP(tmp))
   {
     ONERROR tmp;
@@ -644,6 +708,9 @@ node *index_node(node *n, struct pike_string * id)
 
 int node_is_eq(node *a,node *b)
 {
+  check_tree(a,0);
+  check_tree(b,0);
+
   if(a == b) return 1;
   if(!a || !b) return 0;
   if(a->token != b->token) return 0;
@@ -737,6 +804,7 @@ node *mksvaluenode(struct svalue *s)
 node *copy_node(node *n)
 {
   node *b;
+  check_tree(n,0);
   if(!n) return n;
   switch(n->token)
   {
@@ -989,6 +1057,7 @@ static void low_print_tree(node *foo,int needlval)
 
 void print_tree(node *n)
 {
+  check_tree(n,0);
   low_print_tree(n,0);
   printf("\n");
   fflush(stdout);
@@ -1540,6 +1609,7 @@ static void optimize(node *n)
       }
     }
     fix_type_field(n);
+    debug_malloc_touch(n->type);
 
 #ifdef DEBUG
     if(l_flag > 3 && n)
@@ -2153,6 +2223,8 @@ int dooptcode(struct pike_string *name,
   int args, vargs, ret;
   struct svalue *foo;
 
+  check_tree(n,0);
+
 #ifdef DEBUG
   if(a_flag > 1)
     fprintf(stderr,"Doing function '%s' at %x\n",name->str,PC);
diff --git a/src/las.h b/src/las.h
index c6ca978291..43c2b9b618 100644
--- a/src/las.h
+++ b/src/las.h
@@ -60,6 +60,7 @@ struct compiler_frame
 /* Prototypes begin here */
 int car_is_node(node *n);
 int cdr_is_node(node *n);
+void check_tree(node *n, int depth);
 INT32 count_args(node *n);
 struct pike_string *find_return_type(node *n);
 struct node_chunk;
@@ -117,4 +118,8 @@ int dooptcode(struct pike_string *name,
 #define INHERIT(i) (new_program->inherits+(i))
 #define PC (new_program->num_program)
 
+#ifndef DEBUG
+#define check_tree(X,Y)
+#endif
+
 #endif
diff --git a/src/lex.c b/src/lex.c
index c62b6ab02b..8dc93d78c4 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.40 1998/01/25 08:25:09 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.41 1998/01/26 19:59:55 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -539,8 +539,12 @@ static int yylex2(YYSTYPE *yylval)
       return F_NUMBER;
 	
     case '"':
-      yylval->string=readstring();
+    {
+      struct pike_string *s=readstring();
+      yylval->n=mkstrnode(s);
+      free_string(s);
       return F_STRING;
+    }
   
     case ':':
       if(GOBBLE(':')) return F_COLON_COLON;
@@ -735,8 +739,12 @@ static int yylex2(YYSTYPE *yylval)
 	break;
       }
 
-      yylval->string=make_shared_string(tmp+offset);
-      return F_IDENTIFIER;
+      {
+	struct pike_string *s=make_shared_string(tmp+offset);
+	yylval->n=mkstrnode(s);
+	free_string(s);
+	return F_IDENTIFIER;
+      }
     }
 
   
@@ -855,8 +863,12 @@ static int yylex2(YYSTYPE *yylval)
 	  break;
 	  }
 	}
-	yylval->string=make_shared_binary_string(buf,len);
-	return F_IDENTIFIER;
+	{
+	  struct pike_string *tmp=make_shared_binary_string(buf,len);
+	  yylval->n=mkstrnode(tmp);
+	  free_string(tmp);
+	  return F_IDENTIFIER;
+	}
       }else{
 	char buff[100];
 	sprintf(buff, "Illegal character (hex %02x) '%c'", c, c);
diff --git a/src/main.c b/src/main.c
index a64871a7f4..156d0e17e7 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.36 1998/01/25 09:15:47 hubbe Exp $");
+RCSID("$Id: main.c,v 1.37 1998/01/26 19:59:56 hubbe Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -69,7 +69,7 @@ struct callback *add_exit_callback(callback_func call,
   return add_to_callback(&exit_callbacks, call, arg, free_func);
 }
 
-int main(int argc, char **argv)
+int dbm_main(int argc, char **argv)
 {
   JMP_BUF back;
   int e, num, do_backend;
@@ -304,9 +304,13 @@ int main(int argc, char **argv)
   UNSETJMP(back);
 
   do_exit(num);
+  return num; /* avoid warning */
 }
 
-void do_exit(int num)
+#undef ATTRIBUTE
+#define ATTRIBUTE(X)
+
+void do_exit(int num) ATTRIBUTE((noreturn))
 {
   call_callback(&exit_callbacks, (void *)0);
   free_callback(&exit_callbacks);
@@ -361,7 +365,7 @@ void low_exit_main(void)
     INT32 num,size,recount=0;
 
     count_memory_in_arrays(&num, &size);
-    if(num || size)
+    if(num)
     {
       recount++;
       fprintf(stderr,"Arrays left: %d (%d bytes) (zapped)\n",num,size);
@@ -370,7 +374,7 @@ void low_exit_main(void)
     zap_all_arrays();
 
     count_memory_in_mappings(&num, &size);
-    if(num || size)
+    if(num)
     {
       recount++;
       fprintf(stderr,"Mappings left: %d (%d bytes) (zapped)\n",num,size);
@@ -379,7 +383,7 @@ void low_exit_main(void)
     zap_all_mappings();
 
     count_memory_in_multisets(&num, &size);
-    if(num || size)
+    if(num)
       fprintf(stderr,"Multisets left: %d (%d bytes)\n",num,size);
 
 
@@ -398,7 +402,7 @@ void low_exit_main(void)
     
 
     count_memory_in_programs(&num, &size);
-    if(num || size)
+    if(num)
       fprintf(stderr,"Programs left: %d (%d bytes)\n",num,size);
 
     {
@@ -411,13 +415,9 @@ void low_exit_main(void)
 
 
     count_memory_in_objects(&num, &size);
-    if(num || size)
+    if(num)
       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
diff --git a/src/main.h b/src/main.h
index 64e65a9927..54698c0a6d 100644
--- a/src/main.h
+++ b/src/main.h
@@ -17,8 +17,8 @@ struct callback *add_post_master_callback(callback_func call,
 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);
+int dbm_main(int argc, char **argv);
+void do_exit(int num) ATTRIBUTE((noreturn));
 void low_init_main(void);
 void exit_main(void);
 void init_main(void);
diff --git a/src/modules/Gmp/mpz_glue.c b/src/modules/Gmp/mpz_glue.c
index 56916f4e7f..116835f98f 100644
--- a/src/modules/Gmp/mpz_glue.c
+++ b/src/modules/Gmp/mpz_glue.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: mpz_glue.c,v 1.24 1997/10/29 11:20:41 hubbe Exp $");
+RCSID("$Id: mpz_glue.c,v 1.25 1998/01/26 20:01:17 hubbe Exp $");
 #include "gmp_machine.h"
 
 #if !defined(HAVE_LIBGMP)
@@ -297,8 +297,15 @@ static void mpzmod_cast(INT32 args)
   error("mpz->cast() to other type than string, int or float.\n");
 }
 
+#ifdef DEBUG_MALLOC
+#define get_mpz(X,Y) \
+ (debug_get_mpz((X),(Y)),( (X)->type==T_OBJECT? debug_malloc_touch((X)->u.object) :0 ),debug_get_mpz((X),(Y)))
+#else
+#define get_mpz debug_get_mpz 
+#endif
+
 /* Converts an svalue, located on the stack, to an mpz object */
-static MP_INT *get_mpz(struct svalue *s, int throw_error)
+static MP_INT *debug_get_mpz(struct svalue *s, int throw_error)
 {
 #define ERROR(x) if (throw_error) error(x)
   struct object *o;
diff --git a/src/modules/Image/font.c b/src/modules/Image/font.c
index a21aa39e44..9251e6b5b0 100644
--- a/src/modules/Image/font.c
+++ b/src/modules/Image/font.c
@@ -1,4 +1,4 @@
-/* $Id: font.c,v 1.26 1998/01/16 22:09:10 grubba Exp $ */
+/* $Id: font.c,v 1.27 1998/01/26 20:01:58 hubbe Exp $ */
 #include <config.h>
 
 #define SPACE_CHAR 'i'
@@ -6,7 +6,7 @@
 /*
 **! module Image
 **! note
-**!	$Id: font.c,v 1.26 1998/01/16 22:09:10 grubba Exp $
+**!	$Id: font.c,v 1.27 1998/01/26 20:01:58 hubbe Exp $
 **! class font
 **!
 **! note
@@ -134,6 +134,7 @@ Kerningtable types:
 #include <sys/mman.h>
 #endif
 
+#include "dmalloc.h"
 
 static struct program *font_program;
 extern struct program *image_program;
diff --git a/src/object.c b/src/object.c
index 3ea12bf304..3360b32e3a 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.33 1998/01/25 08:25:12 hubbe Exp $");
+RCSID("$Id: object.c,v 1.34 1998/01/26 19:59:56 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -128,11 +128,20 @@ static void call_pike_initializers(struct object *o, int args)
   pop_stack();
 }
 
-struct object *clone_object(struct program *p, int args)
+void do_free_object(struct object *o)
 {
+  free_object(o);
+}
+
+struct object *debug_clone_object(struct program *p, int args)
+{
+  ONERROR tmp;
   struct object *o=low_clone(p);
+  SET_ONERROR(tmp, do_free_object, o);
+  debug_malloc_touch(o);
   call_c_initializers(o);
   call_pike_initializers(o,args);
+  UNSET_ONERROR(tmp);
   return o;
 }
 
@@ -141,12 +150,16 @@ struct object *parent_clone_object(struct program *p,
 				   int parent_identifier,
 				   int args)
 {
+  ONERROR tmp;
   struct object *o=low_clone(p);
+  SET_ONERROR(tmp, do_free_object, o);
+  debug_malloc_touch(o);
   o->parent=parent;
   parent->refs++;
   o->parent_identifier=parent_identifier;
   call_c_initializers(o);
   call_pike_initializers(o,args);
+  UNSET_ONERROR(tmp);
   return o;
 }
 
@@ -202,6 +215,7 @@ struct object *get_master(void)
     }
   }
   master_object=low_clone(master_program);
+  debug_malloc_touch(master_object);
 
   call_c_initializers(master_object);
   call_pike_initializers(master_object,0);
diff --git a/src/object.h b/src/object.h
index 04aea59f01..ee127e8bc8 100644
--- a/src/object.h
+++ b/src/object.h
@@ -41,7 +41,7 @@ extern struct program *master_program;
 /* Prototypes begin here */
 void setup_fake_object(void);
 struct object *low_clone(struct program *p);
-struct object *clone_object(struct program *p, int args);
+struct object *debug_clone_object(struct program *p, int args);
 struct object *parent_clone_object(struct program *p,
 				   struct object *parent,
 				   int parent_identifier,
@@ -84,5 +84,11 @@ void gc_free_all_unreferenced_objects(void);
 void count_memory_in_objects(INT32 *num_, INT32 *size_);
 /* Prototypes end here */
 
+#ifdef MALLOC_DEBUG
+#define clone_object(X,Y) ((struct object *)debug_malloc_touch(debug_clone_object((X),(Y))))
+#else
+#define clone_object debug_clone_object
+#endif
+
 #endif /* OBJECT_H */
 
diff --git a/src/operators.c b/src/operators.c
index 504471bfa0..fa7b28b113 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -5,7 +5,7 @@
 \*/
 #include <math.h>
 #include "global.h"
-RCSID("$Id: operators.c,v 1.22 1998/01/13 22:56:47 hubbe Exp $");
+RCSID("$Id: operators.c,v 1.23 1998/01/26 19:59:57 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -1418,11 +1418,6 @@ static int generate_sizeof(node *n)
   return 1;
 }
 
-void f_call_function(INT32 args)
-{
-  mega_apply(APPLY_STACK,args,0,0);
-}
-
 static int generate_call_function(node *n)
 {
   node **arg;
diff --git a/src/pike_memory.c b/src/pike_memory.c
index 5b4b88783d..102443801f 100644
--- a/src/pike_memory.c
+++ b/src/pike_memory.c
@@ -478,6 +478,7 @@ struct memloc_block
 
 static struct memloc_block *memloc_blocks=0;
 static struct memloc *free_memlocs=0;
+static struct memhdr no_leak_memlocs;
 
 static struct memloc *alloc_memloc(void)
 {
@@ -534,6 +535,15 @@ static void add_location(struct memhdr *mh, const char *fn, int line)
   mh->locations=ml;
 }
 
+static int find_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 1;
+  return 0;
+}
+
 static void make_memhdr(void *p, int s, const char *fn, int line)
 {
   struct memhdr *mh=alloc_memhdr();
@@ -563,6 +573,7 @@ static int remove_memhdr(void *p)
       struct memloc *ml;
       while((ml=mh->locations))
       {
+	add_location(&no_leak_memlocs, ml->filename, ml->line);
 	mh->locations=ml->next;
 	ml->next=free_memlocs;
 	free_memlocs=ml;
@@ -655,9 +666,15 @@ static void cleanup_memhdrs()
       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);
+	fprintf(stderr, "LEAK: (%p) %d bytes\n",m->data, m->size);
 	for(l=m->locations;l;l=l->next)
-	  fprintf(stderr,"  *** %s:%d (%d times)\n",l->filename, l->line, l->times);
+	  fprintf(stderr,"  *** %s:%d (%d times) %s\n",
+		  l->filename,
+		  l->line,
+		  l->times,
+		  find_location(&no_leak_memlocs,
+				l->filename,
+				l->line) ? "" : " *");
       }
     }
   }
@@ -672,9 +689,12 @@ int main(int argc, char *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);
+  if(p)
+  {
+    struct memhdr *mh;
+    if((mh=find_memhdr(p)))
+      add_location(mh, fn, line);
+  }
   return p;
 }
 
diff --git a/src/pike_types.c b/src/pike_types.c
index f83fc612bb..c19dd598b8 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.29 1998/01/25 08:25:13 hubbe Exp $");
+RCSID("$Id: pike_types.c,v 1.30 1998/01/26 19:59:58 hubbe Exp $");
 #include <ctype.h>
 #include "svalue.h"
 #include "pike_types.h"
@@ -914,9 +914,14 @@ int match_types(struct pike_string *a,struct pike_string *b)
 }
 
 
+#ifdef DEBUG_MALLOC
+#define low_index_type(X,Y) ((struct pike_string *)debug_malloc_touch(debug_low_index_type((X),(Y))))
+#else
+#define low_index_type debug_low_index_type
+#endif
 
 /* FIXME, add the index */
-static struct pike_string *low_index_type(char *t, node *n)
+static struct pike_string *debug_low_index_type(char *t, node *n)
 {
   switch(EXTRACT_UCHAR(t++))
   {
@@ -969,6 +974,8 @@ static struct pike_string *low_index_type(char *t, node *n)
     if(!a) return b;
     push_finished_type(b);
     push_finished_type(a);
+    free_string(a);
+    free_string(b);
     push_type(T_OR);
     return pop_unfinished_type();
   }
diff --git a/src/pike_types.h b/src/pike_types.h
index 00646b53a4..0c449555f2 100644
--- a/src/pike_types.h
+++ b/src/pike_types.h
@@ -14,6 +14,9 @@ struct node_s
   INT16 line_number;
   INT16 node_info;
   INT16 tree_info;
+#ifdef DEBUG
+  struct pike_string *current_file;
+#endif
   struct pike_string *type;
   struct node_s *parent;
   union 
diff --git a/src/program.c b/src/program.c
index 3c5ea79646..546f989a33 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.54 1998/01/25 08:25:14 hubbe Exp $");
+RCSID("$Id: program.c,v 1.55 1998/01/26 19:59:59 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -478,9 +478,14 @@ void really_free_program(struct program *p)
 
   for(e=1; e<p->num_inherits; e++)
   {
-    free_program(p->inherits[e].prog);
-    if(p->inherits[e].parent)
-      free_object(p->inherits[e].parent);
+    if(p->inherits[e].name)
+      free_string(p->inherits[e].name);
+    if(e)
+    {
+      free_program(p->inherits[e].prog);
+      if(p->inherits[e].parent)
+	free_object(p->inherits[e].parent);
+    }
   }
 
   if(p->prev)
@@ -777,7 +782,7 @@ struct program *end_first_pass(int finish)
 /*
  * Finish this program, returning the newly built program
  */
-struct program *end_program(void)
+struct program *debug_end_program(void)
 {
   return end_first_pass(1);
 }
@@ -937,8 +942,7 @@ void low_inherit(struct program *p,
     {
       if(e==0)
       {
-	inherit.name=name;
-	reference_shared_string(name);
+	copy_shared_string(inherit.name,name);
       }
       else if(inherit.name)
       {
@@ -1397,7 +1401,7 @@ int add_function_constant(char *name, void (*cfun)(INT32), char * type, INT16 fl
 }
 
 
-int end_class(char *name, INT32 flags)
+int debug_end_class(char *name, INT32 flags)
 {
   INT32 ret;
   struct svalue tmp;
diff --git a/src/program.h b/src/program.h
index de26fe64c2..e18f49936d 100644
--- a/src/program.h
+++ b/src/program.h
@@ -240,7 +240,7 @@ void really_free_program(struct program *p);
 void dump_program_desc(struct program *p);
 void check_program(struct program *p);
 struct program *end_first_pass(int finish);
-struct program *end_program(void);
+struct program *debug_end_program(void);
 SIZE_T add_storage(SIZE_T size);
 void set_init_callback(void (*init)(struct object *));
 void set_exit_callback(void (*exit)(struct object *));
@@ -301,7 +301,7 @@ int add_program_constant(char *name,
 			 struct program *p,
 			 INT32 flags);
 int add_function_constant(char *name, void (*cfun)(INT32), char * type, INT16 flags);
-int end_class(char *name, INT32 flags);
+int debug_end_class(char *name, INT32 flags);
 INT32 define_function(struct pike_string *name,
 		      struct pike_string *type,
 		      INT16 flags,
@@ -343,3 +343,11 @@ void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2)));
 
 
 #endif
+
+#ifdef DEBUG_MALLOC
+#define end_program() ((struct program *)debug_malloc_touch(debug_end_program()))
+#define end_class(NAME, FLAGS) do { debug_malloc_touch(new_program); debug_end_class(NAME, FLAGS); }while(0)
+#else
+#define end_class debug_end_class
+#define end_program debug_end_program
+#endif
diff --git a/src/stralloc.c b/src/stralloc.c
index 576674f22e..660a72adcd 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -397,7 +397,7 @@ void dump_stralloc_strings(void)
   struct pike_string *p;
   for(e=0;e<htable_size;e++)
     for(p=base_table[e];p;p=p->next)
-      printf("%ld refs \"%s\"\n",(long)p->refs,p->str);
+      printf("0x%p: %ld refs \"%s\"\n",p,(long)p->refs,p->str);
 }
 
 #endif
@@ -669,8 +669,13 @@ void cleanup_shared_string_table(void)
 
   if(verbose_debug_exit)
   {
-    fprintf(stderr,"Leaked strings \n");
-    dump_stralloc_strings();
+    INT32 num,size;
+    count_memory_in_strings(&num,&size);
+    if(num)
+    {
+      fprintf(stderr,"Strings left: %d (%d bytes) (zapped)\n",num,size);
+      dump_stralloc_strings();
+    }
   }
 #endif
   for(e=0;e<htable_size;e++)
diff --git a/src/stralloc.h b/src/stralloc.h
index 35388541b2..18f709dd53 100644
--- a/src/stralloc.h
+++ b/src/stralloc.h
@@ -31,11 +31,11 @@ struct pike_string *debug_findstring(const struct pike_string *foo);
 #define my_order_strcmp(X,Y) ((char *)(X)-(char *)(Y))
 #define is_same_string(X,Y) ((X)==(Y))
 
-#define reference_shared_string(s) (s)->refs++
-#define copy_shared_string(to,s) ((to)=(s))->refs++
-
 
 #ifdef DEBUG_MALLOC
+#define reference_shared_string(s) do { struct pike_string *S_=(s); debug_malloc_touch(S_); S_->refs++; }while(0)
+#define copy_shared_string(to,s) do { struct pike_string *S_=(to)=(s); debug_malloc_touch(S_); S_->refs++; }while(0)
+
 struct shared_string_location
 {
   struct pike_string *s;
@@ -56,6 +56,10 @@ extern struct shared_string_location *all_shared_string_locations;
 
 
 #else
+
+#define reference_shared_string(s) (s)->refs++
+#define copy_shared_string(to,s) ((to)=(s))->refs++
+
 #define MAKE_CONSTANT_SHARED_STRING(var, text)	\
  do { static struct pike_string *str_;		\
     if(!str_) str_=make_shared_string((text));	\
diff --git a/src/svalue.h b/src/svalue.h
index 5ed08d1b38..e198ff8377 100644
--- a/src/svalue.h
+++ b/src/svalue.h
@@ -182,8 +182,8 @@ do{ \
 
 #endif
 
-#define free_svalue(X) do { struct svalue *_s=(X); check_type(_s->type); check_refs(_s); if(_s->type<=MAX_REF_TYPE && --*(_s->u.refs) <=0) really_free_svalue(_s); }while(0)
-#define assign_svalue_no_free(X,Y) do { struct svalue _tmp, *_to=(X), *_from=(Y); check_type(_from->type); check_refs(_from);  *_to=_tmp=*_from; if(_tmp.type <= MAX_REF_TYPE) _tmp.u.refs[0]++; }while(0)
+#define free_svalue(X) do { struct svalue *_s=(X); check_type(_s->type); check_refs(_s); if(_s->type<=MAX_REF_TYPE) { debug_malloc_touch(_s->u.refs); if(--*(_s->u.refs) <=0) really_free_svalue(_s); } }while(0)
+#define assign_svalue_no_free(X,Y) do { struct svalue _tmp, *_to=(X), *_from=(Y); check_type(_from->type); check_refs(_from);  *_to=_tmp=*_from; if(_tmp.type <= MAX_REF_TYPE) { debug_malloc_touch(_tmp.u.refs); _tmp.u.refs[0]++; } }while(0)
 #define assign_svalue(X,Y) do { struct svalue *_to2=(X), *_from2=(Y); free_svalue(_to2); assign_svalue_no_free(_to2, _from2);  }while(0)
 
 extern struct svalue dest_ob_zero;
diff --git a/src/threads.c b/src/threads.c
index 98f621e4d1..27bb724746 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.53 1998/01/25 08:25:16 hubbe Exp $");
+RCSID("$Id: threads.c,v 1.54 1998/01/26 20:00:01 hubbe Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -14,6 +14,7 @@ int threads_disabled = 0;
 #include "constants.h"
 #include "program.h"
 #include "gc.h"
+#include "main.h"
 
 #ifdef __NT__
 
@@ -214,7 +215,6 @@ void *new_thread_func(void * data)
   free((char *)data); /* Moved by per, to avoid some bugs.... */
   UNSETJMP(back);
 
-  destruct(thread_id);
   THREADS_FPRINTF((stderr,"THREADS_ALLOW() Thread %08x done\n",
 		   (unsigned int)thread_id));
 
-- 
GitLab