/*
* freescope - Free source browser
* Copyright (C) 2001 Olivier Deme
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* FILE: Trace.h
*
* DESCRIPTION: This file defines the class Trace and its relatives used
* for tracing and logging purpose.
* For more information, see readme.txt
*/
#ifndef _TRACE_H_
#define _TRACE_H_
/************/
/* INCLUDES */
/************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <assert.h>
#ifndef NOT_ANSI
#include <string>
#include <fstream>
#include <new>
using namespace std;
#else // NOT_ANSI
#include <string.h>
#include <fstream.h>
#include <new.h>
#endif // NOT_ANSI
/********************/
/* GLOBAL VARIABLES */
/********************/
#ifdef USE_TRACE_OFF
static int g_trace_off;
#endif // USE_TRACE_OFF
/**********/
/* MACROS */
/**********/
#define TRACE_CFG (Trace::instance())
/*
* WARNING: Do not use LOG and TRACE the following way:
*
* if (bla)
* TRACE(module, level) << "blabla" << endl;
* else
* do_something();
*
*
* This won't compile, instead use curly braces:
*
* if (bla)
* {
* TRACE(module, level) << "blabla" << endl;
* }
* else
* {
* do_something();
* }
*/
#define LOG(module, level) if (Trace::m_flags & Trace::FLAGS_CALLER) \
{ \
Trace::m_locLine = __LINE__; \
Trace::m_locFile = __FILE__; \
} \
Trace::m_module = module; \
Trace::m_level = level; \
(Trace::instance())
// Define USE_TRACE if you want to use trace
#ifndef NO_TRACE
#define TRACE(module, level) if (Trace::m_flags & Trace::FLAGS_CALLER) \
{ \
Trace::m_locLine = __LINE__; \
Trace::m_locFile = __FILE__; \
} \
Trace::m_module = module; \
Trace::m_level = level; \
(Trace::instance())
#else // NO_TRACE
# ifndef USE_TRACE_OFF
/*
* NOTE: If possible, do not define USE_TRACE_OFF. The reason is that
* the following code (the one using if(0)) should be removed
* from the executable when compiled with optimization flag.
* This avoids the overhead of an extra check with 0. when
* NO_TRACE is defined.
* Define USE_TRACE_OFF when the compiler generates a warning
* (code unreachable).
*/
#define TRACE(module, level) if (0) \
(Trace::instance())
# else // USE_TRACE_OFF
#define TRACE(module, level) if (g_trace_off) \
(Trace::instance())
# endif // USE_TRACE_OFF
#endif // NO_TRACE
/********************/
/* PRE-DECLARATIONS */
/********************/
class Hex;
class Width;
/*********************/
/* CLASS DEFINITIONS */
/*********************/
class Trace
{
// TYPE DEFINITIONS
public:
typedef enum
{
FLAGS_CALLER = 0x1 << 0,
FLAGS_ALIGNMENT = 0x1 << 1,
FLAGS_LEVEL_DESCRIPTION = 0x1 << 2,
FLAGS_MODULE_DESCRIPTION = 0x1 << 3,
FLAGS_PROGRAM_NAME = 0x1 << 4,
FLAGS_TIMESTAMP = 0x1 << 5,
FLAGS_TIME_LOCAL = 0x1 << 6,
FLAGS_TIME_GMT = 0x1 << 7
} Flag;
typedef enum
{
OSTREAM_STDOUT = 0x1 << 0,
OSTREAM_STDERR = 0x1 << 1,
OSTREAM_FILE = 0x1 << 2,
OSTREAM_OTHER = 0x1 << 3
} Ostream;
typedef int Level;
typedef int Module;
typedef int Stream;
typedef int Flags;
protected:
typedef struct
{
Level levels;
Level levDescrBits;
string levDescr [sizeof(Level)*8];
string description;
bool descriptionSet;
} Module_t;
typedef Trace& (Trace_manip) (Trace&);
// CONSTANTS
public:
static const Module GLOBAL; // Application-level module
const char HEADER_DELIMITER;
const Level LEVEL_ERROR;
// FRIENDS
friend Trace& flush (Trace&);
friend Trace& endl (Trace&);
friend Trace& operator<< (Trace&, const Hex&);
friend Trace& operator<< (Trace&, const Width&);
// CONSTRUCTORS
private:
Trace () throw();
protected:
virtual ~Trace () {};
// METHODS
public:
void set_program_name (const string& name) throw();
Level add_to_mask (const Module module,
const Level levels) throw();
Level remove_from_mask (const Module module,
const Level levels) throw();
Level set_mask (const Module module,
const Level levels) throw();
void set_level_description (const Module module,
const Level levels,
const string& description) throw();
void set_module_description (const Module modules,
const string& description) throw();
virtual Flags enable (const Flags flags) throw();
virtual Flags disable (const Flags flags) throw();
virtual Flags set_flags (const Flags flags) throw();
// virtual void setbuf (const unsigned int) throw();
virtual Stream close (const Stream streams) throw();
virtual Stream open (const Stream streams) throw();
virtual Stream open (Stream streams,
const string& file);
static bool create () throw(bad_alloc);
static inline Trace& instance () throw();
protected:
virtual int time_stamp (char* buffer) throw();
virtual void do_header ();
private:
void set_level_max_length () throw();
void set_module_max_length () throw();
#ifdef USE_TRACE_OFF
void dummy () throw() {g_trace_off = 0;}; // Remove warning
#endif // USE_TRACE_OFF
// OPERATORS
public:
virtual Trace& operator<< (char character);
virtual Trace& operator<< (unsigned char character);
virtual Trace& operator<< (char* string);
virtual Trace& operator<< (unsigned char* string);
virtual Trace& operator<< (const string& text);
virtual Trace& operator<< (int nbr);
virtual Trace& operator<< (unsigned int nbr);
virtual Trace& operator<< (long nbr);
virtual Trace& operator<< (unsigned long nbr);
virtual Trace& operator<< (short nbr);
virtual Trace& operator<< (unsigned short nbr);
virtual Trace& operator<< (float nbr);
virtual Trace& operator<< (double nbr);
virtual Trace& operator<< (Trace_manip);
// ATTRIBUTES
/*
* The following attributes are static and public.
* Don't scream! This is for efficiency reason, cf. macro.
*/
public:
static Flags m_flags;
static unsigned int m_locLine;
static char* m_locFile;
static Module m_module;
static Level m_level;
protected:
bool m_start;
Module_t m_modules[sizeof(Module)*8]; // The module structures
Stream m_streams; // Opened streams
ofstream m_file; // File streaming
string m_filename; // File name
string m_programName; // Program name
int m_lookupLevel[sizeof(Level)*8]; // Powers of two
static Trace* m_instance; // The singleton
private:
unsigned int m_moduleMaxLength;
unsigned int m_levelMaxLength;
};
class Hex
{
// CONSTRUCTORS
public:
Hex (int nbr) { m_nbr = (unsigned int)nbr; };
Hex (unsigned int nbr) { m_nbr = nbr; };
// FRIEND OPERATORS
friend Trace& operator<< (Trace& trace, const Hex& h);
// ATTRIBUTES
unsigned int m_nbr;
};
class Width
{
// FRIENDS
friend Trace& operator<< (Trace& trace, const Width& w);
// TYPE DEFINITIONS
public:
typedef enum
{
LEFT,
RIGHT
} Format;
// CONSTRUCTORS
public:
Width (Format justify, unsigned int width, char fill = ' ');
// ATTRIBUTES
Format m_fmt;
unsigned int m_width;
char m_fill;
};
/****************/
/* MANIPULATORS */
/****************/
extern Trace& endl (Trace& trace);
extern Trace& flush (Trace& trace);
/********************/
/* INLINE FUNCTIONS */
/********************/
inline Trace& Trace::instance()
throw ()
{
assert(m_instance != 0); // Instance must be created
return *m_instance;
}
#endif // _TRACE_H_
syntax highlighted by Code2HTML, v. 0.9.1