00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef DBG_ENABLED
00020 #define DBG_ENABLED
00021 #endif
00022
00023 #include "dbg.h"
00024
00025 #include <iostream>
00026 #include <cstdlib>
00027 #include <cstring>
00028 #include <cstdio>
00029 #include <string>
00030 #include <vector>
00031 #include <map>
00032 #include <algorithm>
00033 #include <new>
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 #ifdef _MSC_VER
00087 #define STDCLK
00088 #pragma warning(disable:4786)
00089 #else
00090
00091
00092
00093
00094 #define STDCLK std
00095 #endif
00096
00097
00098 #ifdef __BCPLUSPLUS__
00099 #pragma warn -8066
00100 #pragma warn -8071
00101 #pragma warn -8070
00102 #endif
00103
00104
00105
00106
00107
00108 namespace
00109 {
00110
00111
00112
00113
00114 const char *LEVEL_NAMES[] =
00115 {
00116 "info",
00117 "warning",
00118 "error",
00119 "fatal",
00120 "tracing",
00121 "debug",
00122 "none",
00123 "all"
00124 };
00125 const char *BEHAVIOUR_NAMES[] =
00126 {
00127 "assertions_abort",
00128 "assertions_throw",
00129 "assertions_continue"
00130 };
00131 enum constraint_type
00132 {
00133 why_assertion,
00134 why_sentinel,
00135 why_unimplemented,
00136 why_check_ptr
00137 };
00138
00139 const char *TRACE_IN = "->";
00140 const char *TRACE_OUT = "<-";
00141 const char *INDENT = " ";
00142 const char *PREFIX = "*** ";
00143 const char *TRUE_STRING = "true";
00144 const char *FALSE_STRING = "false";
00145 const unsigned int ALL_SOURCES_MASK = 0xff;
00146 const unsigned int NUM_DBG_LEVELS = dbg::all-1;
00147
00148
00149
00150
00151
00158 struct period_data
00159 {
00160 size_t no_triggers;
00161 STDCLK::clock_t triggered_at;
00162
00163 period_data();
00164 };
00165
00171 struct lt_sp
00172 {
00173 bool operator()(const dbg::source_pos &a, const dbg::source_pos &b)
00174 const
00175 {
00176 if (a.file == b.file)
00177 {
00178 if (a.func == b.func)
00179 {
00180 return a.line < b.line;
00181 }
00182 else
00183 {
00184 return a.func < b.func;
00185 }
00186 }
00187 else
00188 {
00189 return a.file < b.file;
00190 }
00191 }
00192 };
00193
00205 class dbg_streambuf : public std::streambuf
00206 {
00207 public:
00208
00209 dbg_streambuf(std::vector<std::ostream*> &ostreams, int bsize = 0);
00210 ~dbg_streambuf();
00211
00212 int pubsync() { return sync(); }
00213
00214 protected:
00215
00216 int overflow(int);
00217 int sync();
00218
00219 private:
00220
00221 void put_buffer(void);
00222 void put_char(int);
00223
00224 std::vector<std::ostream *> &ostreams;
00225 };
00226
00237 class null_streambuf : public std::streambuf
00238 {
00239 public:
00240
00241 null_streambuf() {}
00242 ~null_streambuf() {}
00243
00244 protected:
00245
00246 int overflow(int) { return 0; }
00247 int sync() { return 0; }
00248 };
00249
00259 class dbg_ostream : public std::ostream
00260 {
00261 public:
00262
00263 #ifndef _MSC_VER
00264 dbg_ostream() : std::ostream(&dbg_buf), dbg_buf(streams) {}
00265 dbg_ostream(const dbg_ostream &rhs)
00266 : std::ostream(&dbg_buf), streams(rhs.streams),
00267 dbg_buf(streams) {}
00268 #else
00269
00270
00271
00272
00273 dbg_ostream()
00274 : std::basic_ostream<char>(&dbg_buf), dbg_buf(streams) {}
00275 dbg_ostream(const dbg_ostream &rhs)
00276 : std::basic_ostream<char>(&dbg_buf), streams(rhs.streams),
00277 dbg_buf(streams) {}
00278 #endif
00279 ~dbg_ostream() { dbg_buf.pubsync(); }
00280
00281 void add(std::ostream &o);
00282 void remove(std::ostream &o);
00283 void clear();
00284
00285 private:
00286
00287 dbg_ostream &operator=(const dbg_ostream&);
00288
00289 typedef std::vector<std::ostream*> stream_vec_type;
00290
00291 stream_vec_type streams;
00292 dbg_streambuf dbg_buf;
00293 };
00294
00307 class source_info
00308 {
00309 public:
00310
00316 enum ConstructionStyle
00317 {
00318 ConstructTheDefaultSource = 0,
00319 ConstructCopyOfDefaultSource = 1
00320 };
00321
00322 source_info(ConstructionStyle cs = ConstructCopyOfDefaultSource);
00323 source_info(const source_info &rhs);
00324 ~source_info();
00325
00330 void enable(dbg::level lvl, bool enable);
00331
00335 bool enabled(dbg::level lvl) const
00336 {
00337 return (levels & dbg_source_mask(lvl)) != 0;
00338 }
00339
00343 void add_ostream(dbg::level lvl, std::ostream &o);
00344
00348 void remove_ostream(dbg::level lvl, std::ostream &o);
00349
00353 void clear_ostream(dbg::level lvl);
00354
00359 std::ostream &out(dbg::level lvl);
00360
00361 private:
00362
00367 static unsigned int dbg_source_mask(dbg::level lvl)
00368 {
00369 return (lvl != dbg::all) ? 1 << lvl : ALL_SOURCES_MASK;
00370 }
00371
00372 unsigned int levels;
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 struct array_type
00390 {
00391
00392
00393
00394
00395 dbg_ostream dbg_streams[NUM_DBG_LEVELS];
00396 };
00397 dbg_ostream *dbg_streams;
00398 unsigned char raw_dbg_streams[sizeof(array_type)];
00399
00400 array_type &raw_cast()
00401 {
00402 return *reinterpret_cast<array_type*>(raw_dbg_streams);
00403 }
00404 const array_type &raw_cast() const
00405 {
00406 return *reinterpret_cast<const array_type*>(raw_dbg_streams);
00407 }
00408 };
00409
00420 class source_map_type
00421 {
00422 public:
00423
00424 typedef std::map<std::string, source_info> map_type;
00425 typedef map_type::iterator iterator;
00426 typedef map_type::key_type key_type;
00427 #ifndef _MSC_VER
00428
00429
00430 typedef map_type::mapped_type data_type;
00431 #else
00432
00433 typedef source_info data_type;
00434 #endif
00435 source_map_type()
00436 {
00437
00438 _map.insert(
00439 std::make_pair(dbg::default_source,
00440 source_info(source_info::ConstructTheDefaultSource)));
00441
00442 _map.insert(
00443 std::make_pair(dbg::dbg_source(""),
00444 source_info(source_info::ConstructTheDefaultSource)));
00445 }
00446 iterator begin() { return _map.begin(); }
00447 iterator end() { return _map.end(); }
00448 data_type &operator[](key_type key) { return _map[key]; }
00449
00450 private:
00451
00452 map_type _map;
00453 };
00454
00455 typedef std::map<dbg::source_pos, period_data, lt_sp> period_map_type;
00456
00457
00458
00459
00460
00461
00462 std::ostream null_ostream(new null_streambuf());
00463
00464 dbg::assertion_behaviour behaviour[dbg::all+1] =
00465 {
00466 dbg::assertions_abort,
00467 dbg::assertions_abort,
00468 dbg::assertions_abort,
00469 dbg::assertions_abort,
00470 dbg::assertions_abort,
00471 dbg::assertions_abort,
00472 dbg::assertions_abort,
00473 dbg::assertions_abort
00474 };
00475
00476 unsigned int indent_depth = 0;
00477 std::string indent_prefix = PREFIX;
00478 bool level_prefix = false;
00479 bool time_prefix = false;
00480 STDCLK::clock_t period = 0;
00481 source_map_type source_map;
00482 period_map_type period_map;
00483
00484
00485
00486
00487
00491 void print_pos(std::ostream &out, const dbg::source_pos &where);
00492
00497 void print_pos_short(std::ostream &out, const dbg::source_pos &where);
00498
00503 void print_period_info(std::ostream &out, const dbg::source_pos &where);
00504
00509 void do_assertion_behaviour(dbg::level lvl, constraint_type why,
00510 const dbg::source_pos &pos);
00511
00516 void do_prefix(dbg::level lvl, std::ostream &s);
00517
00521 bool period_allows_impl(const dbg::source_pos &where);
00522
00531 inline bool period_allows(const dbg::source_pos &where)
00532 {
00533 return !period || period_allows_impl(where);
00534 }
00535
00541 void determine_source(dbg::dbg_source &src, const dbg::source_pos &here);
00542 }
00543
00544
00545
00546
00547
00548
00549 dbg::dbg_source dbg::default_source = "dbg::private::default_source";
00550
00551
00552
00553
00554
00555
00556 void dbg::enable(dbg::level lvl, bool enabled)
00557 {
00558 out(debug) << prefix(debug) << "dbg::enable(" << LEVEL_NAMES[lvl]
00559 << "," << (enabled ? TRUE_STRING : FALSE_STRING) << ")\n";
00560
00561 source_map[""].enable(lvl, enabled);
00562 }
00563
00564
00565 void dbg::enable(dbg::level lvl, dbg::dbg_source src, bool enabled)
00566 {
00567 out(debug) << prefix(debug) << "dbg::enable(" << LEVEL_NAMES[lvl]
00568 << ",\"" << src << "\","
00569 << (enabled ? TRUE_STRING : FALSE_STRING) << ")\n";
00570
00571 source_map[src].enable(lvl, enabled);
00572 }
00573
00574
00575 void dbg::enable_all(dbg::level lvl, bool enabled)
00576 {
00577 out(debug) << prefix(debug) << "dbg::enable_all("
00578 << LEVEL_NAMES[lvl] << ","
00579 << (enabled ? TRUE_STRING : FALSE_STRING) << ")\n";
00580
00581 source_map_type::iterator i = source_map.begin();
00582 for ( ; i != source_map.end(); ++i)
00583 {
00584 (i->second).enable(lvl, enabled);
00585 }
00586 }
00587
00588
00589
00590
00591
00592
00593 std::ostream &dbg::out(dbg::level lvl, dbg::dbg_source src)
00594 {
00595 return source_map[src ? src : ""].out(lvl);
00596 }
00597
00598
00599 void dbg::attach_ostream(dbg::level lvl, std::ostream &o)
00600 {
00601 out(debug) << prefix(debug) << "dbg::attach_ostream("
00602 << LEVEL_NAMES[lvl] << ",ostream)\n";
00603
00604 source_map[""].add_ostream(lvl, o);
00605 }
00606
00607
00608 void dbg::attach_ostream(dbg::level lvl, dbg::dbg_source src, std::ostream &o)
00609 {
00610 out(debug) << prefix(debug) << "dbg::attach_ostream("
00611 << LEVEL_NAMES[lvl]
00612 << ", \"" << src
00613 << "\" ,ostream)\n";
00614
00615 source_map[src].add_ostream(lvl, o);
00616 }
00617
00618
00619 void dbg::detach_ostream(dbg::level lvl, std::ostream &o)
00620 {
00621 out(debug) << prefix(debug) << "dbg::detach_ostream("
00622 << LEVEL_NAMES[lvl] << ")\n";
00623
00624 source_map[""].remove_ostream(lvl, o);
00625 }
00626
00627
00628 void dbg::detach_ostream(dbg::level lvl, dbg::dbg_source src, std::ostream &o)
00629 {
00630 out(debug) << prefix(debug) << "dbg::detach_ostream("
00631 << LEVEL_NAMES[lvl]
00632 << ", \"" << src
00633 << "\" ,ostream)\n";
00634
00635 source_map[src].remove_ostream(lvl, o);
00636 }
00637
00638
00639 void dbg::detach_all_ostreams(dbg::level lvl)
00640 {
00641 out(debug) << prefix(debug) << "dbg::detach_all_ostreams("
00642 << LEVEL_NAMES[lvl]
00643 << ")\n";
00644
00645 source_map[""].clear_ostream(lvl);
00646 }
00647
00648
00649 void dbg::detach_all_ostreams(dbg::level lvl, dbg::dbg_source src)
00650 {
00651 out(debug) << prefix(debug) << "dbg::detach_all_ostreams("
00652 << LEVEL_NAMES[lvl]
00653 << ", \"" << src << "\")\n";
00654
00655 source_map[src].clear_ostream(lvl);
00656 }
00657
00658
00659
00660
00661
00662
00663 void dbg::set_prefix(const char *pfx)
00664 {
00665 out(debug) << prefix(debug) << "dbg::set_prefix(" << pfx << ")\n";
00666
00667 indent_prefix = pfx;
00668 }
00669
00670
00671 void dbg::enable_level_prefix(bool enabled)
00672 {
00673 out(debug) << prefix(debug) << "dbg::enable_level_prefix("
00674 << (enabled ? TRUE_STRING : FALSE_STRING) << ")\n";
00675
00676 level_prefix = enabled;
00677 }
00678
00679
00680 void dbg::enable_time_prefix(bool enabled)
00681 {
00682 out(debug) << prefix(debug) << "dbg::enable_time_prefix("
00683 << (enabled ? TRUE_STRING : FALSE_STRING) << ")\n";
00684
00685 time_prefix = enabled;
00686 }
00687
00688
00689 std::ostream &dbg::operator<<(std::ostream &s, const prefix &p)
00690 {
00691 s << indent_prefix.c_str();
00692 do_prefix(p.l, s);
00693 return s;
00694 }
00695
00696
00697 std::ostream &dbg::operator<<(std::ostream &s, const indent &i)
00698 {
00699 s << indent_prefix.c_str();
00700 do_prefix(i.l, s);
00701 for (unsigned int n = 0; n < indent_depth; n++) s << INDENT;
00702 return s;
00703 }
00704
00705
00706 std::ostream &dbg::operator<<(std::ostream &s, const source_pos &pos)
00707 {
00708 print_pos(s, pos);
00709 return s;
00710 }
00711
00712
00713
00714
00715
00716
00717 void dbg::set_assertion_behaviour(level lvl, dbg::assertion_behaviour b)
00718 {
00719 out(debug) << prefix(debug) << "dbg::set_assertion_behaviour("
00720 << LEVEL_NAMES[lvl] << "," << BEHAVIOUR_NAMES[b] << ")\n";
00721
00722 if (lvl < dbg::all)
00723 {
00724 behaviour[lvl] = b;
00725 }
00726 else
00727 {
00728 for (int n = 0; n < dbg::all; n++)
00729 {
00730 behaviour[n] = b;
00731 }
00732 }
00733 }
00734
00735
00736 void dbg::set_assertion_period(dbgclock_t p)
00737 {
00738 out(debug) << prefix(debug) << "dbg::set_assertion_period("
00739 << p << ")\n";
00740
00741 if (!p && period)
00742 {
00743 period_map.clear();
00744 }
00745
00746 period = p;
00747
00748 if (p && STDCLK::clock() == -1)
00749 {
00750 period = p;
00751 out(debug) << prefix(debug)
00752 << "*** WARNING ***\n"
00753 << "Platform does not support std::clock, and so\n"
00754 << "dbg::set_assertion_period is not supported.\n";
00755 }
00756 }
00757
00758
00759
00760
00761
00762
00763 void dbg::assertion(dbg::level lvl, dbg::dbg_source src,
00764 const assert_info &info)
00765 {
00766 determine_source(src, info);
00767
00768 if (source_map[src].enabled(lvl) && !info.asserted && period_allows(info))
00769 {
00770 std::ostream &o = out(lvl, src);
00771
00772 o << indent(lvl) << "assertion \"" << info.text << "\" failed ";
00773 if (strcmp(src, ""))
00774 {
00775 o << "for \"" << src << "\" ";
00776 }
00777 o << "at ";
00778 print_pos(o, info);
00779 print_period_info(o, info);
00780 o << "\n";
00781
00782 do_assertion_behaviour(lvl, why_assertion, info);
00783 }
00784 }
00785
00786
00787
00788
00789
00790
00791 void dbg::sentinel(dbg::level lvl, dbg::dbg_source src, const source_pos &here)
00792 {
00793 determine_source(src, here);
00794
00795 if (source_map[src].enabled(lvl) && period_allows(here))
00796 {
00797 std::ostream &o = out(lvl, src);
00798 o << indent(lvl) << "sentinel reached at ";
00799 print_pos(o, here);
00800 print_period_info(o, here);
00801 o << "\n";
00802
00803 do_assertion_behaviour(lvl, why_sentinel, here);
00804 }
00805 }
00806
00807
00808
00809
00810
00811
00812 void dbg::unimplemented(dbg::level lvl, dbg::dbg_source src,
00813 const source_pos &here)
00814 {
00815 determine_source(src, here);
00816
00817 if (source_map[src].enabled(lvl) && period_allows(here))
00818 {
00819 std::ostream &o = out(lvl, src);
00820 o << indent(lvl) << "behaviour not yet implemented at ";
00821 print_pos(o, here);
00822 print_period_info(o, here);
00823 o << "\n";
00824
00825 do_assertion_behaviour(lvl, why_unimplemented, here);
00826 }
00827 }
00828
00829
00830
00831
00832
00833
00834 void dbg::check_ptr(dbg::level lvl, dbg::dbg_source src,
00835 const void *p, const source_pos &here)
00836 {
00837 determine_source(src, here);
00838
00839 if (source_map[src].enabled(lvl) && p == 0 && period_allows(here))
00840 {
00841 std::ostream &o = out(lvl, src);
00842 o << indent(lvl) << "pointer is zero at ";
00843 print_pos(o, here);
00844 print_period_info(o, here);
00845 o << "\n";
00846
00847 do_assertion_behaviour(lvl, why_check_ptr, here);
00848 }
00849 }
00850
00851
00852
00853
00854
00855
00856 void dbg::check_bounds(dbg::level lvl, dbg::dbg_source src,
00857 int index, int bound, const source_pos &here)
00858 {
00859 determine_source(src, here);
00860
00861 if (source_map[src].enabled(lvl)
00862 && index >= 0 && index >= bound
00863 && period_allows(here))
00864 {
00865 std::ostream &o = out(lvl, src);
00866 o << indent(lvl) << "index " << index << " is out of bounds ("
00867 << bound << ") at ";
00868 print_pos(o, here);
00869 print_period_info(o, here);
00870 o << "\n";
00871
00872 do_assertion_behaviour(lvl, why_check_ptr, here);
00873 }
00874 }
00875
00876
00877
00878
00879
00880
00881 dbg::trace::trace(func_name_t name)
00882 : m_src(0), m_name(name), m_pos(DBG_HERE), m_triggered(false)
00883 {
00884 determine_source(m_src, m_pos);
00885
00886 if (source_map[m_src].enabled(dbg::tracing))
00887 {
00888 trace_begin();
00889 }
00890 }
00891
00892
00893 dbg::trace::trace(dbg_source src, func_name_t name)
00894 : m_src(src), m_name(name), m_pos(DBG_HERE), m_triggered(false)
00895 {
00896 determine_source(m_src, m_pos);
00897
00898 if (source_map[m_src].enabled(dbg::tracing))
00899 {
00900 trace_begin();
00901 }
00902 }
00903
00904
00905 dbg::trace::trace(const source_pos &where)
00906 : m_src(0), m_name(0), m_pos(where), m_triggered(false)
00907 {
00908 determine_source(m_src, m_pos);
00909
00910 if (source_map[m_src].enabled(dbg::tracing))
00911 {
00912 trace_begin();
00913 }
00914 }
00915
00916
00917 dbg::trace::trace(dbg_source src, const source_pos &where)
00918 : m_src(src), m_name(0), m_pos(where), m_triggered(false)
00919 {
00920 determine_source(m_src, m_pos);
00921
00922 if (source_map[src].enabled(dbg::tracing))
00923 {
00924 trace_begin();
00925 }
00926 }
00927
00928
00929 dbg::trace::~trace()
00930 {
00931 if (m_triggered)
00932 {
00933 trace_end();
00934 }
00935 }
00936
00937
00938 void dbg::trace::trace_begin()
00939 {
00940 std::ostream &o = out(dbg::tracing, m_src);
00941 o << indent(tracing);
00942 indent_depth++;
00943 o << TRACE_IN;
00944 if (m_name)
00945 {
00946 o << m_name;
00947 }
00948 else
00949 {
00950 print_pos_short(o, m_pos);
00951 }
00952 if (m_src && strcmp(m_src, ""))
00953 {
00954 o << " (for \"" << m_src << "\")";
00955 }
00956 o << std::endl;
00957
00958 m_triggered = true;
00959 }
00960
00961
00962 void dbg::trace::trace_end()
00963 {
00964 std::ostream &o = out(dbg::tracing, m_src);
00965 indent_depth--;
00966 o << indent(tracing);
00967 o << TRACE_OUT;
00968 if (m_name)
00969 {
00970 o << m_name;
00971 }
00972 else
00973 {
00974 print_pos_short(o, m_pos);
00975 }
00976 if (m_src && strcmp(m_src, ""))
00977 {
00978 o << " (for \"" << m_src << "\")";
00979 }
00980 o << std::endl;
00981 }
00982
00983
00984
00985
00986
00987
00988 namespace
00989 {
00990
00991
00992
00993
00994 dbg_streambuf::dbg_streambuf(std::vector<std::ostream*> &o, int bsize)
00995 : ostreams(o)
00996 {
00997 if (bsize)
00998 {
00999 char *ptr = new char[bsize];
01000 setp(ptr, ptr + bsize);
01001 }
01002 else
01003 {
01004 setp(0, 0);
01005 }
01006 setg(0, 0, 0);
01007 }
01008
01009 dbg_streambuf::~dbg_streambuf()
01010 {
01011 sync();
01012 delete [] pbase();
01013 }
01014
01015 int dbg_streambuf::overflow(int c)
01016 {
01017 put_buffer();
01018 if (c != EOF)
01019 {
01020 if (pbase() == epptr())
01021 {
01022 put_char(c);
01023 }
01024 else
01025 {
01026 sputc(c);
01027 }
01028 }
01029 return 0;
01030 }
01031
01032 int dbg_streambuf::sync()
01033 {
01034 put_buffer();
01035 return 0;
01036 }
01037
01038 void dbg_streambuf::put_buffer(void)
01039 {
01040 if (pbase() != pptr())
01041 {
01042 std::vector<std::ostream *>::iterator i = ostreams.begin();
01043 while (i != ostreams.end())
01044 {
01045 (*i)->write(pbase(), pptr() - pbase());
01046 ++i;
01047 }
01048 setp(pbase(), epptr());
01049 }
01050 }
01051
01052 void dbg_streambuf::put_char(int c)
01053 {
01054 std::vector<std::ostream *>::iterator i = ostreams.begin();
01055 while (i != ostreams.end())
01056 {
01057 (**i) << static_cast<char>(c);
01058 ++i;
01059 }
01060 }
01061
01062
01063
01064
01065
01066
01067 void dbg_ostream::add(std::ostream &o)
01068 {
01069 if (std::find(streams.begin(), streams.end(), &o) == streams.end())
01070 {
01071 streams.push_back(&o);
01072 }
01073 }
01074
01075 void dbg_ostream::remove(std::ostream &o)
01076 {
01077 stream_vec_type::iterator i
01078 = std::find(streams.begin(), streams.end(), &o);
01079 if (i != streams.end())
01080 {
01081 streams.erase(i);
01082 }
01083 }
01084
01085 void dbg_ostream::clear()
01086 {
01087 streams.clear();
01088 }
01089
01090
01091
01092
01093
01094
01095 source_info::source_info(ConstructionStyle cs)
01096 : levels(cs ? source_map[dbg::default_source].levels : 0),
01097 dbg_streams(raw_cast().dbg_streams)
01098 {
01099 if (cs)
01100 {
01101 new (raw_dbg_streams)
01102 array_type(source_map[dbg::default_source].raw_cast());
01103 }
01104 else
01105 {
01106 new (raw_dbg_streams) array_type;
01107
01108 add_ostream(dbg::error, std::cerr);
01109 add_ostream(dbg::fatal, std::cerr);
01110 }
01111 }
01112
01113 source_info::source_info(const source_info &rhs)
01114 : levels(rhs.levels), dbg_streams(raw_cast().dbg_streams)
01115 {
01116 new (raw_dbg_streams) array_type(rhs.raw_cast());
01117 }
01118
01119 source_info::~source_info()
01120 {
01121 raw_cast().~array_type();
01122 }
01123
01124 void source_info::enable(dbg::level lvl, bool status)
01125 {
01126 levels &= ~dbg_source_mask(lvl);
01127 if (status)
01128 {
01129 levels |= dbg_source_mask(lvl);
01130 }
01131 }
01132
01133 void source_info::add_ostream(dbg::level lvl, std::ostream &o)
01134 {
01135 if (lvl == dbg::all)
01136 {
01137 for (unsigned int n = 0; n < NUM_DBG_LEVELS; ++n)
01138 {
01139 dbg_streams[n].add(o);
01140 }
01141 }
01142 else
01143 {
01144 dbg_streams[lvl].add(o);
01145 }
01146 }
01147
01148 void source_info::remove_ostream(dbg::level lvl, std::ostream &o)
01149 {
01150 if (lvl == dbg::all)
01151 {
01152 for (unsigned int n = 0; n < NUM_DBG_LEVELS; ++n)
01153 {
01154 dbg_streams[n].remove(o);
01155 }
01156 }
01157 else
01158 {
01159 dbg_streams[lvl].remove(o);
01160 }
01161 }
01162
01163 void source_info::clear_ostream(dbg::level lvl)
01164 {
01165 if (lvl == dbg::all)
01166 {
01167 for (unsigned int n = 0; n < NUM_DBG_LEVELS; ++n)
01168 {
01169 dbg_streams[n].clear();
01170 }
01171 }
01172 else
01173 {
01174 dbg_streams[lvl].clear();
01175 }
01176 }
01177
01178 std::ostream &source_info::out(dbg::level lvl)
01179 {
01180 if (lvl == dbg::none || !enabled(lvl))
01181 {
01182 return null_ostream;
01183 }
01184 else
01185 {
01186 return dbg_streams[lvl];
01187 }
01188 }
01189
01190
01191
01192
01193
01194
01195 period_data::period_data()
01196 : no_triggers(0), triggered_at(STDCLK::clock() - period*2)
01197 {
01198 }
01199
01200
01201
01202
01203
01204
01205 void print_pos(std::ostream &out, const dbg::source_pos &where)
01206 {
01207 if (where.file)
01208 {
01209 if (where.func)
01210 {
01211 out << "function: " << where.func << ", ";
01212 }
01213 out << "line: " << where.line << ", file: " << where.file;
01214 }
01215 }
01216
01217 void print_pos_short(std::ostream &out, const dbg::source_pos &where)
01218 {
01219 if (where.file)
01220 {
01221 if (where.func)
01222 {
01223 out << where.func << " (" << where.line
01224 << " in " << where.file << ")";
01225 }
01226 else
01227 {
01228 out << "function at (" << where.line
01229 << " in " << where.file << ")";
01230 }
01231 }
01232 }
01233
01234 void print_period_info(std::ostream &out, const dbg::source_pos &where)
01235 {
01236 if (period)
01237 {
01238 size_t no_triggers = period_map[where].no_triggers;
01239 out << " (triggered " << no_triggers << " time";
01240 if (no_triggers > 1)
01241 {
01242 out << "s)";
01243 }
01244 else
01245 {
01246 out << ")";
01247 }
01248 }
01249 }
01250
01251 void do_assertion_behaviour(dbg::level lvl, constraint_type why,
01252 const dbg::source_pos &pos)
01253 {
01254 switch (lvl != dbg::fatal ? behaviour[lvl] : dbg::assertions_abort)
01255 {
01256 case dbg::assertions_abort:
01257 {
01258 abort();
01259 break;
01260 }
01261 case dbg::assertions_throw:
01262 {
01263 switch (why)
01264 {
01265 default:
01266 case why_assertion:
01267 {
01268 throw dbg::assertion_exception(pos);
01269 break;
01270 }
01271 case why_sentinel:
01272 {
01273 throw dbg::sentinel_exception(pos);
01274 break;
01275 }
01276 case why_unimplemented:
01277 {
01278 throw dbg::unimplemented_exception(pos);
01279 break;
01280 }
01281 case why_check_ptr:
01282 {
01283 throw dbg::check_ptr_exception(pos);
01284 break;
01285 }
01286 }
01287 break;
01288 }
01289 case dbg::assertions_continue:
01290 default:
01291 {
01292 break;
01293 }
01294 }
01295 }
01296
01297 void do_prefix(dbg::level lvl, std::ostream &s)
01298 {
01299 if (time_prefix)
01300 {
01301 STDCLK::time_t t = STDCLK::time(0);
01302 if (t != -1)
01303 {
01304 s << std::string(STDCLK::ctime(&t), 24) << ": ";
01305 }
01306 }
01307 if (level_prefix)
01308 {
01309 switch (lvl)
01310 {
01311 case dbg::info: { s << " info: "; break; }
01312 case dbg::warning: { s << "warning: "; break; }
01313 case dbg::error: { s << " error: "; break; }
01314 case dbg::fatal: { s << " fatal: "; break; }
01315 case dbg::tracing: { s << " trace: "; break; }
01316 case dbg::debug: { s << " debug: "; break; }
01317 case dbg::none: { break; }
01318 case dbg::all: { s << " all: "; break; }
01319 }
01320 }
01321 }
01322
01323 bool period_allows_impl(const dbg::source_pos &where)
01324 {
01325 period_data &data = period_map[where];
01326 data.no_triggers++;
01327 if (data.triggered_at < STDCLK::clock() - period)
01328 {
01329 data.triggered_at = STDCLK::clock();
01330 return true;
01331 }
01332 else
01333 {
01334 return false;
01335 }
01336 }
01337
01338 void determine_source(dbg::dbg_source &src, const dbg::source_pos &here)
01339 {
01340 if (!src) src = "";
01341 if (src == "" && here.src)
01342 {
01343 src = here.src;
01344 }
01345 }
01346 }