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