/* -*- mode: c++; c-basic-offset: 4; -*-
 *
 * MICO --- a CORBA implementation
 * Copyright (C) 1997-98 Kay Roemer & Arno Puder
 * 
 * spezial debug support
 * Copyright (C) 1999 Andreas Schultz                                 
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Send comments and/or bug reports to:
 *                mico@informatik.uni-frankfurt.de
 * 
 * $Id: mtdebug.h,v 1.9 2000/01/08 00:28:04 aschultz Exp $
 *
 */


#ifndef __mico_mtdebug_h__
#define __mico_mtdebug_h__

#include <ctype.h>
#include <iostream.h>
#include <fstream.h>
#include <CORBA.h>
#include <mico/os-misc.h>
#include "string"

extern void __mtdebug_lock();
extern void __mtdebug_unlock();


class MICODebug {
    MICO_ULong _level;
    MICO_ULong _module;
    ostream *_null;
    static MICODebug *_instance;

    ostream &prefix (); 
public:
    typedef enum { Global, Support, Thread, ORB, POA, GIOP, IMR, IR } DebugModules; 

    MICODebug (MICO_ULong level = 0, MICO_ULong module = 1);
    ~MICODebug ();

    void level (MICO_ULong);
    MICO_ULong level () const;

    void module (MICO_ULong);
    MICO_ULong module () const;

    ostream &printer ();
    ostream &debugger ();
    ostream &tracer ();
    ostream &dumper ();
    ostream &profiler ();

    MICO_Boolean module ( DebugModules dm )   { return ((_module & (1 << dm)) != 0); };

    MICO_Boolean debug ()   { return ((_level & 1) != 0); };
    MICO_Boolean trace ()   { return ((_level & 2) != 0); };
    MICO_Boolean dump ()    { return ((_level & 4) != 0); };
    MICO_Boolean profile () { return ((_level & 8) != 0); };

    static MICODebug *instance ();
};

/*
 * MACRO debug MAGIC - this it not realy needed to succesfull run MICO
 *                     if it breaks you compiler, simply undef MTDEBUG
 */

#define __MTSAVE( x ) __mtdebug_lock(); x; __mtdebug_unlock(); 
#ifdef MTDEBUG
#  define DEBUG_NAMES
#  define __NAME( x )  x
#  define __MTOUT( x ) x
#else 
#  define __NAME( x )
#  define __MTOUT( x )
#endif // MTDEBUG

#ifndef MICO_DEBUG_MODULE
#  define MICO_DEBUG_MODULE MICODebug::Global
#endif

/*
 * BE CAREFULL: the module checking for Mutexes, Semaphore, etc, only
 *              works, because they are mostly inlined !!!!
 */
#define __MT_debug(x)                                                   \
  if ( MICODebug::instance()->module( MICO_DEBUG_MODULE ) ) {           \
       /* user debug code starts here */                                \
       x;                                                               \
       /* user debug code ends here */                                  \
  }

#define MT_DEBUG( x )   __MT_debug({ if ( MICODebug::instance()->debug() )   { __MTSAVE( x ); } })
#define MT_TRACE( x )   __MT_debug({ if ( MICODebug::instance()->trace() )   { __MTSAVE( x ); } })
#define MT_DUMP( x )    __MT_debug({ if ( MICODebug::instance()->dump() )    { __MTSAVE( x ); } })
#define MT_PROFILE( x ) __MT_debug({ if ( MICODebug::instance()->profile() ) { __MTSAVE( x ); } })

// __NAME is a wrapper for all _namedObject related definitions
// it is only used for debug purposes

#ifdef DEBUG_NAMES
    class _namedObject {
    protected:
	char *_name;
    public:
	_namedObject ();
        // get this object's Name (if assigned)
        const char *name (const char *new_name = NULL);
        ~_namedObject ();
    };
#endif  //DEBUG_NAMES
	
#endif  //__mico_mtdebug_h__
