- enhancement: Use asm highlighter in cpu window

- fix: "AT&T" radio button not correctly checked in cpu window
  - enhancement: Remove blank lines in the register list of cpu window.
  - fix: Cpu window's size not correctly saved, if it is not closed before app exits.
  - fix: Can't restore cpu window's splitter position.
This commit is contained in:
Roy Qu 2022-12-02 10:19:03 +08:00
parent f9fb966c38
commit 77942999d5
11 changed files with 178 additions and 36 deletions

View File

@ -17,6 +17,11 @@ Red Panda C++ Version 2.5
- enhancement: Disable "run" and "debug" actions when current project is static or dynamic library - enhancement: Disable "run" and "debug" actions when current project is static or dynamic library
- enhancement: Add "Generate Assembly" in "Run" Menu - enhancement: Add "Generate Assembly" in "Run" Menu
- enhancement: Improve highlighter for asm - enhancement: Improve highlighter for asm
- enhancement: Use asm highlighter in cpu window
- fix: "AT&T" radio button not correctly checked in cpu window
- enhancement: Remove blank lines in the register list of cpu window.
- fix: Cpu window's size not correctly saved, if it is not closed before app exits.
- fix: Can't restore cpu window's splitter position.
Red Panda C++ Version 2.4 Red Panda C++ Version 2.4

View File

@ -1459,7 +1459,9 @@ void DebugReader::handleRegisterNames(const QList<GDBMIResultParser::ParseValue>
{ {
QStringList nameList; QStringList nameList;
foreach (const GDBMIResultParser::ParseValue& nameValue, names) { foreach (const GDBMIResultParser::ParseValue& nameValue, names) {
nameList.append(nameValue.value()); // QString text = nameValue.value().trimmed();
// if (!text.isEmpty())
nameList.append(nameValue.value());
} }
emit registerNamesUpdated(nameList); emit registerNamesUpdated(nameList);
} }
@ -2605,7 +2607,9 @@ QVariant RegisterModel::data(const QModelIndex &index, int role) const
case 0: case 0:
return mRegisterNames[index.row()]; return mRegisterNames[index.row()];
case 1: case 1:
return mRegisterValues.value(index.row(),""); return mRegisterValues.value(
mRegisterNameIndex.value(index.row(),-1)
,"");
default: default:
return QVariant(); return QVariant();
} }
@ -2630,7 +2634,15 @@ QVariant RegisterModel::headerData(int section, Qt::Orientation orientation, int
void RegisterModel::updateNames(const QStringList &regNames) void RegisterModel::updateNames(const QStringList &regNames)
{ {
beginResetModel(); beginResetModel();
mRegisterNames = regNames; mRegisterNameIndex.clear();
mRegisterNames.clear();
for (int i=0;i<regNames.length();i++) {
QString regName = regNames[i].trimmed();
if (!regName.isEmpty()) {
mRegisterNames.append(regNames[i]);
mRegisterNameIndex.insert(mRegisterNames.count()-1,i);
}
}
endResetModel(); endResetModel();
} }

View File

@ -113,6 +113,7 @@ public:
void clear(); void clear();
private: private:
QStringList mRegisterNames; QStringList mRegisterNames;
QHash<int,int> mRegisterNameIndex;
QHash<int,QString> mRegisterValues; QHash<int,QString> mRegisterValues;
}; };

View File

@ -4925,6 +4925,8 @@ void MainWindow::on_actionOpen_triggered()
void MainWindow::closeEvent(QCloseEvent *event) { void MainWindow::closeEvent(QCloseEvent *event) {
mQuitting = true; mQuitting = true;
if (!mShouldRemoveAllSettings) { if (!mShouldRemoveAllSettings) {
if (mCPUDialog)
mCPUDialog->close();
Settings::UI& settings = pSettings->ui(); Settings::UI& settings = pSettings->ui();
settings.setMainWindowState(saveState()); settings.setMainWindowState(saveState());
settings.setMainWindowGeometry(saveGeometry()); settings.setMainWindowGeometry(saveGeometry());

View File

@ -3745,7 +3745,6 @@ void Settings::Debugger::doSave()
saveValue("gdb_server_port",mGDBServerPort); saveValue("gdb_server_port",mGDBServerPort);
saveValue("memory_view_rows",mMemoryViewRows); saveValue("memory_view_rows",mMemoryViewRows);
saveValue("memory_view_columns",mMemoryViewColumns); saveValue("memory_view_columns",mMemoryViewColumns);
} }
void Settings::Debugger::doLoad() void Settings::Debugger::doLoad()

View File

@ -26,12 +26,13 @@
CPUDialog::CPUDialog(QWidget *parent) : CPUDialog::CPUDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::CPUDialog) ui(new Ui::CPUDialog),
mInited(false)
{ {
setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint); setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
setWindowFlag(Qt::WindowContextHelpButtonHint,false); setWindowFlag(Qt::WindowContextHelpButtonHint,false);
ui->setupUi(this); ui->setupUi(this);
ui->txtCode->setHighlighter(highlighterManager.getCppHighlighter()); ui->txtCode->setHighlighter(highlighterManager.getAsmHighlighter());
ui->txtCode->setReadOnly(true); ui->txtCode->setReadOnly(true);
ui->txtCode->gutter().setShowLineNumbers(false); ui->txtCode->gutter().setShowLineNumbers(false);
ui->txtCode->setCaretUseTextColor(true); ui->txtCode->setCaretUseTextColor(true);
@ -40,6 +41,7 @@ CPUDialog::CPUDialog(QWidget *parent) :
ui->txtCode->codeFolding().fillIndents = false; ui->txtCode->codeFolding().fillIndents = false;
ui->txtCode->setGutterWidth(0); ui->txtCode->setGutterWidth(0);
ui->txtCode->setUseCodeFolding(false); ui->txtCode->setUseCodeFolding(false);
ui->txtCode->setRightEdge(0);
highlighterManager.applyColorScheme(ui->txtCode->highlighter(), highlighterManager.applyColorScheme(ui->txtCode->highlighter(),
pSettings->editor().colorScheme()); pSettings->editor().colorScheme());
PColorSchemeItem item = pColorManager->getItem(pSettings->editor().colorScheme(),COLOR_SCHEME_ACTIVE_LINE); PColorSchemeItem item = pColorManager->getItem(pSettings->editor().colorScheme(),COLOR_SCHEME_ACTIVE_LINE);
@ -60,17 +62,11 @@ CPUDialog::CPUDialog(QWidget *parent) :
delete m; delete m;
ui->rdIntel->setChecked(pSettings->debugger().useIntelStyle()); ui->rdIntel->setChecked(pSettings->debugger().useIntelStyle());
if (!ui->rdIntel->isChecked())
ui->rdATT->setChecked(true);
ui->chkBlendMode->setChecked(pSettings->debugger().blendMode()); ui->chkBlendMode->setChecked(pSettings->debugger().blendMode());
resize(pSettings->ui().CPUDialogWidth(),pSettings->ui().CPUDialogHeight()); resize(pSettings->ui().CPUDialogWidth(),pSettings->ui().CPUDialogHeight());
QList<int> sizes = ui->splitter->sizes();
int tabWidth = pSettings->ui().CPUDialogSplitterPos();
int totalSize = sizes[0] + sizes[1];
sizes[0] = tabWidth;
sizes[1] = std::max(1,totalSize - sizes[0]);
ui->splitter->setSizes(sizes);
onUpdateIcons();
connect(pIconsManager,&IconsManager::actionIconsUpdated, connect(pIconsManager,&IconsManager::actionIconsUpdated,
this, &CPUDialog::onUpdateIcons); this, &CPUDialog::onUpdateIcons);
} }
@ -200,3 +196,18 @@ void CPUDialog::onUpdateIcons()
pIconsManager->setIcon(ui->btnStepOverInstruction, IconsManager::ACTION_RUN_STEP_OVER_INSTRUCTION); pIconsManager->setIcon(ui->btnStepOverInstruction, IconsManager::ACTION_RUN_STEP_OVER_INSTRUCTION);
} }
void CPUDialog::showEvent(QShowEvent *event)
{
QDialog::showEvent(event);
if (!mInited) {
mInited=true;
QList<int> sizes = ui->splitter->sizes();
int tabWidth = pSettings->ui().CPUDialogSplitterPos();
int totalSize = sizes[0] + sizes[1];
sizes[0] = tabWidth;
sizes[1] = std::max(0,totalSize - sizes[0]);
ui->splitter->setSizes(sizes);
}
}

View File

@ -42,6 +42,7 @@ private:
void sendSyntaxCommand(); void sendSyntaxCommand();
private: private:
Ui::CPUDialog *ui; Ui::CPUDialog *ui;
bool mInited;
// QWidget interface // QWidget interface
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
@ -52,6 +53,10 @@ private slots:
void on_btnStepOverInstruction_clicked(); void on_btnStepOverInstruction_clicked();
void on_btnStepIntoInstruction_clicked(); void on_btnStepIntoInstruction_clicked();
void onUpdateIcons(); void onUpdateIcons();
// QWidget interface
protected:
void showEvent(QShowEvent *event) override;
}; };
#endif // CPUDIALOG_H #endif // CPUDIALOG_H

View File

@ -34,7 +34,7 @@
<widget class="QWidget" name="widget" native="true"> <widget class="QWidget" name="widget" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
@ -83,7 +83,7 @@
<widget class="QSynedit::SynEdit" name="txtCode"> <widget class="QSynedit::SynEdit" name="txtCode">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>3</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
@ -187,6 +187,12 @@
</layout> </layout>
</widget> </widget>
<widget class="QTableView" name="lstRegister"> <widget class="QTableView" name="lstRegister">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set> <set>QAbstractItemView::NoEditTriggers</set>
</property> </property>

View File

@ -53,6 +53,7 @@ extern const QChar SoftBreakGlyph;
#define SYNS_AttrSymbol "Symbol" #define SYNS_AttrSymbol "Symbol"
#define SYNS_AttrVariable "Variable" #define SYNS_AttrVariable "Variable"
#define SYNS_AttrSpace "Space" #define SYNS_AttrSpace "Space"
// names of exporter output formats // names of exporter output formats
#define SYNS_ExporterFormatHTML "HTML" #define SYNS_ExporterFormatHTML "HTML"
#define SYNS_ExporterFormatRTF "RTF" #define SYNS_ExporterFormatRTF "RTF"

View File

@ -20,6 +20,23 @@
namespace QSynedit { namespace QSynedit {
const QSet<QString> ASMHighlighter::Registers {
"ah","al","ax","eax",
"bh","bl","bx","ebx",
"ch","cl","cx","ecx",
"dh","dl","dx","edx",
"rax","rbx","rcx","rdx","rsi","rdi","rbp",
"rsp","r8","r9","r10","r11","r12","r13","r14","r15",
"r8h","r8l","r8w","r8d",
"r9h","r9l","r9w","r9d",
"r10h","r10l","r10w","r10d",
"r11h","r11l","r11w","r11d",
"r12h","r12l","r12w","r12d",
"r13h","r13l","r13w","r13d",
"r14h","r14l","r14w","r14d",
"r15h","r15l","r15w","r15d"
};
const QSet<QString> ASMHighlighter::Keywords { const QSet<QString> ASMHighlighter::Keywords {
"movb","movw","movl","movq", "movb","movw","movl","movq",
"leab","leaw","leal","leaq", "leab","leaw","leal","leaq",
@ -83,13 +100,24 @@ ASMHighlighter::ASMHighlighter()
{ {
mNumberAttribute = std::make_shared<HighlighterAttribute>(SYNS_AttrNumber, TokenType::Number); mNumberAttribute = std::make_shared<HighlighterAttribute>(SYNS_AttrNumber, TokenType::Number);
addAttribute(mNumberAttribute); addAttribute(mNumberAttribute);
mDirectiveAttribute = std::make_shared<HighlighterAttribute>(SYNS_AttrVariable, TokenType::Keyword);
addAttribute(mDirectiveAttribute);
mLabelAttribute = std::make_shared<HighlighterAttribute>(SYNS_AttrFunction, TokenType::Keyword);
addAttribute(mLabelAttribute);
mRegisterAttribute = std::make_shared<HighlighterAttribute>(SYNS_AttrClass, TokenType::Keyword);
addAttribute(mRegisterAttribute);
} }
PHighlighterAttribute ASMHighlighter::numberAttribute() const PHighlighterAttribute &ASMHighlighter::numberAttribute() const
{ {
return mNumberAttribute; return mNumberAttribute;
} }
const PHighlighterAttribute &ASMHighlighter::registerAttribute() const
{
return mRegisterAttribute;
}
void ASMHighlighter::CommentProc() void ASMHighlighter::CommentProc()
{ {
mTokenID = TokenId::Comment; mTokenID = TokenId::Comment;
@ -114,17 +142,32 @@ void ASMHighlighter::GreaterProc()
mRun++; mRun++;
} }
void ASMHighlighter::IdentProc() void ASMHighlighter::IdentProc(IdentPrefix prefix)
{ {
int start = mRun; int start = mRun;
while (isIdentChar(mLine[mRun])) { while (isIdentChar(mLine[mRun])) {
mRun++; mRun++;
} }
QString s = mLineString.mid(start,mRun-start); QString s = mLineString.mid(start,mRun-start).toLower();
if (Keywords.contains(s)) { switch(prefix) {
mTokenID = TokenId::rainbow; case IdentPrefix::Percent:
} else { mTokenID = TokenId::Register;
mTokenID = TokenId::Identifier; break;
case IdentPrefix::Period:
if (mLine[mRun]==':')
mTokenID = TokenId::Label;
else
mTokenID = TokenId::Directive;
break;
default:
if (Keywords.contains(s))
mTokenID = TokenId::Instruction;
else if (Registers.contains(s))
mTokenID = TokenId::Register;
else if (mLine[mRun]==':')
mTokenID = TokenId::Label;
else
mTokenID = TokenId::Identifier;
} }
} }
@ -206,7 +249,8 @@ void ASMHighlighter::StringProc()
mTokenID = TokenId::String; mTokenID = TokenId::String;
if ((mRun+2 < mLineString.size()) && (mLine[mRun + 1] == '\"') && (mLine[mRun + 2] == '\"')) if ((mRun+2 < mLineString.size()) && (mLine[mRun + 1] == '\"') && (mLine[mRun + 2] == '\"'))
mRun += 2; mRun += 2;
mRun+=1; else
mRun+=1;
while (true) { while (true) {
if (mLine[mRun] == 0 || mLine[mRun] == '\r' || mLine[mRun] == '\n') if (mLine[mRun] == 0 || mLine[mRun] == '\r' || mLine[mRun] == '\n')
break; break;
@ -230,6 +274,20 @@ void ASMHighlighter::UnknownProc()
mTokenID = TokenId::Unknown; mTokenID = TokenId::Unknown;
} }
bool ASMHighlighter::isIdentStartChar(const QChar &ch)
{
if (ch == '_') {
return true;
}
if ((ch>='a') && (ch <= 'z')) {
return true;
}
if ((ch>='A') && (ch <= 'Z')) {
return true;
}
return false;
}
bool ASMHighlighter::eol() const bool ASMHighlighter::eol() const
{ {
return mTokenID == TokenId::Null; return mTokenID == TokenId::Null;
@ -257,8 +315,14 @@ PHighlighterAttribute ASMHighlighter::getTokenAttribute() const
return mCommentAttribute; return mCommentAttribute;
case TokenId::Identifier: case TokenId::Identifier:
return mIdentifierAttribute; return mIdentifierAttribute;
case TokenId::rainbow: case TokenId::Instruction:
return mKeywordAttribute; return mKeywordAttribute;
case TokenId::Directive:
return mDirectiveAttribute;
case TokenId::Label:
return mLabelAttribute;
case TokenId::Register:
return mRegisterAttribute;
case TokenId::Number: case TokenId::Number:
return mNumberAttribute; return mNumberAttribute;
case TokenId::Space: case TokenId::Space:
@ -313,6 +377,19 @@ void ASMHighlighter::next()
CommentProc(); CommentProc();
break; break;
case '.': case '.':
if (isIdentChar(mLine[mRun+1])) {
mRun++;
IdentProc(IdentPrefix::Period);
} else
SymbolProc();
break;
case '%':
if (isIdentChar(mLine[mRun+1])) {
mRun++;
IdentProc(IdentPrefix::Percent);
} else
UnknownProc();
break;
case ':': case ':':
case '&': case '&':
case '{': case '{':
@ -329,10 +406,8 @@ void ASMHighlighter::next()
default: default:
if (mLine[mRun]>='0' && mLine[mRun]<='9') { if (mLine[mRun]>='0' && mLine[mRun]<='9') {
NumberProc(); NumberProc();
} else if ((mLine[mRun]>='A' && mLine[mRun]<='Z') } else if (isIdentChar(mLine[mRun])) {
|| (mLine[mRun]>='a' && mLine[mRun]<='z') IdentProc(IdentPrefix::None);
|| (mLine[mRun]=='_')) {
IdentProc();
} else if (mLine[mRun]<=32) { } else if (mLine[mRun]<=32) {
SpaceProc(); SpaceProc();
} else { } else {
@ -384,4 +459,14 @@ QSet<QString> ASMHighlighter::keywords() const
{ {
return Keywords; return Keywords;
} }
const PHighlighterAttribute &ASMHighlighter::directiveAttribute() const
{
return mDirectiveAttribute;
}
const PHighlighterAttribute &ASMHighlighter::labelAttribute() const
{
return mLabelAttribute;
}
} }

View File

@ -26,7 +26,10 @@ class ASMHighlighter : public Highlighter
enum class TokenId { enum class TokenId {
Comment, Comment,
Identifier, Identifier,
rainbow, // add mov etc Instruction, // add mov etc
Directive, // .section .data etc
Label,
Register, //EAX EBX etc
Null, Null,
Number, Number,
Space, Space,
@ -34,11 +37,21 @@ class ASMHighlighter : public Highlighter
Symbol, Symbol,
Unknown Unknown
}; };
enum class IdentPrefix {
None,
Period,
Percent
};
public: public:
explicit ASMHighlighter(); explicit ASMHighlighter();
PHighlighterAttribute numberAttribute(); const PHighlighterAttribute &numberAttribute() const;
const PHighlighterAttribute &directiveAttribute() const;
const PHighlighterAttribute &labelAttribute() const;
const PHighlighterAttribute &registerAttribute() const;
static const QSet<QString> Keywords; static const QSet<QString> Keywords;
static const QSet<QString> Registers;
private: private:
QChar* mLine; QChar* mLine;
QString mLineString; QString mLineString;
@ -49,12 +62,15 @@ private:
int mTokenPos; int mTokenPos;
TokenId mTokenID; TokenId mTokenID;
PHighlighterAttribute mNumberAttribute; PHighlighterAttribute mNumberAttribute;
PHighlighterAttribute mDirectiveAttribute;
PHighlighterAttribute mRegisterAttribute;
PHighlighterAttribute mLabelAttribute;
private: private:
void CommentProc(); void CommentProc();
void CRProc(); void CRProc();
void GreaterProc(); void GreaterProc();
void IdentProc(); void IdentProc(IdentPrefix prefix);
void LFProc(); void LFProc();
void LowerProc(); void LowerProc();
void NullProc(); void NullProc();
@ -65,7 +81,7 @@ private:
void StringProc(); void StringProc();
void SymbolProc(); void SymbolProc();
void UnknownProc(); void UnknownProc();
bool isIdentStartChar(const QChar& ch);
// SynHighlighter interface // SynHighlighter interface
public: public:
@ -88,11 +104,10 @@ public:
void setState(const HighlighterState& rangeState) override; void setState(const HighlighterState& rangeState) override;
void resetState() override; void resetState() override;
// SynHighlighter interface
public: public:
QSet<QString> keywords() const override; QSet<QString> keywords() const override;
const PHighlighterAttribute &directiveAttribute() const;
const PHighlighterAttribute &labelAttribute() const;
}; };
} }