libdbg  1.2
dbg.h
1 /*
2  * File: dbg.h
3  * Author: Pete Goodliffe
4  * Version: 1.10
5  * Created: 7 June 2001
6  *
7  * Purpose: C++ debugging support library
8  *
9  * Copyright (c) Pete Goodliffe 2001-2002 (pete@cthree.org)
10  *
11  * This file is modifiable/redistributable under the terms of the GNU
12  * Lesser General Public License.
13  *
14  * You should have recieved a copy of the GNU General Public License along
15  * with this program; see the file COPYING. If not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 0211-1307, USA.
17  */
18 
19 #ifndef DBG_DBG_H
20 #define DBG_DBG_H
21 
22 #include <iosfwd>
23 #include <exception>
24 
25 #ifndef _MSC_VER
26 #include <ctime>
27 #else
28 // The start of a MSVC compatibility disaster area.
29 // See the documentation for the dbgclock_t type.
30 #include <time.h>
31 #endif
32 
33 #if defined(DBG_ENABLED) && defined(NDEBUG)
34 //#warning DBG_ENABLED defined with NDEBUG which do you want?
35 #endif
36 
292 namespace dbg
293 {
300  const int version = 110;
301 
302  /**************************************************************************
303  * Debugging declarations
304  *************************************************************************/
305 
325  enum level
326  {
327  info,
328  warning,
329  error,
330  fatal,
331  tracing,
332  debug,
333  none,
334  all
335  };
336 
354  {
355  assertions_abort,
356  assertions_throw,
357  assertions_continue
358  };
359 
379  typedef const char * dbg_source;
380 
381  /**************************************************************************
382  * source_pos
383  *************************************************************************/
384 
392  typedef const unsigned int line_no_t;
393 
402  typedef const char * func_name_t;
403 
411  typedef const char * file_name_t;
412 
431  struct source_pos
432  {
433  line_no_t line;
434  func_name_t func;
435  file_name_t file;
436  dbg_source src;
437 
443  : line(ln), func(fn), file(fl), src(s) {}
444 
449  : line(0), func(0), file(0), src(0) {}
450  };
451 
452 #ifndef _MSC_VER
453 
466  typedef std::clock_t dbgclock_t;
467 #else
468 
472  typedef clock_t dbgclock_t;
473 #endif
474 
475  /**************************************************************************
476  * Exceptions
477  *************************************************************************/
478 
487  struct dbg_exception : public std::exception
488  {
489  dbg_exception(const source_pos &p) : pos(p) {}
490  const source_pos pos;
491  };
492 
499  {
501  };
502 
509  {
511  };
512 
519  {
521  };
522 
529  {
531  };
532 
533 #ifdef DBG_ENABLED
534 
535  /**************************************************************************
536  * default_source
537  *************************************************************************/
538 
554  extern dbg_source default_source;
555 
556  /**************************************************************************
557  * Debug version of the DBG_HERE macro
558  *************************************************************************/
559 
560  /*
561  * DBG_FUNCTION is defined to be a macro that expands to the name of
562  * the current function, or zero if the compiler is unable to supply that
563  * information. It's sad that this wasn't included in the C++ standard
564  * from the very beginning.
565  */
566  #if defined(__GNUC__)
567  #define DBG_FUNCTION __FUNCTION__
568  #else
569  #define DBG_FUNCTION 0
570  #endif
571 
572  #if !defined(DBG_SOURCE)
573  #define DBG_SOURCE 0
574  #endif
575 
576  /*
577  * Handy macro to generate a @ref source_pos object containing the
578  * information of the current source line.
579  *
580  * @see dbg::source_pos
581  */
582  #define DBG_HERE \
583  (::dbg::source_pos(__LINE__, DBG_FUNCTION, __FILE__, DBG_SOURCE))
584 
585  /**************************************************************************
586  * Enable/disable dbg facilities
587  *************************************************************************/
588 
616  void enable(level lvl, bool enabled);
617 
638  void enable(level lvl, dbg_source src, bool enabled);
639 
651  void enable_all(level lvl, bool enabled);
652 
653  /**************************************************************************
654  * Logging
655  *************************************************************************/
656 
678  std::ostream &out(level lvl, dbg_source src);
679 
703  inline std::ostream &out(level lvl)
704  {
705  return out(lvl, 0);
706  }
707 
729  void attach_ostream(level lvl, std::ostream &o);
730 
742  void attach_ostream(level lvl, dbg_source src, std::ostream &o);
743 
757  void detach_ostream(level lvl, std::ostream &o);
758 
770  void detach_ostream(level lvl, dbg_source src, std::ostream &o);
771 
780  void detach_all_ostreams(level lvl);
781 
791  void detach_all_ostreams(level lvl, dbg_source src);
792 
799  inline std::ostream &info_out()
800  {
801  return out(dbg::info);
802  }
803 
810  inline std::ostream &warning_out()
811  {
812  return out(dbg::warning);
813  }
814 
821  inline std::ostream &error_out()
822  {
823  return out(dbg::error);
824  }
825 
832  inline std::ostream &fatal_out()
833  {
834  return out(dbg::fatal);
835  }
836 
843  inline std::ostream &trace_out()
844  {
845  return out(dbg::tracing);
846  }
847 
848  /**************************************************************************
849  * Output formatting
850  *************************************************************************/
851 
861  void set_prefix(const char *prefix);
862 
874  void enable_level_prefix(bool enabled);
875 
891  void enable_time_prefix(bool enabled);
892 
917  struct prefix
918  {
923  prefix() : l(none) {}
924 
928  prefix(level lvl) : l(lvl) {}
929 
930  level l;
931  };
932 
939  std::ostream &operator<<(std::ostream &s, const prefix &p);
940 
960  struct indent
961  {
966  indent() : l(none) {}
967 
971  indent(level lvl) : l(lvl) {}
972 
973  level l;
974  };
975 
982  std::ostream &operator<<(std::ostream &s, const indent &i);
983 
1004  std::ostream &operator<<(std::ostream &s, const source_pos &pos);
1005 
1006  /**************************************************************************
1007  * Behaviour
1008  *************************************************************************/
1009 
1030  void set_assertion_behaviour(level lvl, assertion_behaviour behaviour);
1031 
1080  void set_assertion_period(dbgclock_t period);
1081 
1082  /**************************************************************************
1083  * Assertion
1084  *************************************************************************/
1085 
1095  struct assert_info : public source_pos
1096  {
1097  bool asserted;
1098  const char *text;
1099 
1105  assert_info(bool a, const char *t,
1106  line_no_t line, func_name_t func,
1107  file_name_t file, dbg_source spos)
1108  : source_pos(line, func, file, spos), asserted(a), text(t) {}
1109 
1115  assert_info(bool a, const char *b, const source_pos &sp)
1116  : source_pos(sp), asserted(a), text(b) {}
1117  };
1118 
1119  /*
1120  * Utility macro used by the DBG_ASSERTION macro - it converts a
1121  * macro parameter into a character string.
1122  */
1123  #define DBG_STRING(a) #a
1124 
1125  /*
1126  * Handy macro used by clients of the @ref dbg::assertion function.
1127  * It use is described in the @ref assertion documentation.
1128  *
1129  * @see dbg::assertion
1130  */
1131  #define DBG_ASSERTION(a) \
1132  ::dbg::assert_info(a, DBG_STRING(a), DBG_HERE)
1133 
1164  void assertion(level lvl, dbg_source src, const assert_info &ai);
1165 
1173  inline void assertion(level lvl, const assert_info &ai)
1174  {
1175  assertion(lvl, 0, ai);
1176  }
1177 
1185  inline void assertion(dbg_source src, const assert_info &ai)
1186  {
1187  assertion(warning, src, ai);
1188  }
1189 
1196  inline void assertion(const assert_info &ai)
1197  {
1198  assertion(warning, 0, ai);
1199  }
1200 
1201  /**************************************************************************
1202  * Sentinel
1203  *************************************************************************/
1204 
1224  void sentinel(level lvl, dbg_source src, const source_pos &here);
1225 
1233  inline void sentinel(level lvl, const source_pos &here)
1234  {
1235  sentinel(lvl, 0, here);
1236  }
1237 
1245  inline void sentinel(dbg_source src, const source_pos &here)
1246  {
1247  sentinel(warning, src, here);
1248  }
1249 
1256  inline void sentinel(const source_pos &here)
1257  {
1258  sentinel(warning, 0, here);
1259  }
1260 
1261  /**************************************************************************
1262  * Unimplemented
1263  *************************************************************************/
1264 
1291  void unimplemented(level lvl, dbg_source src, const source_pos &here);
1292 
1300  inline void unimplemented(level lvl, const source_pos &here)
1301  {
1302  unimplemented(lvl, 0, here);
1303  }
1304 
1312  inline void unimplemented(dbg_source src, const source_pos &here)
1313  {
1314  unimplemented(warning, src, here);
1315  }
1316 
1323  inline void unimplemented(const source_pos &here)
1324  {
1325  unimplemented(warning, 0, here);
1326  }
1327 
1328  /**************************************************************************
1329  * Pointer checking
1330  *************************************************************************/
1331 
1349  void check_ptr(level lvl, dbg_source src, const void *p, const source_pos &here);
1350 
1359  inline void check_ptr(level lvl, const void *p, const source_pos &here)
1360  {
1361  check_ptr(lvl, 0, p, here);
1362  }
1363 
1372  inline void check_ptr(dbg_source src, const void *p, const source_pos &here)
1373  {
1374  check_ptr(warning, src, p, here);
1375  }
1376 
1384  inline void check_ptr(const void *p, const source_pos &here)
1385  {
1386  check_ptr(warning, 0, p, here);
1387  }
1388 
1389  /**************************************************************************
1390  * Bounds checking
1391  *************************************************************************/
1392 
1404  template <class T>
1405  inline unsigned int array_size(T &array)
1406  {
1407  return sizeof(array)/sizeof(array[0]);
1408  }
1409 
1424  void check_bounds(level lvl, dbg_source src,
1425  int index, int bound, const source_pos &here);
1442  inline void check_bounds(level lvl, dbg_source src,
1443  int index, int minbound, int maxbound,
1444  const source_pos &here)
1445  {
1446  check_bounds(lvl, src, index-minbound, maxbound, here);
1447  }
1448 
1467  template <class T>
1468  void check_bounds(level lvl, dbg_source src,
1469  int index, T &array, const source_pos &here)
1470  {
1471  check_bounds(lvl, src, index, array_size(array), here);
1472  }
1473 
1483  template <class T>
1484  void check_bounds(level lvl, int index, T &array, const source_pos &here)
1485  {
1486  check_bounds(lvl, 0, index, array_size(array), here);
1487  }
1488 
1498  template <class T>
1499  void check_bounds(dbg_source src, int index, T &array,
1500  const source_pos &here)
1501  {
1502  check_bounds(warning, src, index, array_size(array), here);
1503  }
1504 
1513  template <class T>
1514  void check_bounds(int index, T &array, const source_pos &here)
1515  {
1516  check_bounds(warning, 0, index, array_size(array), here);
1517  }
1518 
1519  /**************************************************************************
1520  * Tracing
1521  *************************************************************************/
1522 
1581  class trace
1582  {
1583  public:
1584 
1593  trace(func_name_t name);
1594 
1599  trace(dbg_source src, func_name_t name);
1600 
1607  trace(const source_pos &here);
1608 
1613  trace(dbg_source src, const source_pos &here);
1614 
1615  ~trace();
1616 
1617  private:
1618 
1619  trace(const trace &);
1620  trace &operator=(const trace &);
1621 
1622  void trace_begin();
1623  void trace_end();
1624 
1625  dbg_source m_src;
1626  const char *m_name;
1627  const source_pos m_pos;
1628  bool m_triggered;
1629  };
1630 
1631  /**************************************************************************
1632  * Post conditions
1633  *************************************************************************/
1634 
1690  template <class obj_t>
1691  class post_mem_fun
1692  {
1693  public:
1694 
1699  typedef bool (obj_t::*fn_t)();
1700 
1707  post_mem_fun(level lvl, obj_t *obj, fn_t fn, const source_pos &pos)
1708  : m_lvl(lvl), m_src(0), m_obj(obj), m_fn(fn), m_pos(pos) {}
1709 
1717  post_mem_fun(level lvl, dbg_source src,
1718  obj_t *obj, fn_t fn, const source_pos &pos)
1719  : m_lvl(lvl), m_src(src), m_obj(obj), m_fn(fn), m_pos(pos) {}
1720 
1729  post_mem_fun(obj_t *obj, fn_t fn, const source_pos &pos)
1730  : m_lvl(dbg::warning), m_src(0),
1731  m_obj(obj), m_fn(fn), m_pos(pos) {}
1732 
1742  post_mem_fun(dbg_source src, obj_t *obj, fn_t fn,
1743  const source_pos &pos)
1744  : m_lvl(dbg::warning), m_src(src),
1745  m_obj(obj), m_fn(fn), m_pos(pos) {}
1746 
1750  ~post_mem_fun()
1751  {
1752  assertion(m_lvl, m_src,
1753  assert_info((m_obj->*m_fn)(), "post condition",
1754  m_pos.line, m_pos.func, m_pos.file, m_pos.src));
1755  }
1756 
1757  private:
1758 
1759  const level m_lvl;
1760  const dbg_source m_src;
1761  obj_t *m_obj;
1762  fn_t m_fn;
1763  const source_pos m_pos;
1764  };
1765 
1777  class post
1778  {
1779  public:
1780 
1785  typedef bool (*fn_t)();
1786 
1792  post(level lvl, fn_t fn, const source_pos &pos)
1793  : m_lvl(lvl), m_src(0), m_fn(fn), m_pos(pos) {}
1794 
1801  post(level lvl, dbg_source src, fn_t fn, const source_pos &pos)
1802  : m_lvl(lvl), m_src(src), m_fn(fn), m_pos(pos) {}
1803 
1811  post(fn_t fn, const source_pos &pos)
1812  : m_lvl(dbg::warning), m_src(0), m_fn(fn), m_pos(pos) {}
1813 
1822  post(dbg_source src, fn_t fn, const source_pos &pos)
1823  : m_lvl(dbg::warning), m_src(src), m_fn(fn), m_pos(pos) {}
1824 
1828  ~post()
1829  {
1830  assertion(m_lvl, m_src,
1831  assert_info(m_fn(), "post condition",
1832  m_pos.line, m_pos.func, m_pos.file, m_pos.src));
1833  }
1834 
1835  private:
1836 
1837  level m_lvl;
1838  const dbg_source m_src;
1839  fn_t m_fn;
1840  const source_pos m_pos;
1841  };
1842 
1843  /**************************************************************************
1844  * Compile time assertions
1845  *************************************************************************/
1846 
1866  template <bool expression>
1867  class compile_assertion;
1868  template <>
1869  class compile_assertion<true> {};
1870 
1871 #else
1872 
1873  /**************************************************************************
1874  * Non-debug stub versions
1875  *************************************************************************/
1876 
1877  /*
1878  * With debugging switched off we generate null versions of the above
1879  * definitions.
1880  *
1881  * Given a good compiler and a strong prevailing headwind, these will
1882  * optimise away to nothing.
1883  */
1884 
1885  #define DBG_HERE ((void*)0)
1886  #define DBG_ASSERTION(a) ((void*)0)
1887 
1888  //enum { default_source = 0xdead };
1889  const dbg_source default_source = 0;
1890 
1898  {
1899  public:
1900 #ifdef _MSC_VER
1901  null_stream &operator<<(void *) { return *this; }
1902  null_stream &operator<<(const void *) { return *this; }
1903  null_stream &operator<<(long) { return *this; }
1904 #else
1905  template <class otype>
1906  null_stream &operator<<(const otype &) { return *this; }
1907 #endif
1908 
1909  template <class otype>
1910  null_stream &operator<<(otype &) { return *this; }
1911  null_stream &operator<<(std::ostream& (*)(std::ostream&))
1912  {
1913  return *this;
1914  }
1915  };
1916 
1917  struct prefix { prefix() {} prefix(level) {} };
1918  struct indent { indent() {} indent(level) {} };
1919 
1920  inline void enable(level, bool) {}
1921  inline void enable(level, dbg_source, bool) {}
1922  inline void enable_all(level, bool) {}
1923  inline null_stream out(level, dbg_source) {return null_stream();}
1924  inline null_stream out(level) {return null_stream();}
1925  inline void attach_ostream(level, std::ostream &) {}
1926  inline void attach_ostream(level, dbg_source, std::ostream &) {}
1927  inline void detach_ostream(level, std::ostream &) {}
1928  inline void detach_ostream(level, dbg_source, std::ostream &) {}
1929  inline void detach_all_ostreams(level) {}
1930  inline void detach_all_ostreams(level, dbg_source) {}
1931  inline null_stream info_out() {return null_stream();}
1932  inline null_stream warning_out() {return null_stream();}
1933  inline null_stream error_out() {return null_stream();}
1934  inline null_stream fatal_out() {return null_stream();}
1935  inline null_stream trace_out() {return null_stream();}
1936  inline void set_prefix(const char *) {}
1937  inline void enable_level_prefix(bool) {}
1938  inline void enable_time_prefix(bool) {}
1939 
1940  inline void set_assertion_behaviour(level, assertion_behaviour) {}
1941  inline void set_assertion_period(dbgclock_t) {}
1942  inline void assertion(level, dbg_source, void *) {}
1943  inline void assertion(level, void *) {}
1944  inline void assertion(dbg_source, void *) {}
1945  inline void assertion(void *) {}
1946  inline void sentinel(level, dbg_source, void *) {}
1947  inline void sentinel(level, void *) {}
1948  inline void sentinel(dbg_source, void *) {}
1949  inline void sentinel(void *) {}
1950  inline void unimplemented(level, dbg_source, void *) {}
1951  inline void unimplemented(level, void *) {}
1952  inline void unimplemented(dbg_source, void *) {}
1953  inline void unimplemented(void *) {}
1954  inline void check_ptr(level, dbg_source, const void *, void *) {}
1955  inline void check_ptr(level, const void *, void *) {}
1956  inline void check_ptr(dbg_source, const void *, void *) {}
1957  inline void check_ptr(const void *, void *) {}
1958  inline void check_bounds(level, void *, int, int, void *) {}
1959  inline void check_bounds(level, dbg_source, int, void*, void*) {}
1960  inline void check_bounds(level, dbg_source, int, int,
1961  void *, void *) {}
1962  inline void check_bounds(level, int, void *, void*) {}
1963  inline void check_bounds(void *, int, void *, void *) {}
1964  inline void check_bounds(int, void *, void *) {}
1965 
1966  class trace
1967  {
1968  public:
1969  trace(const char *fn_name) {}
1970  trace(dbg_source, const char *fn_name) {}
1971  trace(void *here) {}
1972  trace(dbg_source, void *here) {}
1973  ~trace() {}
1974  };
1975 
1976  template <class obj_t>
1978  {
1979  public:
1980  typedef bool (obj_t::*fn_t)();
1981  post_mem_fun(level, void *, fn_t, void *) {}
1982  post_mem_fun(level, dbg_source, void *, fn_t, void *) {}
1983  post_mem_fun(void *, fn_t, void *) {}
1984  post_mem_fun(dbg_source, void *, fn_t, void *) {}
1985  ~post_mem_fun() {}
1986  };
1987  class post
1988  {
1989  public:
1990  typedef bool(*fn_t)();
1991  post(level, fn_t, void *) {}
1992  post(level, dbg_source, fn_t, void *) {}
1993  post(fn_t, void *) {}
1994  post(dbg_source, fn_t, void *) {}
1995  ~post() {}
1996  };
1997 
1998  template <bool expression>
2000 
2001 #endif
2002 }
2003 
2004 #endif
dbg::assertion_behaviour
assertion_behaviour
This enum type describes what happens when a debugging assertion fails.
Definition: dbg.h:353
dbg::dbg_source
const typedef char * dbg_source
typedef for a string that describes the "source" of a diagnostic.
Definition: dbg.h:379
dbg::post_mem_fun
Definition: dbg.h:1977
dbg::trace
Definition: dbg.h:1966
dbg::level
level
The various predefined debugging levels.
Definition: dbg.h:325
dbg::unimplemented_exception
The type of exception thrown by unimplemented.
Definition: dbg.h:518
dbg::null_stream
In non-debug versions, this class is used to replace an ostream so that code will compile away.
Definition: dbg.h:1897
dbg::source_pos
Data structure describing a position in the source file.
Definition: dbg.h:431
dbg::check_ptr_exception
The type of exception thrown by check_ptr.
Definition: dbg.h:528
dbg::source_pos::source_pos
source_pos()
A 'null' source_pos for 'no position specified'.
Definition: dbg.h:448
dbg::assertion_exception
The type of exception thrown by assertion.
Definition: dbg.h:498
dbg::dbgclock_t
std::clock_t dbgclock_t
The dbgclock_t typedef is an unfortunate workaround for comptability purposes.
Definition: dbg.h:466
dbg::source_pos::source_pos
source_pos(line_no_t ln, func_name_t fn, file_name_t fl, dbg_source s)
Creates a source_pos struct.
Definition: dbg.h:442
dbg::indent
Definition: dbg.h:1918
dbg::func_name_t
const typedef char * func_name_t
Typedef used in the source_pos data structure.
Definition: dbg.h:402
dbg::line_no_t
const typedef unsigned int line_no_t
Typedef used in the source_pos data structure.
Definition: dbg.h:392
dbg
@libdoc dbg library
Definition: dbg.h:292
dbg::dbg_exception
The base type of exception thrown by dbg assertions (and other dbg library constraint checks) if the ...
Definition: dbg.h:487
dbg::version
const int version
This is the version number of the dbg library.
Definition: dbg.h:300
dbg::sentinel_exception
The type of exception thrown by sentinel.
Definition: dbg.h:508
dbg::compile_assertion
Definition: dbg.h:1999
dbg::post
Definition: dbg.h:1987
dbg::file_name_t
const typedef char * file_name_t
Typedef used in the source_pos data structure.
Definition: dbg.h:411
dbg::prefix
Definition: dbg.h:1917