/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for 
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #                                      
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    Debug.h
    Author:  Copyright  1995 Julian Smith, Cy Booker, Paul Field.
    Version: 1.01 (04 Jun 1995)
    Purpose: Defines interface to a set of functions useful for
             debugging.
    Mods:    25 Aug 1995 - JS - Added Desk_Debug_Assert.
             12 Feb 1996 - JS - Removed Desk_Debug__Dummy, and changed 
                                Desk_Debug_Dummyf macro to use printf.
                                Made #defines of Debug<n>_Printf map 
                                straight to Desk_Debug_Dummyf for non-debug 
                                builds to stop cc from making a .o file 
                                which refers to Desk_debug_level, but doesn't 
                                actually use it in the code.
             20 Feb 1996 - JS - Added #include <stdio.h>

*/


/*

Here are prototypes for a standard set of simple debugging functions.

Note that the main DeskLib library 'DeskLib:o.DeskLib' does *not*
contain any of these functions - you have to link with a library inside
'DeskLib:o.Debug.' (or provide your own versions of the functions). This
is so that different debugging libraries can be used, to output data to
stderr, or a file in pipe or wherever you feel most comfortable with...

This header file ensures that all calls to Desk_Debug_xxx functions are
macro-ed out by the preprocessor unless Desk_DeskLib_DEBUG is predefined.

This is so you can put lots of 'Desk_Debug_Printf(...)' calls etc in your
code, safe in the knowledge that they will all disappear when building a
normal version of your project.

*/

#ifndef __Desk_Debug_h
#define __Desk_Debug_h

#ifdef __cplusplus
	extern "C" {
#endif

#include <stdio.h>
#include <stdarg.h>


#ifndef __Desk_Core_h
	#include "Desk.Core.h"
#endif



typedef void (*Desk_debug_signalhandlerfn)( int sig, void *reference);
/*
This is a function-type which is called when a signal happens
*/






#if !defined( Desk_DEBUG) && !defined( Desk__making_Debug)

	#define Desk_Debug_Initialise()
	
	#define Desk_Debug_InitialiseSignal()
	#define Desk_Debug_ClaimSignal( fn, reference)
	#define Desk_Debug_ReleaseSignal()
	
	#define	Desk_Debug_Finalise()
	
	#define Desk_Debug_Assert( expression)
	
	#define Desk_Debug_Error_CheckFatal( errfn)	Desk_Error_CheckFatal( errfn)
	
	#define Desk_Debug_Print( text)
	
	#define	Desk_Debug_DumpRegistersToFile()
	
	#define	Desk_Debug_SetNestingIndentation( indentstring)
	
	#define	Desk_Debug_DescribeError2( error)
	
	#define	Desk_Debug_SetLevel( level)
	
	#define	Desk_Debug_BackTrace()
	#define	Desk_Debug_PrintMemory( start, size)
	
	#define Desk_Debug_Printf 	Desk_Debug_Dummyf
	#define Desk_Debug1_Printf	Desk_Debug_Dummyf
	#define Desk_Debug2_Printf	Desk_Debug_Dummyf
	#define Desk_Debug3_Printf 	Desk_Debug_Dummyf
	#define Desk_Debug4_Printf 	Desk_Debug_Dummyf
	#define Desk_Debug5_Printf 	Desk_Debug_Dummyf
	
	#define Desk_Debug_VPrintf 	Desk_Debug_Dummyf
	#define Desk_Debug1_VPrintf	Desk_Debug_Dummyf
	#define Desk_Debug2_VPrintf	Desk_Debug_Dummyf
	#define Desk_Debug3_VPrintf 	Desk_Debug_Dummyf
	#define Desk_Debug4_VPrintf 	Desk_Debug_Dummyf
	#define Desk_Debug5_VPrintf 	Desk_Debug_Dummyf
	
	#define	Desk_Debug_RedirectToFilename( filename)
	
	/*
	These effectively remove any references to Desk_Debug_ functions from 
	source code.
	*/

#else
	
	void	Desk_Debug_Initialise( void);
	/*
	Sets up the debug library - call this at the start of main().
	*/
	
	void	Desk_Debug_Finalise( void);
	/*
	Closes any output file. Not normally needed as the C runtime system
	closes all open files automatically.
	*/
	
	void	Desk_Debug_InitialiseSignal( void);
	/*
	Sets up a handler for signals
	*/
	
	void	Desk_Debug_ClaimSignal( Desk_debug_signalhandlerfn fn, void *reference);
	/*
	Makes 'fn' be called when a signal occurs.
	*/
	
	void	Desk_Debug_ReleaseSignal( void);
	/*
	Stops the fn, from a previous call to Desk_Debug_ClaimSignal, being called
	*/
	
	int	Desk_Debug_Printf( const char *format, ...);
	/*
	Sends the text to the debug output, in same way as printf.
	*/
	
	int	Desk_Debug_VPrintf( const char *format, va_list va);
	/*
	Sends the text to the debug output, in same way as vprintf.
	*/
	
	void	Desk_Debug_Print( const char *text);
	/*
	Sends a string to the debug output.
	*/
	
	void	Desk_Debug_DumpRegistersToFile( void);
	/*
	Saves all registers to '<Wimp$ScrapDir>.regsxx' using OS_File
	10, where 'xx' is a hex number starting at 0. Preserves all
	registers apart from lr	and pc.
	 */
	
	void	Desk_Debug_SetNestingIndentation( const char* prefix);
	/*
	Future outputs from Desk_Debug_Printf are prefixed by multiples of
	the specified string, according to the current function-call
	nesting.
	
	Note that the prefix string is /not/ copied, so must be
	permanent.
	
	Also note that you shouldn't call this if you are ever going to
	call Desk_Debug_Printf from a place which doesn't have a stack
	that the Desk_BackTrace functions understand - otherwise they
	will cause an address exception or similar.
	
	This has only happened to me (JS) was inside a function which
	was called by a CMHG IRQ veneer.
	*/
	
	struct Desk_error2_block;
	void	Desk_Debug_DescribeError2( const struct Desk_error2_block* error);
	/*
	Uses Desk_Error2_FDescribe to send info about 'error' to Debug_Printf.
	 */
	
	
	#define	Desk_Debug_SetLevel( level)	Desk_debug_level = (level)
	/*
	Use this so set the debug-level - it reduces to nothing with
	normal compilation
	 */
	
	int	Desk_Debug_PrintfRef( void* reference, const char *format, ...);
	/*
	This function behaves exactly like Desk_Debug_Printf - 'reference' is ignored.
	It is for use as a call-back receiver to functions which send a reference (eg
	Desk_Error2_FDescribe).
	 */
	
	
	void	Desk_Debug_BackTrace( void);
	/*
	Outputs a backtrace using Desk_Debug_Printf.
	 */
	
	
	
	#define Desk_Debug_Error_CheckFatal( errfn)		\
		do	{					\
			Desk_os_error	*Desk_debug__e = errfn;	\
				if ( Desk_debug__e)	{	\
				Desk_Error_ReportFatal( 	\
					Desk_debug__e->errnum, 	\
					Desk_error_PLACE "%s", 	\
					Desk_debug__e->errmess	\
					);			\
				}				\
			}					\
			while (0)
	/*
	As Desk_Error_ReportFatal, but also displays the file and line number if
	Desk_DeskLib_DEBUG is predefined.
	*/
	
	void	Desk_Debug__Assert( const char *expression, const char *sourcefile, int line);
	/*
	Not for user consumption - used by Desk_Debug_Assert.
	*/
	
	
	void	Desk_Debug_PrintMemory( void* start, int size);
	
	void	Desk_Debug_RedirectToFilename( const char* filename);
	/*
	Only implemented in uniqfile at the moment.
	 */
	
	#define Desk_Debug_Assert( expression)					\
		(								\
			(expression) 						\
				? 						\
				(void) 0	 				\
				: 						\
				Desk_Debug__Assert( #expression, __FILE__, __LINE__)	\
		)
	/*
	This is similar to the standard ANSI C 'assert' macro. If
	'expression' evaluates to Desk_bool_FALSE, Desk_Debug_Printf is used
	to output a diagnostic message, and then abort() is called.
	
	Like all the Desk_Debug_ commands, Desk_Debug_Assert is removed before compilation
	unless Desk_DeskLib_DEBUG is defined.
	
	*/
	
	#define Desk_Debug1_Printf (Desk_debug_level<1) ? 0 : Desk_Debug_Printf
	/* Only outpus diagnostics if Desk_debug_level is >= 1	*/
	
	#define Desk_Debug2_Printf (Desk_debug_level<2) ? 0 : Desk_Debug_Printf
	/* Only outpus diagnostics if Desk_debug_level is >= 2	*/
	
	#define Desk_Debug3_Printf (Desk_debug_level<3) ? 0 : Desk_Debug_Printf
	/* Only outpus diagnostics if Desk_debug_level is >= 3	*/
	
	#define Desk_Debug4_Printf (Desk_debug_level<4) ? 0 : Desk_Debug_Printf
	/* Only outpus diagnostics if Desk_debug_level is >= 4	*/
	
	#define Desk_Debug5_Printf (Desk_debug_level<5) ? 0 : Desk_Debug_Printf
	/* Only outpus diagnostics if Desk_debug_level is >= 5	*/
	
	/* 
	The Desk_DebugN_Printf macros can be used to control how much 
	diagnostic information is produced.
	*/
	
#endif










#define Desk_Debug_Dummyf (Desk_bool_TRUE) ? 0 : printf
/*
A macro which is used to remove calls to a multi-argument function which
returns an integer. This isn't a bomb-proof macro, but is the best I can
come up with.

NB The simpler alternative macro '#define Desk_Debug_Dummyf if (0)
Desk_Debug__Dummyf' isn't used because it affects the meaning of 'else' in
(for example):

if (flag) Desk_Debug_Dummyf( "flag=%i\n", flag);
else      flag=3;

*/


extern int	Desk_debug_level;
/*
This is initially 0. Setting it to values greater than zero will turn on
any subsequent Desk_DebugX_Printf statements.

Note that this will only happen with code compiled with Desk_DeskLib_DEBUG
predefined.

Note that this selection of Desk_DebugX_Printf is 'live' - ie you can change
Desk_debug_level before calling different functions to only have diagnostics
from certain parts of your code.

*/





#ifdef __cplusplus
}
#endif


#endif
