2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
18 #include "debugmanager.hxx"
19 #include "threadmanagement.hxx"
20 #include "execvisitor.hxx"
21 #include "printvisitor.hxx"
24 #include "threadId.hxx"
28 #include "Thread_Wrapper.h"
29 #include "storeCommand.h"
31 #include "FileExist.h"
36 std::unique_ptr<DebuggerManager> DebuggerManager::me(nullptr);
39 DebuggerManager* DebuggerManager::getInstance()
41 if (me.get() == nullptr)
43 me.reset(new DebuggerManager());
49 void DebuggerManager::addDebugger(const std::string& _name, AbstractDebugger* _debug)
51 debuggers[_name] = _debug;
54 void DebuggerManager::removeDebugger(const std::string& _name)
56 if(getDebugger(_name))
58 debuggers.erase(_name);
62 AbstractDebugger* DebuggerManager::getDebugger(const std::string& _name)
64 const auto& d = debuggers.find(_name);
65 if(d != debuggers.end())
67 return debuggers[_name];
73 int DebuggerManager::getDebuggerCount()
75 return (int)debuggers.size();
78 Debuggers& DebuggerManager::getAllDebugger()
83 void DebuggerManager::sendStop(int index)
85 currentBreakPoint = index;
86 for (const auto& it : debuggers)
88 it.second->onStop(index);
92 void DebuggerManager::sendExecution()
94 for (const auto& it : debuggers)
96 it.second->onExecution();
100 void DebuggerManager::sendExecutionReleased()
102 for (const auto& it : debuggers)
104 it.second->onExecutionReleased();
108 void DebuggerManager::sendPrint(const std::string& variable)
110 for (const auto& it : debuggers)
112 it.second->onPrint(variable);
116 void DebuggerManager::sendShow(int bp)
118 for (const auto& it : debuggers)
120 it.second->onShow(bp);
124 void DebuggerManager::sendResume()
126 currentBreakPoint = -1;
127 for (const auto& it : debuggers)
129 it.second->onResume();
133 void DebuggerManager::sendAbort()
135 currentBreakPoint = -1;
136 for (const auto& it : debuggers)
138 it.second->onAbort();
142 void DebuggerManager::sendErrorInFile(const std::wstring& filename) const
144 for (const auto& it : debuggers)
146 it.second->onErrorInFile(filename);
150 void DebuggerManager::sendErrorInScript(const std::wstring& funcname) const
152 for (const auto& it : debuggers)
154 it.second->onErrorInScript(funcname);
158 void DebuggerManager::sendQuit()
160 currentBreakPoint = -1;
161 for (const auto& it : debuggers)
167 void DebuggerManager::sendUpdate() const
169 for (const auto& it : debuggers)
171 it.second->updateBreakpoints();
175 void DebuggerManager::setAllBreakPoints(Breakpoints& _bps)
177 // remove existing breakpoints
178 for (auto bp : breakpoints)
184 // set new breakpoints
185 breakpoints.swap(_bps);
189 Breakpoints::iterator DebuggerManager::findBreakPoint(Breakpoint* bp)
191 Breakpoints::iterator found = std::find_if(breakpoints.begin(), breakpoints.end(),
193 bool isMacro = b->getFunctioName() != "" &&
194 b->getFunctioName() == bp->getFunctioName() &&
195 b->getMacroLine() == bp->getMacroLine();
197 bool isFile = b->getFileName() != "" &&
198 b->getFileName() == bp->getFileName() &&
199 b->getFileLine() == bp->getFileLine();
201 return (isMacro || isFile);
207 bool DebuggerManager::addBreakPoint(Breakpoint* bp)
209 //check if breakpoint does not exist
210 Breakpoints::iterator iter = findBreakPoint(bp);
211 if(iter == breakpoints.end())
213 breakpoints.push_back(bp);
221 bool DebuggerManager::updateBreakPoint(Breakpoint* bp)
223 Breakpoints::iterator iter = findBreakPoint(bp);
224 if(iter != breakpoints.end())
226 std::swap(*iter, bp);
234 bool DebuggerManager::removeBreakPoint(Breakpoint* bp)
236 Breakpoints::iterator iter = findBreakPoint(bp);
237 if(iter != breakpoints.end())
240 breakpoints.erase(iter);
247 void DebuggerManager::removeBreakPoint(int _iBreakPoint)
249 if (_iBreakPoint >= 0 && _iBreakPoint <= (int)breakpoints.size())
251 Breakpoints::iterator it = breakpoints.begin() + _iBreakPoint;
253 breakpoints.erase(it);
258 void DebuggerManager::removeAllBreakPoints()
260 Breakpoints::iterator it = breakpoints.begin();
261 for (; it != breakpoints.end(); ++it)
270 void DebuggerManager::disableBreakPoint(int _iBreakPoint)
272 if (_iBreakPoint >= 0 && _iBreakPoint <= (int)breakpoints.size())
274 breakpoints[_iBreakPoint]->setDisable();
279 void DebuggerManager::disableAllBreakPoints()
281 for (const auto& it : breakpoints)
289 void DebuggerManager::enableBreakPoint(int _iBreakPoint)
291 if (_iBreakPoint >= 0 && _iBreakPoint <= (int)breakpoints.size())
293 breakpoints[_iBreakPoint]->setEnable();
298 void DebuggerManager::enableAllBreakPoints()
300 for (const auto& it : breakpoints)
308 bool DebuggerManager::isEnableBreakPoint(int _iBreakPoint)
310 if (_iBreakPoint >= 0 && _iBreakPoint <= (int)breakpoints.size())
312 return breakpoints[_iBreakPoint]->isEnable();
318 Breakpoint* DebuggerManager::getBreakPoint(int _iBreakPoint)
320 if (_iBreakPoint >= 0 && _iBreakPoint < (int)breakpoints.size())
322 return breakpoints[_iBreakPoint];
328 int DebuggerManager::getBreakPointCount()
330 return (int)breakpoints.size();
333 Breakpoints& DebuggerManager::getAllBreakPoint()
338 void DebuggerManager::generateCallStack()
342 std::wostringstream ostr;
343 ast::PrintVisitor pp(ostr, true, true, true);
344 getExp()->accept(pp);
345 char* tmp = wide_string_to_UTF8(ostr.str().data());
350 const std::vector<ConfigVariable::WhereEntry>& where = ConfigVariable::getWhere();
351 auto it_name = where.rbegin();
356 tmp = wide_string_to_UTF8(it_name->call->getName().data());
357 row.functionName = tmp;
360 row.functionLine = -1;
361 if(it_name->call->getFirstLine())
363 row.functionLine = getExp()->getLocation().first_line - it_name->call->getFirstLine();
366 if(callstackAddFile(&row, *it_name->m_file_name))
368 row.fileLine = getExp()->getLocation().first_line;
371 row.scope = symbol::Context::getInstance()->getScopeLevel();
377 for (auto it_line = where.rbegin(); it_name != where.rend(); it_name++, it_line++)
380 tmp = wide_string_to_UTF8(it_name->call->getName().data());
381 row.functionName = tmp;
383 row.functionLine = it_line->m_line - 1;
384 if(it_name->m_file_name && callstackAddFile(&row, *it_name->m_file_name))
386 row.fileLine = it_line->m_line;
387 row.functionLine = -1;
388 if(it_name->call->getFirstLine())
390 row.fileLine = it_name->call->getFirstLine() + it_line->m_line - 1;
391 row.functionLine = it_line->m_line - 1;
395 row.scope = it_line->m_scope_lvl;
399 callstack.stack = cs;
402 bool DebuggerManager::callstackAddFile(StackRow* _row, const std::wstring& _fileName)
404 _row->hasFile = false;
405 if(_fileName.length())
407 std::string pstrFileName = scilab::UTF8::toUTF8(_fileName);
408 _row->hasFile = true;
409 // replace .bin by .sci
410 size_t pos = pstrFileName.rfind(".bin");
411 if(pos != std::string::npos)
413 pstrFileName.replace(pos, 4, ".sci");
414 // do not add the file in the callstack if the associeted .sci is not available
415 if (FileExist(pstrFileName.data()) == false)
417 _row->hasFile = false;
423 _row->fileName = pstrFileName;
427 return _row->hasFile;
430 void DebuggerManager::print(const std::string& variable)
436 void DebuggerManager::show(int bp)
442 char* DebuggerManager::execute(const std::string& command)
444 char* error = checkCommand(command.data());
450 // reset abort flag befor a new exection
455 // execute command and wait
456 StoreDebuggerCommand(command.data());
457 // send execution finished and update debugger informations
458 internal_execution_released();
463 void DebuggerManager::resume() //resume execution
465 if (ConfigVariable::getPauseLevel() != 0)
470 ConfigVariable::DecreasePauseLevel();
474 // send "SendRunMeSignal" to unlock execution then wait
475 ThreadManagement::WaitForDebuggerExecDoneSignal(true);
477 // send execution finished and update debugger informations
478 internal_execution_released();
482 void DebuggerManager::requestPause() //ask for pause
484 // pause on execution only if a command is running
485 if(interrupted == false) {
486 request_pause = true;
490 bool DebuggerManager::isPauseRequested() //pause execution
492 return request_pause;
495 void DebuggerManager::resetPauseRequest() //pause execution
497 request_pause = false;
500 void DebuggerManager::abort() //abort execution
505 // this state is check by the debuggerVisitor to do abort in the main thread
508 // reset requested pause in case we abort before beeing in pause
514 if (ConfigVariable::getPauseLevel() != 0)
516 ConfigVariable::DecreasePauseLevel();
519 // reset lasterror information
520 ConfigVariable::clearLastError();
522 ConfigVariable::resetError();
526 ThreadManagement::WaitForDebuggerExecDoneSignal(true);
528 internal_execution_released();
532 void DebuggerManager::internal_execution_released()
534 // send execution finished
535 sendExecutionReleased();
538 void DebuggerManager::internal_stop()
542 // release the debugger thread
543 ThreadManagement::SendDebuggerExecDoneSignal();
549 catch (const ast::InternalAbort& ia)
551 // can append when aborting an execution
552 // which is running inside a pause
560 void DebuggerManager::stop(const ast::Exp* pExp, int index)
562 //send stop information to all debuggers
565 // because stop is used only in the debuggervisitor the pause
566 // will be executed in the main thread (where is executed the command)
571 void DebuggerManager::errorInFile(const std::wstring filename, const ast::Exp* pExp)
574 sendErrorInFile(filename);
578 void DebuggerManager::errorInScript(const std::wstring funcname, const ast::Exp* pExp)
581 sendErrorInScript(funcname);