/* * 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 #endif /* HAVE_CONFIG_H */ #include #ifndef NOT_ANSI #include #include #include using namespace std; #else // NOT_ANSI #include #include #include #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_