debugger:
[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     //check if breakpoint does not exist
138
139     bool add = true;
140     for (const auto b : breakpoints)
141     {
142         if (b->getFunctioName() != bp->getFunctioName())
143         {
144             continue;
145         }
146
147         if (b->getMacroLine() != bp->getMacroLine())
148         {
149             continue;
150         }
151
152         if (b->getCondition() != bp->getCondition())
153         {
154             continue;
155         }
156
157         //same breakpoint, cancel add
158         add = false;
159     }
160
161     if (add)
162     {
163         breakpoints.push_back(bp);
164         sendUpdate();
165     }
166 }
167
168 void DebuggerMagager::removeBreakPoint(int _iBreakPoint)
169 {
170     if (_iBreakPoint >= 0 && _iBreakPoint <= breakpoints.size())
171     {
172         Breakpoints::iterator it = breakpoints.begin() + _iBreakPoint;
173         delete *it;
174         breakpoints.erase(it);
175         sendUpdate();
176     }
177 }
178
179 void DebuggerMagager::removeAllBreakPoints()
180 {
181     Breakpoints::iterator it = breakpoints.begin();
182     for (; it != breakpoints.end(); ++it)
183     {
184         delete *it;
185     }
186
187     breakpoints.clear();
188     sendUpdate();
189 }
190
191 void DebuggerMagager::disableBreakPoint(int _iBreakPoint)
192 {
193     if (_iBreakPoint >= 0 && _iBreakPoint <= breakpoints.size())
194     {
195         breakpoints[_iBreakPoint]->setDisable();
196         sendUpdate();
197     }
198 }
199
200 void DebuggerMagager::disableAllBreakPoints()
201 {
202     for (const auto& it : breakpoints)
203     {
204         it->setDisable();
205     }
206
207     sendUpdate();
208 }
209
210 void DebuggerMagager::enableBreakPoint(int _iBreakPoint)
211 {
212     if (_iBreakPoint >= 0 && _iBreakPoint <= breakpoints.size())
213     {
214         breakpoints[_iBreakPoint]->setEnable();
215     }
216 }
217
218 void DebuggerMagager::enableAllBreakPoints()
219 {
220     for (const auto& it : breakpoints)
221     {
222         it->setEnable();
223     }
224
225     sendUpdate();
226 }
227
228 bool DebuggerMagager::isEnableBreakPoint(int _iBreakPoint)
229 {
230     if (_iBreakPoint >= 0 && _iBreakPoint <= breakpoints.size())
231     {
232         return breakpoints[_iBreakPoint]->isEnable();
233     }
234
235     return false;
236 }
237
238 Breakpoint* DebuggerMagager::getBreakPoint(int _iBreakPoint)
239 {
240     if (_iBreakPoint >= 0 && _iBreakPoint < breakpoints.size())
241     {
242         return breakpoints[_iBreakPoint];
243     }
244
245     return NULL;
246 }
247
248 int DebuggerMagager::getBreakPointCount()
249 {
250     return (int)breakpoints.size();
251 }
252
253 Breakpoints& DebuggerMagager::getAllBreakPoint()
254 {
255     return breakpoints;
256 }
257
258 void DebuggerMagager::resume() //resume execution
259 {
260     if (ConfigVariable::getPauseLevel() != 0)
261     {
262         ConfigVariable::DecreasePauseLevel();
263         //inform debuggers
264         sendResume();
265     }
266
267 }
268
269 void DebuggerMagager::abort() //abort execution
270 {
271     if (ConfigVariable::getPauseLevel() != 0)
272     {
273         //inform debuggers
274         sendAbort();
275
276         throw ast::InternalAbort();
277     }
278 }
279
280 void DebuggerMagager::internal_stop()
281 {
282     interrupted = true;
283
284     ConfigVariable::IncreasePauseLevel();
285
286     // unlock console thread to display prompt again
287     ThreadManagement::SendConsoleExecDoneSignal();
288
289     //return to console so change mode to 2
290     int iOldMode = ConfigVariable::getPromptMode();
291     ConfigVariable::setPromptMode(2);
292
293     int iPauseLevel = ConfigVariable::getPauseLevel();
294     while (ConfigVariable::getPauseLevel() == iPauseLevel)
295     {
296         ThreadManagement::SendAwakeRunnerSignal();
297         ThreadManagement::WaitForRunMeSignal();
298         try
299         {
300             StaticRunner_launch();
301         }
302         catch (const ast::InternalError& ie)
303         {
304             //return from console so change mode to initial
305             ConfigVariable::setPromptMode(iOldMode);
306             //clean current seqexp
307             clearExp();
308             interrupted = false;
309
310             throw ie;
311         }
312         catch (const ast::InternalAbort& ia)
313         {
314             //return from console so change mode to initial
315             ConfigVariable::setPromptMode(iOldMode);
316             //clean current seqexp
317             clearExp();
318             interrupted = false;
319
320             throw ia;
321         }
322     }
323
324     //return from console so change mode to initial
325     ConfigVariable::setPromptMode(iOldMode);
326     //clean current seqexp
327     interrupted = false;
328 }
329
330 void DebuggerMagager::stop(const ast::Exp* pExp, int index)
331 {
332     //send stop information to all debuggers
333     setExp(pExp);
334     sendStop(index);
335     internal_stop();
336     clearExp();
337 }
338 void DebuggerMagager::errorInFile(const std::wstring filename, const ast::Exp* pExp)
339 {
340     setExp(pExp);
341     sendErrorInFile(filename);
342     internal_stop();
343     clearExp();
344 }
345 void DebuggerMagager::errorInScript(const std::wstring funcname, const ast::Exp* pExp)
346 {
347     setExp(pExp);
348     sendErrorInScript(funcname);
349     internal_stop();
350     clearExp();
351 }
352
353 }