diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 5f77e1ab..5458682e 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -68,7 +68,7 @@ bool Debugger::start() connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); mReader->start(); - mReader->mStartSemaphore.acquire(1); + mReader->waitStart(); pMainWindow->updateAppTitle(); @@ -450,7 +450,7 @@ void Debugger::syncFinishedParsing() } // The program to debug has stopped. Stop the debugger - if (mReader->doprocessexited) { + if (mReader->processExited()) { stop(); return; } @@ -1151,21 +1151,103 @@ void DebugReader::handleValueHistoryValue() doevalready = true; } -AnnotationType DebugReader::peekNextAnnotation() +void DebugReader::processConsoleOutput(const QString& line) { - int indexBackup = mIndex; // do NOT modifiy curpos - AnnotationType result = getNextAnnotation(); - mIndex = indexBackup; - return result; + if (line.length()>3 && line.startsWith("~\"") && line.endsWith("\"")) { + mConsoleOutput.append(line.mid(2,line.length()-3)); + } +} + +void DebugReader::processResult(const QString &result) +{ + int pos = result.indexOf('='); + QString name = result.mid(0,pos); + QString value = result.mid(pos+1); + if (name == "bkpt") { + // info about breakpoint + handleBreakpoint(value); + } else if (name == "BreakpointTable") { + // info about breakpoint table + handleBreakpointTable(value); + } else if (name == "stack") { + // info about frame stack + handleFrameStack(value); + } else if (name == "variables") { + // info about local variables & arguments + handleVariables(value); + } else if (name == "frame") { + // info about current selected frame + handleFrame(value); + } else if (name == "asm_insns") { + // info about disassembled codes + handleDisassembled(value); + } else if (name == "value") { + handleEval(value); + } else if (name=="register-names") { + handleRegisterNames(value); + } else if (name == "register-values") { + handleRegisterValues(value); + } else if (name == "memory") { + handleMemory(value); + } +} + +void DebugReader::processExecAsyncRecord(const QString &line) +{ + if (line.startsWith("*running")) { + mInferiorPaused = false; + return; + } + if (line.startsWith("*stopped")) { + mInferiorPaused = true; + QStringList props = line.split(','); + if (props.count()<2) + return; + QString reason = props[1]; + QRegExp exp("^reason=\"(.+)\"$"); + reason = exp.cap(1); + if (reason.isEmpty()) + return; + if (reason.startsWith("exited")) { + //inferior exited, gdb should terminate too + mProcessExited = true; + return; + } + if (reason==("signal-received")) { + //todo: signal received + return; + } + } +} + +void DebugReader::processError(const QString &errorLine) +{ + //todo } void DebugReader::processResultRecord(const QString &line) { if (line.startsWith("^exit")) { - doprocessexited = true; + mProcessExited = true; + return; + } + if (line.startsWith("^error")) { + processError(line); + return; + } + if (line.startsWith("^done") + || line.startsWith("^running")) { + int pos = line.indexOf(','); + if (pos>=0) { + QString result = line.mid(pos+1); + processResult(result); + } + return ; + } + if (line.startsWith("^connected")) { + //TODO: connected to remote target return; } - } void DebugReader::processDebugOutput(const QString& debugOutput) @@ -1181,6 +1263,8 @@ void DebugReader::processDebugOutput(const QString& debugOutput) emit parseStarted(); + mConsoleOutput.clear(); + //try dobacktraceready = false; @@ -1189,7 +1273,6 @@ void DebugReader::processDebugOutput(const QString& debugOutput) doevalready = false; doupdatememoryview = false; doupdatelocal = false; - doprocessexited = false; doupdateexecution = false; doreceivedsignal = false; doupdatecpuwindow = false; @@ -1205,14 +1288,17 @@ void DebugReader::processDebugOutput(const QString& debugOutput) } switch (line[0].unicode()) { case '~': // console stream output + processConsoleOutput(line); + break; case '@': // target stream output case '&': // log stream output - //todo: process console stream output break; case '^': // result record processResultRecord(line); break; case '*': // exec async output + processExecAsyncRecord(line); + break; case '+': // status async output case '=': // notify async output break; @@ -1522,25 +1608,6 @@ void DebugReader::runNextCmd() } } -void DebugReader::skipSpaces() -{ - while (mIndex < mOutput.length() && - (mOutput[mIndex]=='\t' || mOutput[mIndex]==' ')) - mIndex++; -} - -void DebugReader::skipToAnnotation() -{ - // Walk up to the next annotation - while (mIndex < mOutput.length() && - (mOutput[mIndex]!=26)) - mIndex++; - // Crawl through the remaining ->'s - while (mIndex < mOutput.length() && - (mOutput[mIndex]==26)) - mIndex++; -} - QStringList DebugReader::tokenize(const QString &s) { QStringList result; @@ -1637,6 +1704,25 @@ QStringList DebugReader::tokenize(const QString &s) return result; } +QString DebugReader::removeToken(const QString &line) +{ + int p=0; + while (pstart(); mProcess->waitForStarted(5000); mStartSemaphore.release(1); - while (true) { mProcess->waitForFinished(1); if (mProcess->state()!=QProcess::Running) { diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 7be47f6c..741c658f 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -18,27 +18,6 @@ enum class DebugCommandSource { Other }; -enum class AnnotationType { - TPrePrompt, TPrompt, TPostPrompt, - TSource, - TDisplayBegin, TDisplayEnd, - TDisplayExpression, - TFrameSourceFile, TFrameSourceBegin, TFrameSourceLine, TFrameFunctionName, TFrameWhere, - TFrameArgs, - TFrameBegin, TFrameEnd, - TErrorBegin, TErrorEnd, - TArrayBegin, TArrayEnd, - TElt, TEltRep, TEltRepEnd, - TExit, - TSignal, TSignalName, TSignalNameEnd, TSignalString, TSignalStringEnd, - TValueHistoryValue, TValueHistoryBegin, TValueHistoryEnd, - TArgBegin, TArgEnd, TArgValue, TArgNameEnd, - TFieldBegin, TFieldEnd, TFieldValue, TFieldNameEnd, - TInfoReg, TInfoAsm, - TUnknown, TEOF, - TLocal, TParam, TMemory -}; - struct DebugCommand{ QString command; QString params; @@ -284,10 +263,16 @@ public: void stopDebug(); bool commandRunning(); + bool waitStart(); bool invalidateAllVars() const; void setInvalidateAllVars(bool invalidateAllVars); + bool inferiorPaused() const; + + bool processExited() const; + + signals: void parseStarted(); void invalidateAllVars(); @@ -301,15 +286,7 @@ signals: void cmdFinished(); private: void clearCmdQueue(); - bool findAnnotation(AnnotationType annotation); - AnnotationType getAnnotation(const QString& s); - AnnotationType getLastAnnotation(const QByteArray& text); - AnnotationType getNextAnnotation(); bool outputTerminated(QByteArray& text); - QString getNextFilledLine(); - QString getNextLine(); - QString getNextWord(); - QString getRemainingLine(); void handleDisassembly(); void handleDisplay(); void handleError(); @@ -323,8 +300,11 @@ private: void handleSignal(); void handleSource(); void handleValueHistoryValue(); - AnnotationType peekNextAnnotation(); + void processConsoleOutput(const QString& line); + void processResult(const QString& result); + void processExecAsyncRecord(const QString& line); + void processError(const QString& errorLine); void processResultRecord(const QString& line); void processDebugOutput(const QString& debugOutput); QString processEvalOutput(); @@ -333,6 +313,7 @@ private: void skipSpaces(); void skipToAnnotation(); QStringList tokenize(const QString& s); + QString removeToken(const QString& line); private: Debugger *mDebugger; QString mDebuggerPath; @@ -365,7 +346,6 @@ private: bool dodisassemblerready; bool doregistersready; bool doevalready; - bool doprocessexited; bool doupdatecpuwindow; bool doupdateexecution; bool doreceivedsignal; @@ -373,9 +353,11 @@ private: bool doupdatememoryview; bool doupdatelocal; - bool mStop; + bool mInferiorPaused; + bool mProcessExited; + QStringList mConsoleOutput; - friend class Debugger; + bool mStop; // QThread interface protected: void run() override; diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 2a891ef1..36672c4c 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1296,7 +1296,6 @@ void MainWindow::debug() if (!mDebugger->start()) return; filePath.replace('\\','/'); - mDebugger->sendCommand("-gdb-set","mi-async on"); mDebugger->sendCommand("-gdb-set","host-charset UTF-8"); mDebugger->sendCommand("-file-exec-and-symbols", '"' + filePath + '"'); @@ -1376,7 +1375,6 @@ void MainWindow::debug() mDebugger->setUseUTF8(e->fileEncoding() == ENCODING_UTF8 || e->fileEncoding() == ENCODING_UTF8_BOM); if (!mDebugger->start()) return; - mDebugger->sendCommand("-gdb-set","mi-async on"); mDebugger->sendCommand("-gdb-set","host-charset UTF-8"); mDebugger->sendCommand("-file-exec-and-symbols", QString("\"%1\"").arg(debugFile.filePath().replace('\\','/'))); }