///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  Copyright (C) 1995-1998 by the Board of Trustees of Leland Stanford      //
//  Junior University.  See LICENSE for details.                             //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#ifndef debug_h
#define debug_h

#include "misc.h"

// For backward compatability
#define assert_msg ASSERT_MSG

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Class: Debug								     //
// Description: Generic Debugging Class and Macros                           //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
class Debug {

private:
  const int MAXDEBUGFLAGS = 100;
  static int _initCount;
  static int _flagNext;
  static PBool _flags;
  static PPchar _flagNames;
  static int _maxstrlen;
  static int Lookup(PCchar);

public:
  static Pchar assert_file;
  static int assert_line;

  Debug();
  ~Debug();
  static int InstallDebugFlag(PCchar);
  static void SetDebugFlag(int flag);
  static Bool CheckDebugFlag(int flag);
  static void ClearDebugFlag(int flag);
  static void SetDebugFlag(PCchar flagName)
    { SetDebugFlag(Lookup(flagName)); }
  static Bool CheckDebugFlag(PCchar flagName)
    { return CheckDebugFlag(Lookup(flagName)); }
  static void ClearDebugFlag(PCchar flagName)
    { ClearDebugFlag(Lookup(flagName)); }
  static void AssertFailMsg(Pchar fmt ...);
  static void PrintDebugFlags();
};

// Used to force initialization of Debug static variables
static Debug debugInstance;

#define FATAL_ASSERT(expr) FATAL_ASSERT_MSG(expr,("FATAL_ASSERT violation"))
#define FATAL_ASSERT_MSG(expr, params) \
  if (expr) ; \
  else { \
    Debug::assert_file = __FILE__; \
    Debug::assert_line = __LINE__; \
    Debug::AssertFailMsg params; \
  }

#ifdef DEBUG

#define ASSERT_DO ASSERT
#define ASSERT_DO_MSG ASSERT_MSG
#define ASSERT(expr) ASSERT_MSG(expr,("ASSERT violation"))

#define ASSERT_MSG(expr, params) \
  if (expr) ; \
  else { \
    Debug::assert_file = __FILE__; \
    Debug::assert_line = __LINE__; \
    Debug::AssertFailMsg params; \
  }

#define IF_DEBUG(code) code

#else

////////////////////////////////////////////////////////////////////////////////
// Empty Definitions for non-DEBUG mode                                       //
////////////////////////////////////////////////////////////////////////////////

#define ASSERT_DO(expr) expr
#define ASSERT_DO_MSG(expr, params) expr
#define ASSERT(expr)
#define ASSERT_MSG(expr, params)
#define IF_DEBUG(code)

#endif // DEBUG

#endif // debug_h
