Commit | Line | Data |
---|---|---|
0e23f538 TJ |
1 | /* |
2 | The software in this package is distributed under the GNU General | |
3 | Public License version 2 (with a special exception described below). | |
4 | ||
5 | A copy of GNU General Public License (GPL) is included in this distribution, | |
6 | in the file COPYING.GPL. | |
7 | ||
8 | As a special exception, if other files instantiate templates or use macros | |
9 | or inline functions from this file, or you compile this file and link it | |
10 | with other works to produce a work based on this file, this file | |
11 | does not by itself cause the resulting work to be covered | |
12 | by the GNU General Public License. | |
13 | ||
14 | However the source code for this file must still be made available | |
15 | in accordance with section (3) of the GNU General Public License. | |
16 | ||
17 | This exception does not invalidate any other reasons why a work based | |
18 | on this file might be covered by the GNU General Public License. | |
19 | */ | |
b6fb82a2 RP |
20 | /** @file |
21 | * @brief implementation of tracing functionality. | |
22 | * | |
23 | * @copyright © Copyright 2008 by Intra2net AG | |
b6fb82a2 RP |
24 | * |
25 | * @note This module is not thread safe! | |
26 | * @todo make this module thread safe (only useful when we can use threads...) | |
27 | */ | |
28 | ||
29 | #include "tracefunc.hpp" | |
30 | ||
31 | #include <list> | |
32 | #include <vector> | |
33 | #include <sstream> | |
34 | ||
35 | ||
36 | namespace I2n | |
37 | { | |
38 | namespace Tracer | |
39 | { | |
40 | ||
41 | using Logger::GlobalLogger; | |
42 | ||
43 | ||
44 | namespace | |
45 | { | |
46 | ||
47 | typedef std::list< ScopeTracker* > ScopeTrackerList; | |
48 | ||
49 | ScopeTrackerList scope_tracker_list; | |
50 | ||
51 | ||
52 | std::vector< std::string > indents; | |
53 | ||
54 | ||
55 | /** | |
56 | * @brief ensures indent level string to exist up to the desired level. | |
57 | * @param level the desired indent level. | |
58 | */ | |
59 | void ensure_indent_level(int level) | |
60 | { | |
61 | while (indents.size() <= level) | |
62 | { | |
63 | indents.push_back( indents.back() + " " ); | |
64 | } | |
65 | } // eo ensure_indent_level(int) | |
66 | ||
67 | ||
68 | /** | |
69 | * @brief module initializer. | |
70 | */ | |
71 | class __Initializer | |
72 | { | |
73 | public: | |
74 | __Initializer() | |
75 | { | |
76 | // pre initialize indent strings: | |
77 | indents.clear(); | |
78 | indents.reserve(10); | |
79 | indents.push_back(""); | |
80 | for(int i=10; i-->0;) | |
81 | { | |
82 | indents.push_back( indents.back() + " " ); | |
83 | } | |
84 | } | |
85 | } __initializer; | |
86 | ||
87 | ||
88 | } // eo namespace <anonymous> | |
89 | ||
90 | ||
91 | /* | |
92 | ** implementation of ScopeTracker | |
93 | */ | |
94 | ||
95 | /** | |
96 | * @brief constructor. initializes object with a source location and emits a ENTER message. | |
97 | * @param loc the source location. | |
98 | * | |
99 | * the message is indented according to the current depth of nested ScopeTracker instances. | |
100 | */ | |
101 | ScopeTracker::ScopeTracker( | |
102 | const SourceLocation& loc) | |
103 | : Location(loc) | |
104 | , Depth(0) | |
105 | , FuncDepth(0) | |
106 | { | |
107 | if (!scope_tracker_list.empty()) | |
108 | { | |
109 | ScopeTracker* last_tracker= scope_tracker_list.back(); | |
110 | if (Location) | |
111 | { | |
112 | if (last_tracker->Location | |
113 | && last_tracker->Location.File == Location.File | |
114 | && last_tracker->Location.FunctionName == Location.FunctionName) | |
115 | { | |
116 | FuncDepth= last_tracker->FuncDepth+1; | |
117 | } | |
118 | } | |
119 | Depth= last_tracker->Depth + 1; | |
120 | } | |
121 | ensure_indent_level(Depth); | |
122 | scope_tracker_list.push_back(this); | |
123 | { | |
124 | std::ostringstream ostr; | |
125 | if (Location.FunctionName.empty()) | |
126 | { | |
127 | ostr << "<unknown> (global scope?)"; | |
128 | } | |
129 | else | |
130 | { | |
131 | ostr << Location.FunctionName; | |
132 | if (FuncDepth>0) | |
133 | { | |
134 | ostr << "#" << FuncDepth+1; | |
135 | } | |
136 | } | |
137 | Tag= ostr.str(); | |
138 | } | |
139 | // spit a message | |
140 | if (Logger::has_log_level(Logger::LogLevel::Debug)) | |
141 | { | |
142 | GlobalLogger.debug() << indents[Depth] << "ENTER " << Tag; | |
143 | } | |
144 | } // eo ScopeTrcaker::ScopeTracker(const SourceLocation&) | |
145 | ||
146 | ||
147 | /** | |
148 | * @brief destructor. emits a LEAVE message. | |
149 | * | |
150 | * | |
151 | */ | |
152 | ScopeTracker::~ScopeTracker() | |
153 | { | |
154 | // spit a message | |
155 | if (Logger::has_log_level(Logger::LogLevel::Debug)) | |
156 | { | |
157 | GlobalLogger.debug() << indents[Depth] << "LEAVE " << Tag; | |
158 | } | |
159 | if (scope_tracker_list.empty()) | |
160 | { | |
161 | return; | |
162 | } | |
163 | if (scope_tracker_list.back() == this) | |
164 | { | |
165 | scope_tracker_list.pop_back(); | |
166 | } | |
167 | else | |
168 | { | |
169 | // oh hell, this should never be the case! | |
170 | //TODO | |
171 | GlobalLogger.error() << "inconsistency detected in scope tracker"; | |
172 | } | |
173 | } // eo ScopeTracker::~ScopeTracker() | |
174 | ||
175 | ||
176 | ||
177 | ||
178 | } // eo namespace Tracer | |
179 | } // eo namespace I2n |