/* Debug definitions
 * 
 * By W.H.Scholten 1996-1999
 *
 * This file is placed in the public domain.
 */

/* Inspector Gadget is ALWAYS on duty */

/*---------------------------------------------------------------------------*
 *  Debug output is controlled by 1 or 2 environment variables:
 *    - The first is named DEBUG_LEVEL unless you #define DEBUG_NAME before
 *      #including the debug file and is intended for global output control.
 *    - The second is DEBUG_NAME prefixed with DEBUG_PREFIX, with which it is
 *      possible to control the output of separate sections (files). (to use
 *      this, #define DEBUG_PREFIX before including the debug file).
 *
 *  The real debug level = max(lvl(DEBUG_NAME), lvl(DEBUG_PREFIX DEBUG_NAME)).
 *  This means that if DEBUG_LEVEL=0, then the section environment variables
 *  solely control debug output.
 *
 *  If both variables ar unset or 0, there will not be any output.
 *  E.g. DEBUG_LEVEL=1, export DEBUG_LEVEL in the bash shell to give global
 *  level 1 output.
 *
 *  use of DPRINT:
 *    DPRINT((lvl, ... ))
 *---------------------------------------------------------------------------*/

#ifndef _WHS__whs_debug_h
#define _WHS__whs_debug_h

#undef DEB
#undef DEB1
#undef DEB2
#undef DEB3
#undef ASSERT

#ifdef DEBUG
#  undef DPRT
#  undef DPRINT
#  include <stdlib.h>
#  include <stdio.h>
#  ifndef DEBUG_LEVEL
#    define DEBUG_LEVEL 1
#  endif
#  ifndef DEBUG_PREFIX
#    define DEBUG_PREFIX ""
#  endif
#  ifndef DEBUG_POSTFIX
#    define DEBUG_POSTFIX ""
#  endif
#  ifndef DEBUG_NAME
#    define DEBUG_NAME "DEBUG_LEVEL"
#  endif
static int _whs_debug(int level) {
	static int debug_level = -1;

	if (debug_level<0) {
		char *env;

		env = getenv( DEBUG_NAME );
		if (env != NULL) debug_level=atol(env);
		else debug_level=0;

		env = getenv( DEBUG_PREFIX  DEBUG_NAME  DEBUG_POSTFIX );
		if (env != NULL) {
			int prefix_debug_level = atol(env);
			if (prefix_debug_level > debug_level) debug_level = prefix_debug_level;
		}
	}
	return (debug_level>=level);
}
#  include <stdarg.h>
static void DPRT(char *s, ...) {
	char mesgbuf[1024];
	va_list argp;

	va_start(argp, s);
	vsnprintf(mesgbuf, 1023, s, argp);
	mesgbuf[1023] = 0;

	//fprintf(stderr, s, argp);
	fprintf(stderr, DEBUG_PREFIX DEBUG_POSTFIX " ");
	fprintf(stderr, mesgbuf);
	va_end(argp);
}
#if 0
#define DPRINT(args) DPRINT2 args
static void DPRINT2(int debuglvl, char *s, ...) {
	char mesgbuf[1024];
	va_list argp;

	va_start(argp, s);
	vsnprintf(mesgbuf, 1023, s, argp);
	mesgbuf[1023] = 0;

	//fprintf(stderr, s, argp);
	if (_whs_debug(debuglvl)) fprintf(stderr, mesgbuf);
	va_end(argp);
}
#endif

#  define DEB(x) x
#  define DEB1(x) { if (_whs_debug(1) ) { x; } }
#  define DEB2(x) { if (_whs_debug(2) ) { x; } }
#  define DEB3(x) { if (_whs_debug(3) ) { x; } }

#  define ASSERT(expr) { if (!(expr)) { fprintf(stderr, "Assertion failed: %s, file %s, line %d\n", #expr, __FILE__, __LINE__); fprintf(stderr, "continue? (y/n)"); if (getchar() != 'y') exit (1); } }
#  define ENSURE(expr) ASSERT(expr)

#else
#  define DEB(x)
#  define DEB1(x)
#  define DEB2(x)
#  define DEB3(x)
#  define ASSERT(expr)
#  define ENSURE(expr)

#endif

/* Show me the way, o glorious inspector. */

#ifdef USE_NANA
#  define NANA(x) x
#  include <nana.h>
#else
#  define NANA(x)
#endif

#endif /* _WHS__whs_debug_h */
