9136a895d00d6d3152322cf8241235f28f6ea397
[scilab.git] / scilab / modules / ast / src / cpp / ast / debugmanager.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include <memory>
14
15 #include "debugmanager.hxx"
16 #include "configvariable.hxx"
17 #include "threadmanagement.hxx"
18 #include "runner.hxx"
19
20 #include "threadId.hxx"
21
22 extern "C"
23 {
24 #include "Thread_Wrapper.h"
25 }
26
27 namespace debugger
28 {
29 std::unique_ptr<DebuggerMagager> DebuggerMagager::me(nullptr);
30
31 //singleton
32 DebuggerMagager* DebuggerMagager::getInstance()
33 {
34     if (me.get() == nullptr)
35     {
36         me.reset(new DebuggerMagager());
37     }
38
39     return me.get();
40 }
41
42 void DebuggerMagager::addDebugger(AbstractDebugger* _debug)
43 {
44     debuggers.push_back(_debug);
45 }
46
47 void DebuggerMagager::removeDebugger(int _iDebugger)
48 {
49     if (_iDebugger >= 0 && _iDebugger <= debuggers.size())
50     {
51         debuggers.erase(debuggers.begin() + _iDebugger);
52     }
53 }
54
55 AbstractDebugger* DebuggerMagager::getDebugger(int _iDebugger)
56 {
57     if (_iDebugger >= 0 && _iDebugger <= debuggers.size())
58     {
59         return debuggers[_iDebugger];
60     }
61
62     return NULL;
63 }
64
65 int DebuggerMagager::getDebuggerCount()
66 {
67     return (int)debuggers.size();
68 }
69
70 Debuggers& DebuggerMagager::getAllDebugger()
71 {
72     return debuggers;
73 }
74
75 void DebuggerMagager::sendStop(int index)
76 {
77     currentBreakPoint = index;
78     for (const auto& it : debuggers)
79     {
80         it->onStop(index);
81     }
82 }
83
84 void DebuggerMagager::sendResume()
85 {
86     currentBreakPoint = -1;
87     for (const auto& it : debuggers)
88     {
89         it->onResume();
90     }
91 }
92
93 void DebuggerMagager::sendAbort()
94 {
95     currentBreakPoint = -1;
96     for (const auto& it : debuggers)
97     {
98         it->onAbort();
99     }
100 }
101
102 void DebuggerMagager::sendErrorInFile(const std::wstring& filename) const
103 {
104     for (const auto& it : debuggers)
105     {
106         it->onErrorInFile(filename);
107     }
108 }
109
110 void DebuggerMagager::sendErrorInScript(const std::wstring& funcname) const
111 {
112     for (const auto& it : debuggers)
113     {
114         it->onErrorInScript(funcname);
115     }
116 }
117
118 void DebuggerMagager::sendQuit()
119 {
120     currentBreakPoint = -1;
121     for (const auto& it : debuggers)
122     {
123         it->onQuit();
124     }
125 }
126
127 void DebuggerMagager::sendUpdate() const
128 {
129     for (const auto& it : debuggers)
130     {
131         it->updateBreakpoints();
132     }
133 }
134
135 void DebuggerMagager::addBreakPoint(Breakpoint* bp)
136 {
137     breakpoints.push_back(bp);
138     sendUpdate();
139 }
140
141 void DebuggerMagager::removeBreakPoint(int _iBreakPoint)
142 {
143     if (_iBreakPoint >= 0 && _iBreakPoint <= breakpoints.size())
144     {
145         Breakpoints::iterator it = breakpoints.begin() + _iBreakPoint;
146         delete *it;
147         breakpoints.erase(it);
148         sendUpdate();
149     }
150 }
151
152 void DebuggerMagager::removeAllBreakPoints()
153 {
154     Breakpoints::iterator it = breakpoints.begin();
155     for (; it != breakpoints.end(); ++it)
156     {
157         delete *it;
158     }
159
160     breakpoints.clear();
161     sendUpdate();
162 }
163
164 void DebuggerMagager::disableBreakPoint(int _iBreakPoint)
165 {
166     if (_iBreakPoint >= 0 && _iBreakPoint <= breakpoints.size())
167     {
168         breakpoints[_iBreakPoint]->setDisable();
169         sendUpdate();
170     }
171 }
172
173 void DebuggerMagager::disableAllBreakPoints()
174 {
175     for (const auto& it : breakpoints)
176     {
177         it->setDisable();
178     }
179
180     sendUpdate();
181 }
182
183 void DebuggerMagager::enableBreakPoint(int _iBreakPoint)
184 {
185     if (_iBreakPoint >= 0 && _iBreakPoint <= breakpoints.size())
186     {
187         breakpoints[_iBreakPoint]->setEnable();
188     }
189 }
190
191 void DebuggerMagager::enableAllBreakPoints()
192 {
193     for (const auto& it : breakpoints)
194     {
195         it->setEnable();
196     }
197
198     sendUpdate();
199 }
200
201 bool DebuggerMagager::isEnableBreakPoint(int _iBreakPoint)
202 {
203     if (_iBreakPoint >= 0 && _iBreakPoint <= breakpoints.size())
204     {
205         return breakpoints[_iBreakPoint]->isEnable();
206     }
207
208     return false;
209 }
210
211 Breakpoint* DebuggerMagager::getBreakPoint(int _iBreakPoint)
212 {
213     if (_iBreakPoint >= 0 && _iBreakPoint < breakpoints.size())
214     {
215         return breakpoints[_iBreakPoint];
216     }
217
218     return NULL;
219 }
220
221 int DebuggerMagager::getBreakPointCount()
222 {
223     return (int)breakpoints.size();
224 }
225
226 Breakpoints& DebuggerMagager::getAllBreakPoint()
227 {
228     return breakpoints;
229 }
230
231 void DebuggerMagager::resume() //resume execution
232 {
233     if (ConfigVariable::getPauseLevel() != 0)
234     {
235         ConfigVariable::DecreasePauseLevel();
236         //inform debuggers
237         sendResume();
238     }
239
240 }
241
242 void DebuggerMagager::abort() //abort execution
243 {
244     if (ConfigVariable::getPauseLevel() != 0)
245     {
246         //inform debuggers
247         sendAbort();
248
249         throw ast::InternalAbort();
250     }
251 }
252
253 void DebuggerMagager::internal_stop()
254 {
255     interrupted = true;
256
257     ConfigVariable::IncreasePauseLevel();
258
259     // unlock console thread to display prompt again
260     ThreadManagement::SendConsoleExecDoneSignal();
261
262     //return to console so change mode to 2
263     int iOldMode = ConfigVariable::getPromptMode();
264     ConfigVariable::setPromptMode(2);
265
266     int iPauseLevel = ConfigVariable::getPauseLevel();
267     while (ConfigVariable::getPauseLevel() == iPauseLevel)
268     {
269         ThreadManagement::SendAwakeRunnerSignal();
270         ThreadManagement::WaitForRunMeSignal();
271         try
272         {
273             StaticRunner_launch();
274         }
275         catch (const ast::InternalError& ie)
276         {
277             //return from console so change mode to initial
278             ConfigVariable::setPromptMode(iOldMode);
279             //clean current seqexp
280             clearExp();
281             interrupted = false;
282
283             throw ie;
284         }
285         catch (const ast::InternalAbort& ia)
286         {
287             //return from console so change mode to initial
288             ConfigVariable::setPromptMode(iOldMode);
289             //clean current seqexp
290             clearExp();
291             interrupted = false;
292
293             throw ia;
294         }
295     }
296
297     //return from console so change mode to initial
298     ConfigVariable::setPromptMode(iOldMode);
299     //clean current seqexp
300     interrupted = false;
301 }
302
303 void DebuggerMagager::stop(const ast::Exp* pExp, int index)
304 {
305     //send stop information to all debuggers
306     setExp(pExp);
307     sendStop(index);
308     internal_stop();
309     clearExp();
310 }
311 void DebuggerMagager::errorInFile(const std::wstring filename, const ast::Exp* pExp)
312 {
313     setExp(pExp);
314     sendErrorInFile(filename);
315     internal_stop();
316     clearExp();
317 }
318 void DebuggerMagager::errorInScript(const std::wstring funcname, const ast::Exp* pExp)
319 {
320     setExp(pExp);
321     sendErrorInScript(funcname);
322     internal_stop();
323     clearExp();
324 }
325
326 }