work save

- add: cpu window blend mode
 - fix: asm parser can't correctly parse numbers
 - fix: disassembly code in the cpu window not correctly updated
This commit is contained in:
royqh1979@gmail.com 2021-08-13 11:18:42 +08:00
parent 7d30690227
commit 34dd3eb474
18 changed files with 376 additions and 52 deletions

View File

@ -17,8 +17,8 @@ SOURCES += \
compiler/filecompiler.cpp \
compiler/stdincompiler.cpp \
parser/cpppreprocessor.cpp \
parser/parserutils.cpp \
parser/statementmodel.cpp \
parser/utils.cpp \
qsynedit/Search.cpp \
qsynedit/SearchBase.cpp \
qsynedit/SearchRegex.cpp \
@ -77,8 +77,8 @@ HEADERS += \
compiler/filecompiler.h \
compiler/stdincompiler.h \
parser/cpppreprocessor.h \
parser/parserutils.h \
parser/statementmodel.h \
parser/utils.h \
qsynedit/Search.h \
qsynedit/SearchBase.h \
qsynedit/SearchRegex.h \

View File

@ -774,7 +774,8 @@ void DebugReader::handleDisassembly()
s = getNextLine();
// Add lines of disassembly
while (!s.isEmpty() && (s != "End of assembler dump.")) {
while (s != "End of assembler dump.") {
if(!s.isEmpty())
mDisassembly.append(s);
s = getNextLine();
}

View File

@ -12,7 +12,7 @@
#include "common.h"
#include "colorscheme.h"
#include "iconsmanager.h"
#include "parser/utils.h"
#include "parser/parserutils.h"
Settings* createAppSettings(const QString& filepath = QString()) {
QString filename;
@ -44,7 +44,7 @@ Settings* createAppSettings(const QString& filepath = QString()) {
return nullptr;
}
new Settings(filename);
return new Settings(filename);
}
int main(int argc, char *argv[])

View File

@ -1,6 +1,7 @@
#include "cpppreprocessor.h"
#include "../utils.h"
#include <QFile>
#include <QTextCodec>
CppPreprocessor::CppPreprocessor(QObject *parent) : QObject(parent)
@ -46,9 +47,47 @@ void CppPreprocessor::addDefineByParts(const QString &name, const QString &args,
}
}
void CppPreprocessor::getDefineParts(const QString &Input, QString &name, QString &args, QString &value)
void CppPreprocessor::getDefineParts(const QString &input, QString &name, QString &args, QString &value)
{
QString s = input.trimmed();
name = "";
args = "";
value = "";
// Rules:
// When the character before the first opening brace is nonblank, a function is defined.
// After that point, switch from name to args
// The value starts after the first blank character outside of the outermost () pair
int i = 0;
int level = 0;
bool isFunction = false;
int argStart = 0;
while (i < s.length()) {
// When we find the first opening brace, check if this is a function define
if (s[i] == '(') {
level++;
if ((level == 1) && (!isFunction)) { // found a function define!
name = s.mid(0,i);
argStart = i;
isFunction = true;
}
} else if (s[i]==')') {
level--;
} else if (isSpaceChar(s[i]) && (level == 0)) {
break;
}
i++;
}
if (isFunction) {
// Name has already been found
args = s.mid(argStart,i-argStart);
//todo: expand macro (if already have)
} else {
name = s.mid(0,i);
args = "";
}
value = removeGCCAttributes(s.mid(i+1).trimmed());
}
void CppPreprocessor::addDefineByLine(const QString &line, bool hardCoded)
@ -65,6 +104,134 @@ void CppPreprocessor::addDefineByLine(const QString &line, bool hardCoded)
addDefineByParts(name, args, value, hardCoded);
}
PDefine CppPreprocessor::getDefine(const QString &name)
{
return mDefines.value(name,PDefine());
}
PDefine CppPreprocessor::getHardDefine(const QString &name)
{
return mHardDefines.value(name,PDefine());
}
void CppPreprocessor::reset()
{
mResult.clear();
// Clear extracted data
mIncludes.clear();
mBranchResults.clear();
mCurrentIncludes.reset();
mProcessed.clear();
resetDefines(); // do not throw away hardcoded
}
void CppPreprocessor::resetDefines()
{
mDefines.clear();
mDefines.insert(mHardDefines);
}
void CppPreprocessor::setScanOptions(bool parseSystem, bool parseLocal)
{
mParseSystem = parseSystem;
mParseLocal=parseLocal;
}
void CppPreprocessor::setIncludePaths(QStringList list)
{
mIncludePaths = list;
}
void CppPreprocessor::setProjectIncludePaths(QStringList list)
{
mProjectIncludePaths = list;
}
void CppPreprocessor::setScannedFileList(std::shared_ptr<QSet<QString> > list)
{
mScannedFiles = list;
}
void CppPreprocessor::setIncludesList(std::shared_ptr<QHash<QString, PFileIncludes> > list)
{
mIncludesList = list;
}
void CppPreprocessor::preprocess(const QString &fileName, QStringList buffer)
{
mFileName = fileName;
reset();
openInclude(fileName, buffer);
// StringsToFile(mBuffer,"f:\\buffer.txt");
preprocessBuffer();
// StringsToFile(mBuffer,"f:\\buffer.txt");
// StringsToFile(mResult,"f:\\log.txt");
}
void CppPreprocessor::invalidDefinesInFile(const QString &fileName)
{
PDefineMap defineMap = mFileDefines.value(fileName,PDefineMap());
if (defineMap) {
for (PDefine define:*defineMap) {
PDefine p = mDefines.value(define->name);
if (p == define) {
mDefines.remove(define->name);
}
}
mFileDefines.remove(fileName);
}
}
void CppPreprocessor::dumpDefinesTo(const QString &fileName)
{
QFile file(fileName);
if (file.open(QIODevice::WriteOnly|QIODevice::Truncate)) {
QTextStream stream(&file);
for (PDefine define:mDefines) {
stream<<QString("%1 %2 %3 %4\n").arg(define->name)
.arg(define->args).arg(define->value)
.arg(define->hardCoded)<<Qt::endl;
}
}
}
void CppPreprocessor::dumpIncludesListTo(const QString &fileName)
{
QFile file(fileName);
if (file.open(QIODevice::WriteOnly|QIODevice::Truncate)) {
QTextStream stream(&file);
for (PFileIncludes fileIncludes:*mIncludesList) {
stream<<fileIncludes->baseFile<<" : "<<Qt::endl;
stream<<"\t**includes:**"<<Qt::endl;
for (QString s:fileIncludes->includeFiles.keys()) {
stream<<"\t--"+s<<Qt::endl;
}
stream<<"\t**depends on:**"<<Qt::endl;
for (QString s:fileIncludes->dependingFiles) {
stream<<"\t^^"+s<<Qt::endl;
}
stream<<"\t**depended by:**"<<Qt::endl;
for (QString s:fileIncludes->dependedFiles) {
stream<<"\t&&"+s<<Qt::endl;
}
stream<<"\t**using:**"<<Qt::endl;
for (QString s:fileIncludes->usings) {
stream<<"\t++"+s<<Qt::endl;
}
stream<<"\t**statements:**"<<Qt::endl;
for (std::weak_ptr<Statement> p:fileIncludes->statements) {
PStatement statement = p.lock();
if (statement) {
stream<<QString("\t**%1 , %2").arg(statement->command)
.arg(statement->fullName)<<Qt::endl;
}
}
}
}
}
QString CppPreprocessor::getNextPreprocessor()
{
@ -114,8 +281,7 @@ void CppPreprocessor::handleBranch(const QString &line)
} else {
constexpr int IFDEF_LEN = 5; //length of ifdef;
QString name = line.mid(IFDEF_LEN).trimmed();
int dummy;
setCurrentBranch( getDefine(name,dummy)!=nullptr );
setCurrentBranch( getDefine(name)!=nullptr );
}
} else if (line.startsWith("ifndef")) {
@ -131,8 +297,7 @@ void CppPreprocessor::handleBranch(const QString &line)
} else {
constexpr int IFNDEF_LEN = 6; //length of ifndef;
QString name = line.mid(IFNDEF_LEN).trimmed();
int dummy;
setCurrentBranch( getDefine(name,dummy)==nullptr );
setCurrentBranch( getDefine(name)==nullptr );
}
} else if (line.startsWith("if")) {
// // if a branch that is not at our level is false, current branch is false too;
@ -217,10 +382,9 @@ void CppPreprocessor::handleUndefine(const QString &line)
constexpr int UNDEF_LEN = 5;
QString name = line.mid(UNDEF_LEN).trimmed();
int index;
// //may be defined many times
// while (true) {
PDefine define = getDefine(name, index);
PDefine define = getDefine(name);
if (define) {
//remove the define from defines set
mDefines.remove(name);
@ -288,8 +452,7 @@ void CppPreprocessor::expandMacro(const QString &line, QString &newLine, QString
}
}
} else {
int index;
PDefine define = getDefine(word,index);
PDefine define = getDefine(word);
if (define && define->args=="" ) {
//newLine:=newLine+RemoveGCCAttributes(define^.Value);
if (define->value != word )
@ -441,7 +604,7 @@ void CppPreprocessor::openInclude(const QString &fileName, QStringList bufferedT
//mCurrentIncludes->scopes;
//mCurrentIncludes->dependedFiles;
//mCurrentIncludes->dependingFiles;
mIncludesList.insert(fileName,mCurrentIncludes);
mIncludesList->insert(fileName,mCurrentIncludes);
}
parsedFile->fileIncludes = mCurrentIncludes;
@ -529,6 +692,11 @@ bool CppPreprocessor::getCurrentBranch()
return true;
}
void CppPreprocessor::setCurrentBranch(bool value)
{
mBranchResults.append(value);
}
void CppPreprocessor::removeCurrentBranch()
{
if (mBranchResults.size()>0)
@ -542,7 +710,7 @@ QStringList CppPreprocessor::getResult()
PFileIncludes CppPreprocessor::getFileIncludesEntry(const QString &fileName)
{
return mIncludesList.value(fileName,PFileIncludes());
return mIncludesList->value(fileName,PFileIncludes());
}
void CppPreprocessor::addDefinesInFile(const QString &fileName)
@ -921,8 +1089,7 @@ QString CppPreprocessor::expandDefines(QString line)
tail++;
}
name = line.mid(defineStart, defineEnd - defineStart);
int dummy;
PDefine define = getDefine(name,dummy);
PDefine define = getDefine(name);
QString insertValue;
if (!define) {
insertValue = "0";
@ -937,8 +1104,7 @@ QString CppPreprocessor::expandDefines(QString line)
} else {
// We have found a regular define. Replace it by its value
// Does it exist in the database?
int dummy;
PDefine define = getDefine(name,dummy);
PDefine define = getDefine(name);
QString insertValue;
if (!define) {
insertValue = "0";

View File

@ -3,7 +3,7 @@
#include <QObject>
#include <QTextStream>
#include "utils.h"
#include "parserutils.h"
#define MAX_DEFINE_EXPAND_DEPTH 20
@ -37,20 +37,22 @@ public:
void clear();
void addDefineByParts(const QString& name, const QString& args,
const QString& value, bool hardCoded);
void getDefineParts(const QString& Input, QString &name, QString &args, QString &value);
void getDefineParts(const QString& input, QString &name, QString &args, QString &value);
void addDefineByLine(const QString& line, bool hardCoded);
PDefine getDefine(const QString& name, int &index);
PDefine getHardDefine(const QString& name, int &index);
PDefine getDefine(const QString& name);
PDefine getHardDefine(const QString& name);
void reset(); //reset but don't clear generated defines
void resetDefines();
void setScanOptions(bool parseSystem, bool parseLocal);
void setIncludePaths(QStringList &list);
void setProjectIncludePaths(QStringList& list);
void setScannedFileList(QStringList &list);
void setIncludesList(QString& list);
void preprocessStream(const QString& fileName, QTextStream stream = QTextStream());
void preprocessFile(const QString& fileName);
void setIncludePaths(QStringList list);
void setProjectIncludePaths(QStringList list);
void setScannedFileList(std::shared_ptr<QSet<QString>> list);
void setIncludesList(std::shared_ptr<QHash<QString,PFileIncludes>> list);
void preprocess(const QString& fileName, QStringList buffer = QStringList());
void invalidDefinesInFile(const QString& fileName);
void dumpDefinesTo(const QString& fileName);
void dumpIncludesListTo(const QString& fileName);
signals:
private:
@ -153,7 +155,7 @@ private:
QStringList mResult;
PFileIncludes mCurrentIncludes;
int mPreProcIndex;
QHash<QString,PFileIncludes> mIncludesList;
std::shared_ptr<QHash<QString,PFileIncludes>> mIncludesList;
DefineMap mHardDefines; // set by "cpp -dM -E -xc NUL"
DefineMap mDefines; // working set, editable
QHash<QString, PDefineMap> mFileDefines; //dictionary to save defines for each headerfile;

View File

@ -1,4 +1,4 @@
#include "utils.h"
#include "parserutils.h"
#include <QDir>
#include <QFile>
@ -297,3 +297,33 @@ QString getSystemHeaderFileName(const QString &fileName, const QStringList& incl
//not found
return "";
}
bool isSystemHeaderFile(const QString &fileName, const QStringList &includePaths)
{
if (includePaths.isEmpty())
return false;
bool isFullName = false;
#ifdef Q_OS_WIN
isFullName = fileName.length()>2 && fileName[1]==':';
#else
isFullName = fileName.startsWith("\"");
#endif
if (isFullName) {
// If it's a full file name, check if its directory is an include path
QFileInfo info(fileName);
if (info.exists()) { // full file name
QDir dir = info.dir();
QString absPath = dir.absolutePath();
if (includePaths.indexOf(absPath)>=0)
return true;
}
} else {
//check if it's in the include dir
for (QString includePath: includePaths) {
QDir dir(includePath);
if (dir.exists(fileName))
return true;
}
}
return false;
}

View File

@ -168,4 +168,5 @@ QString getHeaderFileName(const QString& relativeTo, const QString& line,
QString getLocalHeaderFileName(const QString& relativeTo, const QString& fileName);
QString getSystemHeaderFileName(const QString& fileName, const QStringList& includePaths);
bool isSystemHeaderFile(const QString& fileName, const QStringList& includePaths);
#endif // PARSER_UTILS_H

View File

@ -3,7 +3,7 @@
#include <QObject>
#include <QTextStream>
#include "utils.h"
#include "parserutils.h"
class StatementModel : public QObject
{

View File

@ -125,7 +125,7 @@ void SynEditASMHighlighter::NumberProc()
mTokenID = TokenKind::Number;
while (true) {
QChar ch = mLine[mRun];
if (!((ch>=0 && ch<=9) || (ch=='.') || (ch >= 'a' && ch<='f')
if (!((ch>='0' && ch<='9') || (ch=='.') || (ch >= 'a' && ch<='f')
|| (ch=='h') || (ch >= 'A' && ch<='F') || (ch == 'H')))
break;
mRun++;

View File

@ -2308,6 +2308,16 @@ void Settings::Debugger::setFontName(const QString &fontName)
mFontName = fontName;
}
bool Settings::Debugger::blendMode() const
{
return mBlendMode;
}
void Settings::Debugger::setBlendMode(bool blendMode)
{
mBlendMode = blendMode;
}
bool Settings::Debugger::useIntelStyle() const
{
return mUseIntelStyle;
@ -2345,7 +2355,8 @@ void Settings::Debugger::doSave()
saveValue("font_name",mFontName);
saveValue("only_show_mono",mOnlyShowMono);
saveValue("font_size",mFontSize);
boolValue("use_intel_style",mUseIntelStyle);
saveValue("use_intel_style",mUseIntelStyle);
saveValue("blend_mode",mBlendMode);
}
void Settings::Debugger::doLoad()
@ -2356,6 +2367,7 @@ void Settings::Debugger::doLoad()
mOnlyShowMono = boolValue("only_show_mono",true);
mFontSize = intValue("font_size",10);
mUseIntelStyle = boolValue("use_intel_style",true);
mBlendMode = boolValue("blend_mode",true);
}
Settings::History::History(Settings *settings):_Base(settings, SETTING_HISTORY)

View File

@ -429,6 +429,9 @@ public:
QString fontName() const;
void setFontName(const QString &fontName);
bool blendMode() const;
void setBlendMode(bool blendMode);
private:
bool mShowCommandLog;
bool mShowAnnotations;
@ -436,6 +439,7 @@ public:
bool mOnlyShowMono;
int mFontSize;
bool mUseIntelStyle;
bool mBlendMode;
// _Base interface
protected:

View File

@ -27,6 +27,7 @@ void DebugGeneralWidget::doLoad()
} else {
ui->rbATT->setChecked(true);
}
ui->chkBlendMode->setChecked(pSettings->debugger().blendMode());
}
void DebugGeneralWidget::doSave()
@ -37,6 +38,7 @@ void DebugGeneralWidget::doSave()
pSettings->debugger().setShowCommandLog(ui->chkShowLog->isChecked());
pSettings->debugger().setShowAnnotations(ui->chkShowFullAnnotation->isChecked());
pSettings->debugger().setUseIntelStyle(ui->rbIntel->isChecked());
pSettings->debugger().setBlendMode(ui->chkBlendMode->isChecked());
pSettings->debugger().save();
pMainWindow->updateDebuggerSettings();

View File

@ -156,6 +156,61 @@
<property name="bottomMargin">
<number>11</number>
</property>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>CPU Window</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QWidget" name="widget_3" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Disassembly Coding Style:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_4" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="rbIntel">
<property name="text">
@ -179,6 +234,19 @@
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="chkBlendMode">
<property name="text">
<string>Show disassembly code in blend mode</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View File

@ -489,3 +489,14 @@ QStringList ReadFileToLines(const QString &fileName)
}
return result;
}
void StringsToFile(const QStringList &list, const QString &fileName)
{
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream stream(&file);
for (QString s:list) {
stream<<s<<Qt::endl;
}
}
}

View File

@ -93,6 +93,7 @@ void TextToLines(const QString& text, LineProcessFunc lineFunc);
QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec);
QStringList ReadFileToLines(const QString& fileName);
void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc);
void StringsToFile(const QStringList& list, const QString& fileName);
void decodeKey(int combinedKey, int& key, Qt::KeyboardModifiers& modifiers);
void inflateRect(QRect& rect, int delta);

View File

@ -4,24 +4,31 @@
#include "../mainwindow.h"
#include "../debugger.h"
#include "../settings.h"
#include "../colorscheme.h"
CPUDialog::CPUDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CPUDialog)
{
setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
ui->setupUi(this);
ui->txtCode->setHighlighter(highlighterManager.getAsmHighlighter());
ui->txtCode->setHighlighter(highlighterManager.getCppHighlighter());
highlighterManager.applyColorScheme(ui->txtCode->highlighter(),
pSettings->editor().colorScheme());
PColorSchemeItem item = pColorManager->getItem(pSettings->editor().colorScheme(),COLOR_SCHEME_ACTIVE_LINE);
if (item) {
ui->txtCode->setActiveLineColor(item->background());
}
ui->lstRegister->setModel(pMainWindow->debugger()->registerModel());
ui->rdIntel->setChecked(true);
ui->rdIntel->setChecked(pSettings->debugger().useIntelStyle());
ui->chkBlendMode->setChecked(pSettings->debugger().blendMode());
// RadioATT.Checked := devData.UseATTSyntax;
// RadioIntel.Checked := not devData.UseATTSyntax;
// fRegisters := TList.Create;
// fAssembler := TStringList.Create;
updateInfo();
//updateInfo();
}
CPUDialog::~CPUDialog()
@ -35,6 +42,9 @@ void CPUDialog::updateInfo()
// Load the registers..
sendSyntaxCommand();
pMainWindow->debugger()->sendCommand("info", "registers");
if (ui->chkBlendMode->isChecked())
pMainWindow->debugger()->sendCommand("disas", "/s");
else
pMainWindow->debugger()->sendCommand("disas", "");
}
}
@ -45,6 +55,7 @@ void CPUDialog::setDisassembly(const QStringList &lines)
ui->txtFunctionName->setText(lines[0]);
}
int activeLine = -1;
ui->txtCode->lines()->clear();
for (int i=1;i<lines.size();i++) {
QString line = lines[i];
if (line.startsWith("=>")) {
@ -85,3 +96,10 @@ void CPUDialog::on_rdATT_toggled(bool)
pSettings->debugger().setUseIntelStyle(ui->rdIntel->isChecked());
pSettings->debugger().save();
}
void CPUDialog::on_chkBlendMode_stateChanged(int arg1)
{
updateInfo();
pSettings->debugger().setBlendMode(ui->chkBlendMode->isCheckable());
pSettings->debugger().save();
}

View File

@ -28,6 +28,7 @@ protected:
private slots:
void on_rdIntel_toggled(bool checked);
void on_rdATT_toggled(bool checked);
void on_chkBlendMode_stateChanged(int arg1);
};
#endif // CPUDIALOG_H

View File

@ -143,6 +143,13 @@
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="chkBlendMode">
<property name="text">
<string>Blend Mode</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>