dbg.h

00001 /*
00002  * File:    dbg.h
00003  * Author:  Pete Goodliffe
00004  * Version: 1.10
00005  * Created: 7 June 2001
00006  *
00007  * Purpose: C++ debugging support library
00008  *
00009  * Copyright (c) Pete Goodliffe 2001-2002 (pete@cthree.org)
00010  *
00011  * This file is modifiable/redistributable under the terms of the GNU
00012  * Lesser General Public License.
00013  *
00014  * You should have recieved a copy of the GNU General Public License along
00015  * with this program; see the file COPYING. If not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 0211-1307, USA.
00017  */
00018 
00019 #ifndef DBG_DBG_H
00020 #define DBG_DBG_H
00021 
00022 #include <iosfwd>
00023 #include <exception>
00024 
00025 #ifndef _MSC_VER
00026 #include <ctime>
00027 #else
00028 // The start of a MSVC compatibility disaster area.
00029 // See the documentation for the dbgclock_t type.
00030 #include <time.h>
00031 #endif
00032 
00033 #if defined(DBG_ENABLED) && defined(NDEBUG)
00034 //#warning DBG_ENABLED defined with NDEBUG which do you want?
00035 #endif
00036 
00292 namespace dbg
00293 {
00300     const int version = 110;
00301 
00302     /**************************************************************************
00303      * Debugging declarations
00304      *************************************************************************/
00305 
00325     enum level
00326     {
00327         info,
00328         warning,
00329         error,
00330         fatal,
00331         tracing,
00332         debug,
00333         none,
00334         all
00335     };
00336 
00353     enum assertion_behaviour
00354     {
00355         assertions_abort,
00356         assertions_throw,
00357         assertions_continue
00358     };
00359 
00379     typedef const char * dbg_source;
00380 
00381     /**************************************************************************
00382      * source_pos
00383      *************************************************************************/
00384 
00392     typedef const unsigned int line_no_t;
00393 
00402     typedef const char * func_name_t;
00403 
00411     typedef const char * file_name_t;
00412 
00431     struct source_pos
00432     {
00433         line_no_t   line;
00434         func_name_t func;
00435         file_name_t file;
00436         dbg_source  src;
00437 
00442         source_pos(line_no_t ln, func_name_t fn, file_name_t fl, dbg_source s)
00443             : line(ln), func(fn), file(fl), src(s) {}
00444 
00448         source_pos()
00449             : line(0), func(0), file(0), src(0) {}
00450     };
00451 
00452 #ifndef _MSC_VER
00453 
00466     typedef std::clock_t dbgclock_t;
00467 #else
00468 
00472     typedef clock_t dbgclock_t;
00473 #endif
00474 
00475     /**************************************************************************
00476      * Exceptions
00477      *************************************************************************/
00478 
00487     struct dbg_exception : public std::exception
00488     {
00489         dbg_exception(const source_pos &p) : pos(p) {}
00490         const source_pos pos;
00491     };
00492 
00498     struct assertion_exception : public dbg_exception
00499     {
00500         assertion_exception(const source_pos &p) : dbg_exception(p) {}
00501     };
00502 
00508     struct sentinel_exception : public dbg_exception
00509     {
00510         sentinel_exception(const source_pos &p) : dbg_exception(p) {}
00511     };
00512 
00518     struct unimplemented_exception : public dbg_exception
00519     {
00520         unimplemented_exception(const source_pos &p) : dbg_exception(p) {}
00521     };
00522 
00528     struct check_ptr_exception : public dbg_exception
00529     {
00530         check_ptr_exception(const source_pos &p) : dbg_exception(p) {}
00531     };
00532 
00533 #ifdef DBG_ENABLED
00534 
00535     /**************************************************************************
00536      * default_source
00537      *************************************************************************/
00538 
00554      extern dbg_source default_source;
00555 
00556     /**************************************************************************
00557      * Debug version of the DBG_HERE macro
00558      *************************************************************************/
00559 
00560     /*
00561      * DBG_FUNCTION is defined to be a macro that expands to the name of
00562      * the current function, or zero if the compiler is unable to supply that
00563      * information. It's sad that this wasn't included in the C++ standard
00564      * from the very beginning.
00565      */
00566     #if defined(__GNUC__)
00567     #define DBG_FUNCTION __FUNCTION__
00568     #else
00569     #define DBG_FUNCTION 0
00570     #endif
00571 
00572     #if !defined(DBG_SOURCE)
00573     #define DBG_SOURCE 0
00574     #endif
00575 
00576     /*
00577      * Handy macro to generate a @ref source_pos object containing the
00578      * information of the current source line.
00579      *
00580      * @see dbg::source_pos
00581      */
00582     #define DBG_HERE \
00583         (::dbg::source_pos(__LINE__, DBG_FUNCTION, __FILE__, DBG_SOURCE))
00584 
00585     /**************************************************************************
00586      * Enable/disable dbg facilities
00587      *************************************************************************/
00588 
00616     void enable(level lvl, bool enabled);
00617 
00638     void enable(level lvl, dbg_source src, bool enabled);
00639 
00651     void enable_all(level lvl, bool enabled);
00652 
00653     /**************************************************************************
00654      * Logging
00655      *************************************************************************/
00656 
00678     std::ostream &out(level lvl, dbg_source src);
00679 
00703     inline std::ostream &out(level lvl)
00704     {
00705         return out(lvl, 0);
00706     }
00707 
00729     void attach_ostream(level lvl, std::ostream &o);
00730 
00742     void attach_ostream(level lvl, dbg_source src, std::ostream &o);
00743 
00757     void detach_ostream(level lvl, std::ostream &o);
00758 
00770     void detach_ostream(level lvl, dbg_source src, std::ostream &o);
00771 
00780     void detach_all_ostreams(level lvl);
00781 
00791     void detach_all_ostreams(level lvl, dbg_source src);
00792 
00799     inline std::ostream &info_out()
00800     {
00801         return out(dbg::info);
00802     }
00803 
00810     inline std::ostream &warning_out()
00811     {
00812         return out(dbg::warning);
00813     }
00814 
00821     inline std::ostream &error_out()
00822     {
00823         return out(dbg::error);
00824     }
00825 
00832     inline std::ostream &fatal_out()
00833     {
00834         return out(dbg::fatal);
00835     }
00836 
00843     inline std::ostream &trace_out()
00844     {
00845         return out(dbg::tracing);
00846     }
00847 
00848     /**************************************************************************
00849      * Output formatting
00850      *************************************************************************/
00851 
00861     void set_prefix(const char *prefix);
00862 
00874     void enable_level_prefix(bool enabled);
00875 
00891     void enable_time_prefix(bool enabled);
00892 
00917     struct prefix
00918     {
00923         prefix() : l(none) {}
00924 
00928         prefix(level lvl) : l(lvl) {}
00929 
00930         level l;
00931     };
00932 
00939     std::ostream &operator<<(std::ostream &s, const prefix &p);
00940 
00960     struct indent
00961     {
00966         indent() : l(none) {}
00967 
00971         indent(level lvl) : l(lvl) {}
00972 
00973         level l;
00974     };
00975 
00982     std::ostream &operator<<(std::ostream &s, const indent &i);
00983 
01004     std::ostream &operator<<(std::ostream &s, const source_pos &pos);
01005 
01006     /**************************************************************************
01007      * Behaviour
01008      *************************************************************************/
01009 
01030     void set_assertion_behaviour(level lvl, assertion_behaviour behaviour);
01031 
01080     void set_assertion_period(dbgclock_t period);
01081 
01082     /**************************************************************************
01083      * Assertion
01084      *************************************************************************/
01085 
01095     struct assert_info : public source_pos
01096     {
01097         bool        asserted;
01098         const char *text;
01099 
01105         assert_info(bool a, const char *t,
01106                     line_no_t line, func_name_t func,
01107                     file_name_t file, dbg_source spos)
01108             : source_pos(line, func, file, spos), asserted(a), text(t) {}
01109 
01115         assert_info(bool a, const char *b, const source_pos &sp)
01116             : source_pos(sp), asserted(a), text(b) {}
01117     };
01118 
01119     /*
01120      * Utility macro used by the DBG_ASSERTION macro - it converts a
01121      * macro parameter into a character string.
01122      */
01123     #define DBG_STRING(a) #a
01124 
01125     /*
01126      * Handy macro used by clients of the @ref dbg::assertion function.
01127      * It use is described in the @ref assertion documentation.
01128      *
01129      * @see dbg::assertion
01130      */
01131     #define DBG_ASSERTION(a) \
01132         ::dbg::assert_info(a, DBG_STRING(a), DBG_HERE)
01133 
01164     void assertion(level lvl, dbg_source src, const assert_info &ai);
01165 
01173     inline void assertion(level lvl, const assert_info &ai)
01174     {
01175         assertion(lvl, 0, ai);
01176     }
01177 
01185     inline void assertion(dbg_source src, const assert_info &ai)
01186     {
01187         assertion(warning, src, ai);
01188     }
01189 
01196     inline void assertion(const assert_info &ai)
01197     {
01198         assertion(warning, 0, ai);
01199     }
01200 
01201     /**************************************************************************
01202      * Sentinel
01203      *************************************************************************/
01204 
01224     void sentinel(level lvl, dbg_source src, const source_pos &here);
01225 
01233     inline void sentinel(level lvl, const source_pos &here)
01234     {
01235         sentinel(lvl, 0, here);
01236     }
01237 
01245     inline void sentinel(dbg_source src, const source_pos &here)
01246     {
01247         sentinel(warning, src, here);
01248     }
01249 
01256     inline void sentinel(const source_pos &here)
01257     {
01258         sentinel(warning, 0, here);
01259     }
01260 
01261     /**************************************************************************
01262      * Unimplemented
01263      *************************************************************************/
01264 
01291     void unimplemented(level lvl, dbg_source src, const source_pos &here);
01292 
01300     inline void unimplemented(level lvl, const source_pos &here)
01301     {
01302         unimplemented(lvl, 0, here);
01303     }
01304 
01312     inline void unimplemented(dbg_source src, const source_pos &here)
01313     {
01314         unimplemented(warning, src, here);
01315     }
01316 
01323     inline void unimplemented(const source_pos &here)
01324     {
01325         unimplemented(warning, 0, here);
01326     }
01327 
01328     /**************************************************************************
01329      * Pointer checking
01330      *************************************************************************/
01331 
01349     void check_ptr(level lvl, dbg_source src, const void *p, const source_pos &here);
01350 
01359     inline void check_ptr(level lvl, const void *p, const source_pos &here)
01360     {
01361         check_ptr(lvl, 0, p, here);
01362     }
01363 
01372     inline void check_ptr(dbg_source src, const void *p, const source_pos &here)
01373     {
01374         check_ptr(warning, src, p, here);
01375     }
01376 
01384     inline void check_ptr(const void *p, const source_pos &here)
01385     {
01386         check_ptr(warning, 0, p, here);
01387     }
01388 
01389     /**************************************************************************
01390      * Bounds checking
01391      *************************************************************************/
01392 
01404     template <class T>
01405     inline unsigned int array_size(T &array)
01406     {
01407         return sizeof(array)/sizeof(array[0]);
01408     }
01409 
01424     void check_bounds(level lvl, dbg_source src,
01425                       int index, int bound, const source_pos &here);
01442     inline void check_bounds(level lvl, dbg_source src,
01443                              int index, int minbound, int maxbound,
01444                              const source_pos &here)
01445     {
01446         check_bounds(lvl, src, index-minbound, maxbound, here);
01447     }
01448 
01467     template <class T>
01468     void check_bounds(level lvl, dbg_source src,
01469                       int index, T &array, const source_pos &here)
01470     {
01471         check_bounds(lvl, src, index, array_size(array), here);
01472     }
01473 
01483     template <class T>
01484     void check_bounds(level lvl, int index, T &array, const source_pos &here)
01485     {
01486         check_bounds(lvl, 0, index, array_size(array), here);
01487     }
01488 
01498     template <class T>
01499     void check_bounds(dbg_source src, int index, T &array,
01500                       const source_pos &here)
01501     {
01502         check_bounds(warning, src, index, array_size(array), here);
01503     }
01504 
01513     template <class T>
01514     void check_bounds(int index, T &array, const source_pos &here)
01515     {
01516         check_bounds(warning, 0, index, array_size(array), here);
01517     }
01518 
01519     /**************************************************************************
01520      * Tracing
01521      *************************************************************************/
01522 
01581     class trace
01582     {
01583         public:
01584 
01593             trace(func_name_t name);
01594 
01599             trace(dbg_source src, func_name_t name);
01600 
01607             trace(const source_pos &here);
01608 
01613             trace(dbg_source src, const source_pos &here);
01614 
01615             ~trace();
01616 
01617         private:
01618 
01619             trace(const trace &);
01620             trace &operator=(const trace &);
01621 
01622             void trace_begin();
01623             void trace_end();
01624 
01625             dbg_source        m_src;
01626             const char       *m_name;
01627             const source_pos  m_pos;
01628             bool              m_triggered;
01629     };
01630 
01631     /**************************************************************************
01632      * Post conditions
01633      *************************************************************************/
01634 
01690     template <class obj_t>
01691     class post_mem_fun
01692     {
01693         public:
01694 
01699             typedef bool (obj_t::*fn_t)();
01700 
01707             post_mem_fun(level lvl, obj_t *obj, fn_t fn, const source_pos &pos)
01708                 : m_lvl(lvl), m_src(0), m_obj(obj), m_fn(fn), m_pos(pos) {}
01709 
01717             post_mem_fun(level lvl, dbg_source src,
01718                          obj_t *obj, fn_t fn, const source_pos &pos)
01719                 : m_lvl(lvl), m_src(src), m_obj(obj), m_fn(fn), m_pos(pos) {}
01720 
01729             post_mem_fun(obj_t *obj, fn_t fn, const source_pos &pos)
01730                 : m_lvl(dbg::warning), m_src(0),
01731                   m_obj(obj), m_fn(fn), m_pos(pos) {}
01732 
01742             post_mem_fun(dbg_source src, obj_t *obj, fn_t fn,
01743                          const source_pos &pos)
01744                 : m_lvl(dbg::warning), m_src(src),
01745                   m_obj(obj), m_fn(fn), m_pos(pos) {}
01746 
01750             ~post_mem_fun()
01751             {
01752                 assertion(m_lvl, m_src,
01753                           assert_info((m_obj->*m_fn)(), "post condition",
01754                           m_pos.line, m_pos.func, m_pos.file, m_pos.src));
01755             }
01756 
01757         private:
01758 
01759             const level       m_lvl;
01760             const dbg_source  m_src;
01761             obj_t            *m_obj;
01762             fn_t              m_fn;
01763             const source_pos  m_pos;
01764     };
01765 
01777     class post
01778     {
01779         public:
01780 
01785             typedef bool (*fn_t)();
01786 
01792             post(level lvl, fn_t fn, const source_pos &pos)
01793                 : m_lvl(lvl), m_src(0), m_fn(fn), m_pos(pos) {}
01794 
01801             post(level lvl, dbg_source src, fn_t fn, const source_pos &pos)
01802                 : m_lvl(lvl), m_src(src), m_fn(fn), m_pos(pos) {}
01803 
01811             post(fn_t fn, const source_pos &pos)
01812                 : m_lvl(dbg::warning), m_src(0), m_fn(fn), m_pos(pos) {}
01813 
01822             post(dbg_source src, fn_t fn, const source_pos &pos)
01823                 : m_lvl(dbg::warning), m_src(src), m_fn(fn), m_pos(pos) {}
01824 
01828             ~post()
01829             {
01830                 assertion(m_lvl, m_src,
01831                           assert_info(m_fn(), "post condition",
01832                           m_pos.line, m_pos.func, m_pos.file, m_pos.src));
01833             }
01834 
01835         private:
01836 
01837             level            m_lvl;
01838             const dbg_source m_src;
01839             fn_t             m_fn;
01840             const source_pos m_pos;
01841     };
01842 
01843     /**************************************************************************
01844      * Compile time assertions
01845      *************************************************************************/
01846 
01866     template <bool expression>
01867     class compile_assertion;
01868     template <>
01869     class compile_assertion<true> {};
01870 
01871 #else
01872 
01873     /**************************************************************************
01874      * Non-debug stub versions
01875      *************************************************************************/
01876 
01877     /*
01878      * With debugging switched off we generate null versions of the above
01879      * definitions.
01880      *
01881      * Given a good compiler and a strong prevailing headwind, these will
01882      * optimise away to nothing.
01883      */
01884 
01885     #define DBG_HERE         ((void*)0)
01886     #define DBG_ASSERTION(a) ((void*)0)
01887 
01888     //enum { default_source = 0xdead };
01889     const dbg_source default_source = 0;
01890 
01897     class null_stream
01898     {
01899         public:
01900 #ifdef _MSC_VER
01901             null_stream &operator<<(void *)        { return *this; }
01902             null_stream &operator<<(const void *)  { return *this; }
01903             null_stream &operator<<(long)          { return *this; }
01904 #else
01905             template <class otype>
01906             null_stream &operator<<(const otype &) { return *this; }
01907 #endif
01908 
01909             template <class otype>
01910             null_stream &operator<<(otype &)       { return *this; }
01911             null_stream &operator<<(std::ostream& (*)(std::ostream&))
01912               {
01913                 return *this;
01914               }
01915     };
01916 
01917     struct prefix { prefix() {} prefix(level) {} };
01918     struct indent { indent() {} indent(level) {} };
01919 
01920     inline void        enable(level, bool)                                 {}
01921     inline void        enable(level, dbg_source, bool)                     {}
01922     inline void        enable_all(level, bool)                             {}
01923     inline null_stream out(level, dbg_source)         {return null_stream();}
01924     inline null_stream out(level)                     {return null_stream();}
01925     inline void        attach_ostream(level, std::ostream &)               {}
01926     inline void        attach_ostream(level, dbg_source, std::ostream &)   {}
01927     inline void        detach_ostream(level, std::ostream &)               {}
01928     inline void        detach_ostream(level, dbg_source, std::ostream &)   {}
01929     inline void        detach_all_ostreams(level)                          {}
01930     inline void        detach_all_ostreams(level, dbg_source)              {}
01931     inline null_stream info_out()                     {return null_stream();}
01932     inline null_stream warning_out()                  {return null_stream();}
01933     inline null_stream error_out()                    {return null_stream();}
01934     inline null_stream fatal_out()                    {return null_stream();}
01935     inline null_stream trace_out()                    {return null_stream();}
01936     inline void        set_prefix(const char *)                            {}
01937     inline void        enable_level_prefix(bool)                           {}
01938     inline void        enable_time_prefix(bool)                            {}
01939 
01940     inline void        set_assertion_behaviour(level, assertion_behaviour) {}
01941     inline void        set_assertion_period(dbgclock_t)                    {}
01942     inline void        assertion(level, dbg_source, void *)                {}
01943     inline void        assertion(level, void *)                            {}
01944     inline void        assertion(dbg_source, void *)                       {}
01945     inline void        assertion(void *)                                   {}
01946     inline void        sentinel(level, dbg_source, void *)                 {}
01947     inline void        sentinel(level, void *)                             {}
01948     inline void        sentinel(dbg_source, void *)                        {}
01949     inline void        sentinel(void *)                                    {}
01950     inline void        unimplemented(level, dbg_source, void *)            {}
01951     inline void        unimplemented(level, void *)                        {}
01952     inline void        unimplemented(dbg_source, void *)                   {}
01953     inline void        unimplemented(void *)                               {}
01954     inline void        check_ptr(level, dbg_source, const void *, void *)  {}
01955     inline void        check_ptr(level, const void *, void *)              {}
01956     inline void        check_ptr(dbg_source, const void *, void *)         {}
01957     inline void        check_ptr(const void *, void *)                     {}
01958     inline void        check_bounds(level, void *, int, int, void *)       {}
01959     inline void        check_bounds(level, dbg_source, int, void*, void*)  {}
01960     inline void        check_bounds(level, dbg_source, int, int,
01961                                     void *, void *)                        {}
01962     inline void        check_bounds(level, int, void *, void*)             {}
01963     inline void        check_bounds(void *, int, void *, void *)           {}
01964     inline void        check_bounds(int, void *, void *)                   {}
01965 
01966     class trace
01967     {
01968         public:
01969             trace(const char *fn_name)                                     {}
01970             trace(dbg_source, const char *fn_name)                         {}
01971             trace(void *here)                                              {}
01972             trace(dbg_source, void *here)                                  {}
01973             ~trace()                                                       {}
01974     };
01975 
01976     template <class obj_t>
01977     class post_mem_fun
01978     {
01979         public:
01980             typedef bool (obj_t::*fn_t)();
01981             post_mem_fun(level, void *, fn_t, void *)                      {}
01982             post_mem_fun(level, dbg_source, void *, fn_t, void *)          {}
01983             post_mem_fun(void *, fn_t, void *)                             {}
01984             post_mem_fun(dbg_source, void *, fn_t, void *)                 {}
01985             ~post_mem_fun()                                                {}
01986     };
01987     class post
01988     {
01989         public:
01990             typedef bool(*fn_t)();
01991             post(level, fn_t, void *)                                      {}
01992             post(level, dbg_source, fn_t, void *)                          {}
01993             post(fn_t, void *)                                             {}
01994             post(dbg_source, fn_t, void *)                                 {}
01995             ~post()                                                        {}
01996     };
01997 
01998     template <bool expression>
01999     class compile_assertion {};
02000 
02001 #endif
02002 }
02003 
02004 #endif

Generated on Tue Sep 18 04:19:15 2007 for libdbg by  doxygen 1.5.3