diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 5537b1ce..b52481a9 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -121,12 +121,14 @@ SOURCES += \ compiler/projectcompiler.cpp \ compiler/runner.cpp \ customfileiconprovider.cpp \ - gdbmiresultparser.cpp \ compiler/compiler.cpp \ compiler/compilermanager.cpp \ compiler/executablerunner.cpp \ compiler/filecompiler.cpp \ compiler/stdincompiler.cpp \ + debugger/debugger.cpp \ + debugger/gdbmidebugger.cpp \ + debugger/gdbmiresultparser.cpp \ cpprefacter.cpp \ parser/cppparser.cpp \ parser/cpppreprocessor.cpp \ @@ -179,7 +181,6 @@ SOURCES += \ widgets/codecompletionlistview.cpp \ widgets/codecompletionpopup.cpp \ widgets/cpudialog.cpp \ - debugger/debugger.cpp \ editor.cpp \ editorlist.cpp \ iconsmanager.cpp \ @@ -255,9 +256,11 @@ HEADERS += \ compiler/projectcompiler.h \ compiler/runner.h \ compiler/stdincompiler.h \ + debugger/debugger.h \ + debugger/gdbmidebugger.h \ + debugger/gdbmiresultparser.h \ cpprefacter.h \ customfileiconprovider.h \ - gdbmiresultparser.h \ parser/cppparser.h \ parser/cpppreprocessor.h \ parser/cpptokenizer.h \ @@ -309,7 +312,6 @@ HEADERS += \ widgets/codecompletionlistview.h \ widgets/codecompletionpopup.h \ widgets/cpudialog.h \ - debugger/debugger.h \ editor.h \ editorlist.h \ iconsmanager.h \ diff --git a/RedPandaIDE/debugger/debugger.cpp b/RedPandaIDE/debugger/debugger.cpp index 53ebe45f..d6342d62 100644 --- a/RedPandaIDE/debugger/debugger.cpp +++ b/RedPandaIDE/debugger/debugger.cpp @@ -52,7 +52,7 @@ Debugger::Debugger(QObject *parent) : QObject(parent), connect(mWatchModel.get(), &WatchModel::setWatchVarValue, this, &Debugger::setWatchVarValue); mExecuting = false; - mReader = nullptr; + mClient = nullptr; mTarget = nullptr; mCommandChanged = false; mLeftPageIndexBackup = -1; @@ -158,56 +158,56 @@ bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStrin mTarget->waitStart(); } //delete when thread finished - mReader = new DebugReader(this); - mReader->addBinDirs(binDirs); - mReader->addBinDir(pSettings->dirs().appDir()); - mReader->setDebuggerPath(debuggerPath); - connect(mReader, &QThread::finished,this,&Debugger::cleanUpReader); - connect(mReader, &QThread::finished,mMemoryModel.get(),&MemoryModel::reset); - connect(mReader, &DebugReader::parseFinished,this,&Debugger::syncFinishedParsing,Qt::BlockingQueuedConnection); - connect(mReader, &DebugReader::changeDebugConsoleLastLine,this,&Debugger::onChangeDebugConsoleLastline); - connect(mReader, &DebugReader::cmdStarted,pMainWindow, &MainWindow::disableDebugActions); - connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); - connect(mReader, &DebugReader::inferiorStopped, pMainWindow, &MainWindow::enableDebugActions); + mClient = new DebuggerClient(this); + mClient->addBinDirs(binDirs); + mClient->addBinDir(pSettings->dirs().appDir()); + mClient->setDebuggerPath(debuggerPath); + connect(mClient, &QThread::finished,this,&Debugger::cleanUpReader); + connect(mClient, &QThread::finished,mMemoryModel.get(),&MemoryModel::reset); + connect(mClient, &DebuggerClient::parseFinished,this,&Debugger::syncFinishedParsing,Qt::BlockingQueuedConnection); + connect(mClient, &DebuggerClient::changeDebugConsoleLastLine,this,&Debugger::onChangeDebugConsoleLastline); + connect(mClient, &DebuggerClient::cmdStarted,pMainWindow, &MainWindow::disableDebugActions); + connect(mClient, &DebuggerClient::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); + connect(mClient, &DebuggerClient::inferiorStopped, pMainWindow, &MainWindow::enableDebugActions); - connect(mReader, &DebugReader::breakpointInfoGetted, mBreakpointModel.get(), + connect(mClient, &DebuggerClient::breakpointInfoGetted, mBreakpointModel.get(), &BreakpointModel::updateBreakpointNumber); - connect(mReader, &DebugReader::localsUpdated, pMainWindow, + connect(mClient, &DebuggerClient::localsUpdated, pMainWindow, &MainWindow::onLocalsReady); - connect(mReader, &DebugReader::memoryUpdated,this, + connect(mClient, &DebuggerClient::memoryUpdated,this, &Debugger::updateMemory); - connect(mReader, &DebugReader::evalUpdated,this, + connect(mClient, &DebuggerClient::evalUpdated,this, &Debugger::updateEval); - connect(mReader, &DebugReader::disassemblyUpdate,this, + connect(mClient, &DebuggerClient::disassemblyUpdate,this, &Debugger::updateDisassembly); - connect(mReader, &DebugReader::registerNamesUpdated, this, + connect(mClient, &DebuggerClient::registerNamesUpdated, this, &Debugger::updateRegisterNames); - connect(mReader, &DebugReader::registerValuesUpdated, this, + connect(mClient, &DebuggerClient::registerValuesUpdated, this, &Debugger::updateRegisterValues); - connect(mReader, &DebugReader::varCreated,mWatchModel.get(), + connect(mClient, &DebuggerClient::varCreated,mWatchModel.get(), &WatchModel::updateVarInfo); - connect(mReader, &DebugReader::prepareVarChildren,mWatchModel.get(), + connect(mClient, &DebuggerClient::prepareVarChildren,mWatchModel.get(), &WatchModel::prepareVarChildren); - connect(mReader, &DebugReader::addVarChild,mWatchModel.get(), + connect(mClient, &DebuggerClient::addVarChild,mWatchModel.get(), &WatchModel::addVarChild); - connect(mReader, &DebugReader::varValueUpdated,mWatchModel.get(), + connect(mClient, &DebuggerClient::varValueUpdated,mWatchModel.get(), &WatchModel::updateVarValue); - connect(mReader, &DebugReader::varsValueUpdated,mWatchModel.get(), + connect(mClient, &DebuggerClient::varsValueUpdated,mWatchModel.get(), &WatchModel::updateAllHasMoreVars); - connect(mReader, &DebugReader::inferiorContinued,pMainWindow, + connect(mClient, &DebuggerClient::inferiorContinued,pMainWindow, &MainWindow::removeActiveBreakpoints); - connect(mReader, &DebugReader::inferiorStopped,pMainWindow, + connect(mClient, &DebuggerClient::inferiorStopped,pMainWindow, &MainWindow::setActiveBreakpoint); - connect(mReader, &DebugReader::watchpointHitted,pMainWindow, + connect(mClient, &DebuggerClient::watchpointHitted,pMainWindow, &MainWindow::onWatchpointHitted); - connect(mReader, &DebugReader::errorNoSymbolTable,pMainWindow, + connect(mClient, &DebuggerClient::errorNoSymbolTable,pMainWindow, &MainWindow::stopDebugForNoSymbolTable); - connect(mReader, &DebugReader::inferiorStopped,this, + connect(mClient, &DebuggerClient::inferiorStopped,this, &Debugger::refreshAll); - mReader->registerInferiorStoppedCommand("-stack-list-frames",""); - mReader->start(); - mReader->waitStart(); + mClient->registerInferiorStoppedCommand("-stack-list-frames",""); + mClient->start(); + mClient->waitStart(); pMainWindow->updateAppTitle(); @@ -220,7 +220,7 @@ void Debugger::stop() { mTarget->stopDebug(); mTarget = nullptr; } - mReader->stopDebug(); + mClient->stopDebug(); } mCurrentSourceFile=""; } @@ -230,8 +230,8 @@ void Debugger::cleanUpReader() mExecuting = false; //stop debugger - mReader->deleteLater(); - mReader=nullptr; + mClient->deleteLater(); + mClient=nullptr; if (pMainWindow->cpuDialog()!=nullptr) { pMainWindow->cpuDialog()->close(); @@ -290,23 +290,23 @@ std::shared_ptr Debugger::watchModel() const void Debugger::sendCommand(const QString &command, const QString ¶ms, DebugCommandSource source) { - if (mExecuting && mReader) { - mReader->postCommand(command,params,source); + if (mExecuting && mClient) { + mClient->postCommand(command,params,source); } } bool Debugger::commandRunning() { - if (mExecuting && mReader) { - return mReader->commandRunning(); + if (mExecuting && mClient) { + return mClient->commandRunning(); } return false; } bool Debugger::inferiorRunning() { - if (mExecuting && mReader) { - return mReader->inferiorRunning(); + if (mExecuting && mClient) { + return mClient->inferiorRunning(); } return false; } @@ -876,7 +876,7 @@ void Debugger::syncFinishedParsing() bool spawnedcpuform = false; // GDB determined that the source code is more recent than the executable. Ask the user if he wants to rebuild. - if (mReader->receivedSFWarning()) { + if (mClient->receivedSFWarning()) { if (QMessageBox::question(pMainWindow, tr("Compile"), tr("Source file is more recent than executable.")+"

" + tr("Recompile?"), @@ -892,20 +892,20 @@ void Debugger::syncFinishedParsing() // show command output if (pSettings->debugger().enableDebugConsole() ) { if (pSettings->debugger().showDetailLog()) { - for (const QString& line:mReader->fullOutput()) { + for (const QString& line:mClient->fullOutput()) { pMainWindow->addDebugOutput(line); } } else { - if (mReader->currentCmd() && mReader->currentCmd()->command == "disas") { + if (mClient->currentCmd() && mClient->currentCmd()->command == "disas") { } else { - for (const QString& line:mReader->consoleOutput()) { + for (const QString& line:mClient->consoleOutput()) { pMainWindow->addDebugOutput(line); } if ( - (mReader->currentCmd() - && mReader->currentCmd()->source== DebugCommandSource::Console) - || !mReader->consoleOutput().isEmpty() ) { + (mClient->currentCmd() + && mClient->currentCmd()->source== DebugCommandSource::Console) + || !mClient->consoleOutput().isEmpty() ) { pMainWindow->addDebugOutput("(gdb)"); } } @@ -913,20 +913,20 @@ void Debugger::syncFinishedParsing() } // The program to debug has stopped. Stop the debugger - if (mReader->processExited()) { + if (mClient->processExited()) { stop(); return; } - if (mReader->signalReceived() - && mReader->signalName()!="SIGINT" - && mReader->signalName()!="SIGTRAP") { + if (mClient->signalReceived() + && mClient->signalName()!="SIGINT" + && mClient->signalName()!="SIGTRAP") { SignalMessageDialog dialog(pMainWindow); dialog.setOpenCPUInfo(pSettings->debugger().openCPUInfoWhenSignaled()); dialog.setMessage( - tr("Signal \"%1\" Received: ").arg(mReader->signalName()) + tr("Signal \"%1\" Received: ").arg(mClient->signalName()) + "
" - + mReader->signalMeaning()); + + mClient->signalMeaning()); int result = dialog.exec(); if (result == QDialog::Accepted && dialog.openCPUInfo()) { pMainWindow->showCPUInfoDialog(); @@ -934,7 +934,7 @@ void Debugger::syncFinishedParsing() } // CPU form updates itself when spawned, don't update twice! - if ((mReader->updateCPUInfo() && !spawnedcpuform) && (pMainWindow->cpuDialog()!=nullptr)) { + if ((mClient->updateCPUInfo() && !spawnedcpuform) && (pMainWindow->cpuDialog()!=nullptr)) { pMainWindow->cpuDialog()->updateInfo(); } } @@ -990,7 +990,7 @@ bool Debugger::executing() const return mExecuting; } -DebugReader::DebugReader(Debugger* debugger, QObject *parent) : QThread(parent), +DebuggerClient::DebuggerClient(Debugger* debugger, QObject *parent) : QThread(parent), #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) mCmdQueueMutex(), #else @@ -1004,36 +1004,13 @@ DebugReader::DebugReader(Debugger* debugger, QObject *parent) : QThread(parent), mAsyncUpdated = false; } -void DebugReader::postCommand(const QString &Command, const QString &Params, - DebugCommandSource Source) -{ - QMutexLocker locker(&mCmdQueueMutex); - PDebugCommand pCmd = std::make_shared(); - pCmd->command = Command; - pCmd->params = Params; - pCmd->source = Source; - mCmdQueue.enqueue(pCmd); -// if (!mCmdRunning) - // runNextCmd(); -} - -void DebugReader::registerInferiorStoppedCommand(const QString &Command, const QString &Params) -{ - QMutexLocker locker(&mCmdQueueMutex); - PDebugCommand pCmd = std::make_shared(); - pCmd->command = Command; - pCmd->params = Params; - pCmd->source = DebugCommandSource::Other; - mInferiorStoppedHookCommands.append(pCmd); -} - -void DebugReader::clearCmdQueue() +void DebuggerClient::clearCmdQueue() { QMutexLocker locker(&mCmdQueueMutex); mCmdQueue.clear(); } -void DebugReader::processConsoleOutput(const QByteArray& line) +void DebuggerClient::processConsoleOutput(const QByteArray& line) { if (line.length()>3 && line.startsWith("~\"") && line.endsWith("\"")) { QByteArray s=line.mid(2,line.length()-3); @@ -1119,7 +1096,7 @@ void DebugReader::processConsoleOutput(const QByteArray& line) } } -void DebugReader::processLogOutput(const QByteArray &line) +void DebuggerClient::processLogOutput(const QByteArray &line) { if (mDebugger->debugInfosUsingUTF8() && line.endsWith(": No such file or directory.\n\"")) { QByteArray newLine = line; @@ -1133,7 +1110,7 @@ void DebugReader::processLogOutput(const QByteArray &line) } } -void DebugReader::processResult(const QByteArray &result) +void DebuggerClient::processResult(const QByteArray &result) { GDBMIResultParser parser; GDBMIResultType resultType; @@ -1186,7 +1163,7 @@ void DebugReader::processResult(const QByteArray &result) } -void DebugReader::processExecAsyncRecord(const QByteArray &line) +void DebuggerClient::processExecAsyncRecord(const QByteArray &line) { QByteArray result; GDBMIResultParser::ParseObject multiValues; @@ -1260,7 +1237,7 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) } } -void DebugReader::processError(const QByteArray &errorLine) +void DebuggerClient::processError(const QByteArray &errorLine) { QString s = QString::fromLocal8Bit(errorLine); mConsoleOutput.append(s); @@ -1272,7 +1249,7 @@ void DebugReader::processError(const QByteArray &errorLine) } static QRegularExpression reGdbSourceLine("^(\\d)+\\s+in\\s+(.+)$"); -void DebugReader::processResultRecord(const QByteArray &line) +void DebuggerClient::processResultRecord(const QByteArray &line) { if (line.startsWith("^exit")) { mProcessExited = true; @@ -1337,7 +1314,7 @@ void DebugReader::processResultRecord(const QByteArray &line) } } -void DebugReader::processDebugOutput(const QByteArray& debugOutput) +void DebuggerClient::processDebugOutput(const QByteArray& debugOutput) { // Only update once per update at most //WatchView.Items.BeginUpdate; @@ -1385,7 +1362,7 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) mFullOutput.clear(); } -void DebugReader::runInferiorStoppedHook() +void DebuggerClient::runInferiorStoppedHook() { QMutexLocker locker(&mCmdQueueMutex); foreach (const PDebugCommand& cmd, mInferiorStoppedHookCommands) { @@ -1393,7 +1370,7 @@ void DebugReader::runInferiorStoppedHook() } } -void DebugReader::runNextCmd() +void DebuggerClient::runNextCmd() { QMutexLocker locker(&mCmdQueueMutex); @@ -1406,7 +1383,7 @@ void DebugReader::runNextCmd() if (mCmdQueue.isEmpty()) { if (mDebugger->useDebugServer() && mInferiorRunning && !mAsyncUpdated) { mAsyncUpdated = true; - QTimer::singleShot(50,this,&DebugReader::asyncUpdate); + QTimer::singleShot(50,this,&DebuggerClient::asyncUpdate); } return; } @@ -1451,7 +1428,6 @@ void DebugReader::runNextCmd() emit writeToDebugFailed(); } -// if devDebugger.ShowCommandLog or pCmd^.ShowInConsole then begin if (pSettings->debugger().enableDebugConsole() ) { //update debug console if (pSettings->debugger().showDetailLog() @@ -1461,7 +1437,7 @@ void DebugReader::runNextCmd() } } -QStringList DebugReader::tokenize(const QString &s) +QStringList DebuggerClient::tokenize(const QString &s) { QStringList result; int tStart,tEnd; @@ -1557,7 +1533,7 @@ QStringList DebugReader::tokenize(const QString &s) return result; } -bool DebugReader::outputTerminated(const QByteArray &text) +bool DebuggerClient::outputTerminated(const QByteArray &text) { QStringList lines = textToLines(QString::fromUtf8(text)); foreach (const QString& line,lines) { @@ -1567,7 +1543,7 @@ bool DebugReader::outputTerminated(const QByteArray &text) return false; } -void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint) +void DebuggerClient::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint) { QString filename; // gdb use system encoding for file path @@ -1580,7 +1556,7 @@ void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpo emit breakpointInfoGetted(filename, line , number); } -void DebugReader::handleFrame(const GDBMIResultParser::ParseValue &frame) +void DebuggerClient::handleFrame(const GDBMIResultParser::ParseValue &frame) { if (frame.isValid()) { GDBMIResultParser::ParseObject frameObj = frame.object(); @@ -1598,7 +1574,7 @@ void DebugReader::handleFrame(const GDBMIResultParser::ParseValue &frame) } } -void DebugReader::handleStack(const QList & stack) +void DebuggerClient::handleStack(const QList & stack) { mDebugger->backtraceModel()->clear(); foreach (const GDBMIResultParser::ParseValue& frameValue, stack) { @@ -1616,7 +1592,7 @@ void DebugReader::handleStack(const QList & stack } } -void DebugReader::handleLocalVariables(const QList &variables) +void DebuggerClient::handleLocalVariables(const QList &variables) { QStringList locals; foreach (const GDBMIResultParser::ParseValue& varValue, variables) { @@ -1633,12 +1609,12 @@ void DebugReader::handleLocalVariables(const QList &rows) +void DebuggerClient::handleMemory(const QList &rows) { QStringList memory; foreach (const GDBMIResultParser::ParseValue& row, rows) { @@ -1654,7 +1630,7 @@ void DebugReader::handleMemory(const QList &rows) emit memoryUpdated(memory); } -void DebugReader::handleRegisterNames(const QList &names) +void DebuggerClient::handleRegisterNames(const QList &names) { QStringList nameList; foreach (const GDBMIResultParser::ParseValue& nameValue, names) { @@ -1665,7 +1641,7 @@ void DebugReader::handleRegisterNames(const QList emit registerNamesUpdated(nameList); } -void DebugReader::handleRegisterValue(const QList &values) +void DebuggerClient::handleRegisterValue(const QList &values) { QHash result; foreach (const GDBMIResultParser::ParseValue& val, values) { @@ -1683,7 +1659,7 @@ void DebugReader::handleRegisterValue(const QList emit registerValuesUpdated(result); } -void DebugReader::handleCreateVar(const GDBMIResultParser::ParseObject &multiVars) +void DebuggerClient::handleCreateVar(const GDBMIResultParser::ParseObject &multiVars) { if (!mCurrentCmd) return; @@ -1696,7 +1672,7 @@ void DebugReader::handleCreateVar(const GDBMIResultParser::ParseObject &multiVar emit varCreated(expression,name,numChild,value,type,hasMore); } -void DebugReader::handleListVarChildren(const GDBMIResultParser::ParseObject &multiVars) +void DebuggerClient::handleListVarChildren(const GDBMIResultParser::ParseObject &multiVars) { if (!mCurrentCmd) return; @@ -1723,7 +1699,7 @@ void DebugReader::handleListVarChildren(const GDBMIResultParser::ParseObject &mu } } -void DebugReader::handleUpdateVarValue(const QList &changes) +void DebuggerClient::handleUpdateVarValue(const QList &changes) { foreach (const GDBMIResultParser::ParseValue& value, changes) { GDBMIResultParser::ParseObject obj = value.object(); @@ -1741,7 +1717,7 @@ void DebugReader::handleUpdateVarValue(const QList(); - auto action = finally([&]{ - mProcess.reset(); - }); - mProcess->setProgram(cmd); - mProcess->setArguments(arguments); - mProcess->setProcessChannelMode(QProcess::MergedChannels); - - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - QString path = env.value("PATH"); - QStringList pathAdded = mBinDirs; - if (!path.isEmpty()) { - path = pathAdded.join(PATH_SEPARATOR) + PATH_SEPARATOR + path; - } else { - path = pathAdded.join(PATH_SEPARATOR); - } - QString cmdDir = extractFileDir(cmd); - if (!cmdDir.isEmpty()) { - path = cmdDir + PATH_SEPARATOR + path; - } - env.insert("PATH",path); - mProcess->setProcessEnvironment(env); - - mProcess->setWorkingDirectory(workingDir); - - connect(mProcess.get(), &QProcess::errorOccurred, - [&](){ - mErrorOccured= true; - }); - QByteArray buffer; - QByteArray readed; - - mProcess->start(); - mProcess->waitForStarted(5000); - mStartSemaphore.release(1); - while (true) { - mProcess->waitForFinished(1); - if (mProcess->state()!=QProcess::Running) { - break; - } - if (mStop) { - mProcess->terminate(); - mProcess->kill(); - break; - } - if (mErrorOccured) - break; - readed = mProcess->readAll(); - buffer += readed; - - if (readed.endsWith("\n")&& outputTerminated(buffer)) { - processDebugOutput(buffer); - buffer.clear(); - mCmdRunning = false; - runNextCmd(); - } else if (!mCmdRunning && readed.isEmpty()){ - runNextCmd(); - } else if (readed.isEmpty()){ - msleep(1); - } - } - if (mErrorOccured) { - emit processError(mProcess->error()); - } -} BreakpointModel::BreakpointModel(QObject *parent):QAbstractTableModel(parent), mIsForProject(false) diff --git a/RedPandaIDE/debugger/debugger.h b/RedPandaIDE/debugger/debugger.h index 9b74417b..1ef40299 100644 --- a/RedPandaIDE/debugger/debugger.h +++ b/RedPandaIDE/debugger/debugger.h @@ -295,11 +295,11 @@ private: }; -class DebugReader; +class DebuggerClient; class DebugTarget; class Editor; -using PDebugReader = std::shared_ptr; +using PDebugReader = std::shared_ptr; class Debugger : public QObject { @@ -417,7 +417,7 @@ private: std::shared_ptr mWatchModel; std::shared_ptr mRegisterModel; std::shared_ptr mMemoryModel; - DebugReader *mReader; + DebuggerClient *mClient; DebugTarget *mTarget; bool mForceUTF8; bool mDebugInfosUsingUTF8; @@ -462,48 +462,29 @@ protected: void run() override; }; -class DebugReader : public QThread +class DebuggerClient : public QThread { Q_OBJECT public: - explicit DebugReader(Debugger* debugger, QObject *parent = nullptr); - void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source); - void registerInferiorStoppedCommand(const QString &Command, const QString &Params); + explicit DebuggerClient(Debugger* debugger, QObject *parent = nullptr); + virtual void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) = 0; + virtual void registerInferiorStoppedCommand(const QString &Command, const QString &Params) = 0; + virtual void stopDebug() = 0; + bool commandRunning(); QString debuggerPath() const; void setDebuggerPath(const QString &debuggerPath); - void stopDebug(); - - bool commandRunning(); void waitStart(); - bool inferiorPaused() const; - bool processExited() const; bool signalReceived() const; const QStringList &consoleOutput() const; - int breakPointLine() const; - - const QString &breakPointFile() const; - const PDebugCommand ¤tCmd() const; bool updateCPUInfo() const; - bool updateLocals() const; - - const QStringList &localsValue() const; - - bool evalReady() const; - - const QString &evalValue() const; - - bool updateMemory() const; - - const QStringList &memoryValue() const; - bool receivedSFWarning() const; const QStringList &fullOutput() const; @@ -585,22 +566,24 @@ private: QByteArray removeToken(const QByteArray& line); private slots: void asyncUpdate(); -private: - Debugger *mDebugger; - QString mDebuggerPath; +protected: #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) QRecursiveMutex mCmdQueueMutex; #else QMutex mCmdQueueMutex; #endif - QSemaphore mStartSemaphore; QQueue mCmdQueue; + QList mInferiorStoppedHookCommands; +private: + Debugger *mDebugger; + QString mDebuggerPath; + + QSemaphore mStartSemaphore; bool mErrorOccured; bool mAsyncUpdated; //fOnInvalidateAllVars: TInvalidateAllVarsEvent; bool mCmdRunning; PDebugCommand mCurrentCmd; - std::shared_ptr mProcess; QStringList mBinDirs; QMap mFileCache; @@ -610,7 +593,6 @@ private: QString mSignalMeaning; // - QList mInferiorStoppedHookCommands; bool mInferiorRunning; bool mProcessExited; @@ -624,10 +606,6 @@ private: QString mCurrentFile; QStringList mConsoleOutput; QStringList mFullOutput; - bool mStop; - // QThread interface -protected: - void run() override; }; #endif // DEBUGGER_H diff --git a/RedPandaIDE/debugger/gdbmidebugger.cpp b/RedPandaIDE/debugger/gdbmidebugger.cpp new file mode 100644 index 00000000..88346437 --- /dev/null +++ b/RedPandaIDE/debugger/gdbmidebugger.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "gdbmidebugger.h" +#include "../utils.h" + +#include + +GDBMIDebuggerClient::GDBMIDebuggerClient(Debugger *debugger, QObject *parent): + DebuggerClient(debugger, parent) +{ + +} + +void GDBMIDebuggerClient::postCommand(const QString &Command, const QString &Params, + DebugCommandSource Source) +{ + QMutexLocker locker(&mCmdQueueMutex); + PDebugCommand pCmd = std::make_shared(); + pCmd->command = Command; + pCmd->params = Params; + pCmd->source = Source; + mCmdQueue.enqueue(pCmd); +// if (!mCmdRunning) + // runNextCmd(); +} + +void GDBMIDebuggerClient::registerInferiorStoppedCommand(const QString &Command, const QString &Params) +{ + QMutexLocker locker(&mCmdQueueMutex); + PDebugCommand pCmd = std::make_shared(); + pCmd->command = Command; + pCmd->params = Params; + pCmd->source = DebugCommandSource::Other; + mInferiorStoppedHookCommands.append(pCmd); +} + +void GDBMIDebuggerClient::stopDebug() +{ + mStop = true; +} + +void GDBMIDebuggerClient::run() +{ + mStop = false; + mInferiorRunning = false; + mProcessExited = false; + mErrorOccured = false; + QString cmd = debuggerPath(); +// QString arguments = "--annotate=2"; + QStringList arguments{"--interpret=mi", "--silent"}; + QString workingDir = QFileInfo(debuggerPath()).path(); + + mProcess = std::make_shared(); + auto action = finally([&]{ + mProcess.reset(); + }); + mProcess->setProgram(cmd); + mProcess->setArguments(arguments); + mProcess->setProcessChannelMode(QProcess::MergedChannels); + + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + QString path = env.value("PATH"); + QStringList pathAdded = binDirs(); + if (!path.isEmpty()) { + path = pathAdded.join(PATH_SEPARATOR) + PATH_SEPARATOR + path; + } else { + path = pathAdded.join(PATH_SEPARATOR); + } + QString cmdDir = extractFileDir(cmd); + if (!cmdDir.isEmpty()) { + path = cmdDir + PATH_SEPARATOR + path; + } + env.insert("PATH",path); + mProcess->setProcessEnvironment(env); + + mProcess->setWorkingDirectory(workingDir); + + connect(mProcess.get(), &QProcess::errorOccurred, + [&](){ + mErrorOccured= true; + }); + QByteArray buffer; + QByteArray readed; + + mProcess->start(); + mProcess->waitForStarted(5000); + mStartSemaphore.release(1); + while (true) { + mProcess->waitForFinished(1); + if (mProcess->state()!=QProcess::Running) { + break; + } + if (mStop) { + mProcess->terminate(); + mProcess->kill(); + break; + } + if (mErrorOccured) + break; + readed = mProcess->readAll(); + buffer += readed; + + if (readed.endsWith("\n")&& outputTerminated(buffer)) { + processDebugOutput(buffer); + buffer.clear(); + mCmdRunning = false; + runNextCmd(); + } else if (!mCmdRunning && readed.isEmpty()){ + runNextCmd(); + } else if (readed.isEmpty()){ + msleep(1); + } + } + if (mErrorOccured) { + emit processError(mProcess->error()); + } +} + diff --git a/RedPandaIDE/debugger/gdbmidebugger.h b/RedPandaIDE/debugger/gdbmidebugger.h new file mode 100644 index 00000000..97014e76 --- /dev/null +++ b/RedPandaIDE/debugger/gdbmidebugger.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef GDBMI_DEBUGGER_H +#define GDBMI_DEBUGGER_H + +#include "debugger.h" +#include +#include + +class GDBMIDebuggerClient: public DebuggerClient { + Q_OBJECT +public: + explicit GDBMIDebuggerClient(Debugger* debugger, QObject *parent = nullptr); + + // DebuggerClient interface +public: + void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) override; + void registerInferiorStoppedCommand(const QString &Command, const QString &Params) override; + void stopDebug() override; + // QThread interface +protected: + void run() override; +private: + bool mStop; + std::shared_ptr mProcess; +}; + +#endif // GDBMI_DEBUGGER_H diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/debugger/gdbmiresultparser.cpp similarity index 100% rename from RedPandaIDE/gdbmiresultparser.cpp rename to RedPandaIDE/debugger/gdbmiresultparser.cpp diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/debugger/gdbmiresultparser.h similarity index 100% rename from RedPandaIDE/gdbmiresultparser.h rename to RedPandaIDE/debugger/gdbmiresultparser.h diff --git a/libs/qsynedit/qsynedit/syntaxer/asm.h b/libs/qsynedit/qsynedit/syntaxer/asm.h index 4cd162ef..3fc96701 100644 --- a/libs/qsynedit/qsynedit/syntaxer/asm.h +++ b/libs/qsynedit/qsynedit/syntaxer/asm.h @@ -125,4 +125,4 @@ public: } -#endif // SYNEDITASMHIGHLIGHTER_H +#endif // QSYNEDIT_ASM_SYNTAXER_H diff --git a/libs/qsynedit/qsynedit/syntaxer/cpp.h b/libs/qsynedit/qsynedit/syntaxer/cpp.h index dc0e0231..6209da37 100644 --- a/libs/qsynedit/qsynedit/syntaxer/cpp.h +++ b/libs/qsynedit/qsynedit/syntaxer/cpp.h @@ -221,4 +221,4 @@ public: } -#endif // SYNEDITCPPHIGHLIGHTER_H +#endif // QSYNEDIT_CPP_SYNTAXER_H diff --git a/libs/qsynedit/qsynedit/syntaxer/glsl.h b/libs/qsynedit/qsynedit/syntaxer/glsl.h index 7299431f..e33f5aa5 100644 --- a/libs/qsynedit/qsynedit/syntaxer/glsl.h +++ b/libs/qsynedit/qsynedit/syntaxer/glsl.h @@ -186,4 +186,4 @@ public: }; } -#endif // SYNEDITGLSLHIGHLIGHTER_H +#endif // QSYNEDIT_GLSL_SYNTAXER_H diff --git a/libs/qsynedit/qsynedit/syntaxer/lua.h b/libs/qsynedit/qsynedit/syntaxer/lua.h index 4b22b7d0..3b388cd5 100644 --- a/libs/qsynedit/qsynedit/syntaxer/lua.h +++ b/libs/qsynedit/qsynedit/syntaxer/lua.h @@ -175,4 +175,4 @@ public: } -#endif // SYNEDITCPPHIGHLIGHTER_H +#endif // QSYNEDIT_LUA_SYNTAXER_H diff --git a/libs/qsynedit/qsynedit/syntaxer/makefile.h b/libs/qsynedit/qsynedit/syntaxer/makefile.h index 015afcf4..d78c0e8d 100644 --- a/libs/qsynedit/qsynedit/syntaxer/makefile.h +++ b/libs/qsynedit/qsynedit/syntaxer/makefile.h @@ -155,4 +155,4 @@ public: }; } -#endif // MAKEFILE_H +#endif // QSYNEDIT_MAKEFILE_SYNTAXER_H diff --git a/libs/qsynedit/qsynedit/syntaxer/syntaxer.h b/libs/qsynedit/qsynedit/syntaxer/syntaxer.h index 8f1ef306..08417146 100644 --- a/libs/qsynedit/qsynedit/syntaxer/syntaxer.h +++ b/libs/qsynedit/qsynedit/syntaxer/syntaxer.h @@ -195,4 +195,4 @@ private: using PSyntaxer = std::shared_ptr; using SyntaxerList = QVector; } -#endif // SYNHIGHLIGTERBASE_H +#endif // QSYNEDIT_SYNTAXER_H diff --git a/libs/qsynedit/qsynedit/syntaxer/textfile.h b/libs/qsynedit/qsynedit/syntaxer/textfile.h index 593d0448..9c03f83a 100644 --- a/libs/qsynedit/qsynedit/syntaxer/textfile.h +++ b/libs/qsynedit/qsynedit/syntaxer/textfile.h @@ -84,4 +84,4 @@ public: }; } -#endif // MAKEFILE_H +#endif // QSYNEDIT_TEXTFILE_SYNTAXER_H