/*
    #   # #             ####                ##
    #   #               #   #              #  #
    #   # #  ###  # ##  #   # # ##   ###   #
    ##### # #   # ##  # ####  ##  # #   # ###  
    #   # # ##### #     #     #     #   #  #
    #   # # #     #     #     #     #   #  #   
    #   # #  ###  #     #     #      ###   #   
    ___________________________________________


Author:		Copyright  1995 Julian Smith
Purpose:	Hierachical profiling of C code.

*/

/*
All HierProf_ macros should /not/ be followed by the usual ';' character.

Example HierProf usage:

int	Foo()
{
HierProf_FnStart( "Foo")

HierProf_Start( "Loop")
for(...)	{ ...	}
HierProf_Stop()
if (...)	HierProf_ReturnValue( 3)
HierProf_NonVoidFnStop()
}

void	Bar()
{
HierProf_FnStart( "Bar")
if (...)	HierProf_ReturnVoid()
HierProf_VoidFnStop()
}

Or you can use HierProfCC to automatically add such macros to a C source
file before compilation.
 */

#ifndef __HierProf_h
#define	__HierProf_h


#ifdef __cplusplus
extern "C"	{
#endif


#include <stdio.h>


/*
The following are to control where profile output will be sent. The
default is to send it to stderr using the function fprintf. You can send
profiling output to your own function if you like.
 */


typedef int (*HierProf_printfnptr)( void *where, const char *format, ...);
/* 
A pointer to a fprintf-type function, except the first argument is a
(void *) rather than a (FILE *).
 */

void	HierProf_InitOuterNesting( void);
/*
Tells Profile to start its outer loop. This is done automatically at the
beginning of the first profile loop if you don't call this function
yourself.
 */

void	HierProf_OutputToFunction( HierProf_printfnptr function, void *where);
/*
Send subsequent profiles to this function. 'where' will be sent as the
first argument to 'function'. e.g. to send output to stderr, use
HierProf_OutputToFunction( (HierProf_printfnptr) fprintf, stderr);
 */

void	HierProf_OutputToTempFile( void);
/*
Send subsequent profiles to filename returned by ANSI C's tmpnam()
function. With Acorn C, this will be a file in the directory
<Wimp$ScrapDir>
 */

void	HierProf_OutputToFilenamef( char *fmt, ...);
/*
Send subsequent profiles to this filename.
 */

void	HierProf_OutputToFilestream( FILE *stream);
/* 
Send subsequent profiles to this filestream
 */

void	HierProf_DontOutput( void);
/*
Make subsequent profiles not output anything.
 */

void	HierProf_OutputNow( void);
/*
Sends a full profile resume to whatever is the current output
stream/function/filename
 */





/* These determines the timer used by the HierProf library.	*/
#include <time.h>
typedef unsigned int			HierProf_clock_t;
#define	HierProf_CLOCKS_PER_SEC		CLOCKS_PER_SEC
#define	HierProf_Clock()		( (HierProf_clock_t) clock())

#define	HierProf_WindClock()
/* Called by HierProf library at start of program	*/	

#define	HierProf_UnwindClock()
/* Called by HierProf library at end of program		*/




/* These are called by the HierProf block start/stop macros	*/
int	HierProf__InitBlock( char* name);
void	HierProf__StartClock( int ref, HierProf_clock_t t);
void	HierProf__StopClock( int ref, HierProf_clock_t t);





#ifdef HierProf_PROFILE

	
	#define	HierProf__StartBlock( name, ref)			\
		{							\
		static int	ref = 0;				\
		if ( ref==0)	ref = HierProf__InitBlock( name);	\
		HierProf__StartClock( ref, HierProf_Clock());		\
		{
	
	#define	HierProf__StopBlock( ref)			\
		}						\
		HierProf__StopClock( ref, HierProf_Clock());	\
		}
	
	#define	HierProf_Start( name)		HierProf__StartBlock( name, HierProf__ref)
	#define	HierProf_Stop()			HierProf__StopBlock( HierProf__ref)
	
	#define	HierProf_FnStart( name)		HierProf__StartBlock( name, HierProf__fnref)
	#define	HierProf_VoidFnStop()		HierProf__StopBlock( HierProf__fnref)
	#define	HierProf_NonVoidFnStop()	}}
	
	#define	HierProf_ReturnValue( x)					\
		{								\
		HierProf__StopClock( HierProf__fnref, HierProf_Clock());	\
		return x;							\
		}
	
	#define	HierProf_ReturnVoid()						\
		{								\
		HierProf__StopClock( HierProf__fnref, HierProf_Clock());	\
		return;								\
		}
	
	#define	HierProf_DontProfile()
	

#else

	#define	HierProf_Start( name)
	#define	HierProf_Stop()
	#define	HierProf_FnStart( name)
	#define	HierProf_VoidFnStop()
	#define	HierProf_NonVoidFnStop()
	#define	HierProf_ReturnValue( x)	return x;
	#define	HierProf_ReturnVoid()		return;
	
	#define	HierProf_InitOuterNesting()
	#define	HierProf_OutputToFunction( function, where)
	#define	HierProf_OutputToTempFile()
	#define	HierProf_OutputToFilenamef (1) ? 0 : printf
	#define	HierProf_OutputToFilestream( stream)
	#define	HierProf_DontOutput()
	#define	HierProf_OutputNow()
	#define	HierProf_DontProfile()


#endif


#ifdef __cplusplus
}
#endif


#endif
