Index: src/Common/Heap.cc
===================================================================
--- src/Common/Heap.cc	(revision 4ea632eaf73e03a88c47bc73708a1b47cf292ed0)
+++ src/Common/Heap.cc	(revision c02f76158a7a8cf2dc6bfdaeced0d4d5c32aaaf0)
@@ -7,9 +7,9 @@
 // Heap.cc --
 //
-// Author           : Peter A. Buhr
-// Created On       :
+// Author           : Thierry Delisle
+// Created On       : Thu May  3 16:16:10 2018
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu May  3 16:16:10 2018
-// Update Count     : 2
+// Last Modified On : Fri May  4 17:17:59 2018
+// Update Count     : 27
 //
 
@@ -21,82 +21,167 @@
 #include <iostream>
 
+//#define WITH_HEAP_STATISTICS
+
 namespace HeapStats {
-	#if !defined( WITH_HEAP_STATISTICS )
-		void newPass( const char * const ) {}
+#if !defined( WITH_HEAP_STATISTICS )
+	void newPass( const char * const ) {}
 
-		void printStats() {}
-	#else
-		struct StatBlock {
-			const char * name = nullptr;
-			size_t mallocs    = 0;
-			size_t frees      = 0;
-		};
+	void printStats() {}
+#else
+	struct StatBlock {
+		const char * name = nullptr;
+		size_t mallocs    = 0;
+		size_t frees      = 0;
+	};
 
-		StatBlock    passes[100];
-		const size_t passes_size = sizeof(passes) / sizeof(passes[0]);
-		size_t       passes_cnt = 0;
+	StatBlock    passes[100] = {{ "Pre-Parse", 0, 0 }};
+	const size_t passes_size = sizeof(passes) / sizeof(passes[0]);
+	size_t       passes_cnt = 1;
 
-		void newPass( const char * const name ) {
-			passes[passes_cnt].name    = name;
-			passes[passes_cnt].mallocs = 0;
-			passes[passes_cnt].frees   = 0;
-			passes_cnt++;
+	void newPass( const char * const name ) {
+		passes[passes_cnt].name    = name;
+		passes[passes_cnt].mallocs = 0;
+		passes[passes_cnt].frees   = 0;
+		passes_cnt++;
 
-			assertf(passes_cnt < passes_size, "Too many passes for HeapStats, increase the size of the array in Heap.h");
+		assertf(passes_cnt < passes_size, "Too many passes for HeapStats, increase the size of the array in Heap.h");
+	}
+
+	void print(size_t value, size_t total) {
+		std::cerr << std::setw(12) << value;
+		std::cerr << "(" << std::setw(3);
+		std::cerr << (value == 0 ? 0 : value * 100 / total);
+		std::cerr << "%) | ";
+	}
+
+	void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees) {
+		std::cerr << std::setw(nc) << stat.name;
+		std::cerr << " | ";
+
+		print(stat.mallocs, total_mallocs);
+		print(stat.frees  , total_frees  );
+		std::cerr << "\n";
+	}
+
+	void print(char c, size_t nc) {
+		for(size_t i = 0; i < nc; i++) {
+			std::cerr << c;
+		}
+		std::cerr << '\n';
+	}
+
+	void printStats() {
+		size_t nc = 0;
+		size_t total_mallocs = 0;
+		size_t total_frees   = 0;
+		for(size_t i = 0; i < passes_cnt; i++) {
+			nc = std::max(nc, std::strlen(passes[i].name));
+			total_mallocs += passes[i].mallocs;
+			total_frees   += passes[i].frees;
+		}
+		size_t nct = nc + 44;
+
+		const char * const title = "Heap Usage Statistic";
+		print('=', nct);
+		for(size_t i = 0; i < (nct - std::strlen(title)) / 2; i++) std::cerr << ' ';
+		std::cerr << title << std::endl;
+		print('-', nct);
+		std::cerr << std::setw(nc) << "Pass";
+		std::cerr << " |       Malloc Count |         Free Count |" << std::endl;
+
+		print('-', nct);
+		for(size_t i = 0; i < passes_cnt; i++) {
+			print(passes[i], nc, total_mallocs, total_frees);
+		}
+		print('-', nct);
+		print({"Sum", total_mallocs, total_frees}, nc, total_mallocs, total_frees);
+
+	}
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+	extern "C" {
+#include <dlfcn.h>
+#include <execinfo.h>
+	}
+
+//=============================================================================================
+// Interposing helpers
+//=============================================================================================
+
+	typedef void (* generic_fptr_t)(void);
+	generic_fptr_t interpose_symbol( const char * symbol, const char * version ) {
+		const char * error;
+
+		static void * library;
+		if ( ! library ) {
+#if defined( RTLD_NEXT )
+			library = RTLD_NEXT;
+#else
+			// missing RTLD_NEXT => must hard-code library name, assuming libstdc++
+			library = dlopen( "libc.so.6", RTLD_LAZY );
+			error = dlerror();
+			if ( error ) {
+				std::cerr << "interpose_symbol : failed to open libc, " << error << std::endl;
+				abort();
+			}
+#endif
+		} // if
+
+		generic_fptr_t fptr;
+
+#if defined( _GNU_SOURCE )
+		if ( version ) {
+			fptr = (generic_fptr_t)dlvsym( library, symbol, version );
+		} else {
+			fptr = (generic_fptr_t)dlsym( library, symbol );
+		}
+#else
+		fptr = (generic_fptr_t)dlsym( library, symbol );
+#endif // _GNU_SOURCE
+
+		error = dlerror();
+		if ( error ) {
+			std::cerr << "interpose_symbol : internal error, " << error << std::endl;
+			abort();
 		}
 
-		void print(size_t value, size_t total) {
-			std::cerr << std::setw(12) << value;
-			std::cerr << "(" << std::setw(3);
-			std::cerr << (value == 0 ? 0 : value * 100 / total);
-			std::cerr << "%) | ";
+		return fptr;
+	}
+
+	extern "C" {
+		void * malloc( size_t size ) __attribute__((malloc));
+		void * malloc( size_t size ) {
+			static auto __malloc = reinterpret_cast<void * (*)(size_t)>(interpose_symbol( "malloc", nullptr ));
+			if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++;
+			return __malloc( size );
 		}
 
-		void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees) {
-			std::cerr << std::setw(nc) << stat.name;
-			std::cerr << " | ";
-
-			print(stat.mallocs, total_mallocs);
-			print(stat.frees  , total_frees  );
-			std::cerr << "\n";
+		void free( void * ptr ) {
+			static auto __free = reinterpret_cast<void   (*)(void *)>(interpose_symbol( "free", nullptr ));
+			if( passes_cnt > 0 ) passes[passes_cnt - 1].frees++;
+			return __free( ptr );
 		}
 
-		void print(char c, size_t nc) {
-			for(size_t i = 0; i < nc; i++) {
-				std::cerr << c;
-			}
-			std::cerr << '\n';
+		void * calloc( size_t nelem, size_t size ) {
+			static auto __calloc = reinterpret_cast<void * (*)(size_t, size_t)>(interpose_symbol( "calloc", nullptr ));
+			if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++;
+			return __calloc( nelem, size );
 		}
 
-		void printStats() {
-			size_t nc = 0;
-			size_t total_mallocs = 0;
-			size_t total_frees   = 0;
-			for(size_t i = 0; i < passes_cnt; i++) {
-				nc = std::max(nc, std::strlen(passes[i].name));
-				total_mallocs += passes[i].mallocs;
-				total_frees   += passes[i].frees;
-			}
-			size_t nct = nc + 44;
-
-			const char * const title = "Heap Usage Statistic";
-			print('=', nct);
-			for(size_t i = 0; i < (nct - std::strlen(title)) / 2; i++) std::cerr << ' ';
-			std::cerr << title << std::endl;
-
-			print('-', nct);
-			std::cerr << std::setw(nc) << "Pass";
-			std::cerr << " |       Malloc Count |         Free Count |" << std::endl;
-
-			print('-', nct);
-			for(size_t i = 0; i < passes_cnt; i++) {
-				print(passes[i], nc, total_mallocs, total_frees);
-			}
-
-			print('-', nct);
-			print({"Sum", total_mallocs, total_frees}, nc, total_mallocs, total_frees);
-
+		void * realloc( void * ptr, size_t size ) {
+			static auto __realloc = reinterpret_cast<void * (*)(void *, size_t)>(interpose_symbol( "realloc", nullptr ));
+			void * s = __realloc( ptr, size );
+			if ( s != ptr && passes_cnt > 0 ) {			// did realloc get new storage ?
+				passes[passes_cnt - 1].mallocs++;
+				passes[passes_cnt - 1].frees++;
+			} // if
+			return s;
 		}
-	#endif
+	}
+#endif
 }
-
