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