From 81da56891cc908c57ce99828c8f13288d86c0600 Mon Sep 17 00:00:00 2001 From: Midas_ Date: Fri, 25 Jun 2021 15:42:27 +0200 Subject: [PATCH] * Added new variable WORKSPACE_ROOT in settings * Added support for building the project in its directory and outputting the files in a build directory * Added light support for debugging multiple files (you can debug a file that includes other files, but the debugger does not jump into the other file) * Fixed a Bug where the input would not work if you debugged the program instead or running it --- .gitignore | 13 + assembler.h | 267 ++- debugger.cpp | 1360 +++++++-------- debugger.h | 8 + fasm.cpp | 1193 ++++++++----- fasm.h | 43 +- gas.cpp | 1076 +++++++----- gas.h | 40 +- mainwindow.cpp | 4329 ++++++++++++++++++++++++------------------------ mainwindow.h | 459 ++--- masm.cpp | 1282 +++++++++----- masm.h | 38 +- nasm.cpp | 1250 +++++++++----- nasm.h | 40 +- 14 files changed, 6451 insertions(+), 4947 deletions(-) diff --git a/.gitignore b/.gitignore index bcf4163d..475b2b13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,21 @@ +# Ignore files with no extensions +* +!*/ +!*.* + +# VSCode +.vscode/ + # Qt # ###################### *.pro.user *.pro.user.* moc_*.cpp +moc_*.h qrc_*.cpp Makefile *-build-* +ui_settings.h # OS generated files # ###################### @@ -20,3 +30,6 @@ Thumbs.db doc/* .qmake.stash sasm.app + +# Build output +*.o \ No newline at end of file diff --git a/assembler.h b/assembler.h index 18e8cc97..b0fc9091 100644 --- a/assembler.h +++ b/assembler.h @@ -41,18 +41,19 @@ #ifndef ASSEMBLER_H #define ASSEMBLER_H -#include -#include +#include #include +#include +#include +#include #include -#include +#include +#include #include #include -#include -#include -#include -#include "common.h" + #include "codeeditor.h" +#include "common.h" /** * @file assembler.h @@ -67,176 +68,154 @@ * */ -class Assembler : public QObject -{ - Q_OBJECT -public: - /*! - * \brief Struct for setting correspondence between - * program text line numbers and addresses in memory - */ - struct LineNum { - //! Program text line number - quint64 numInCode; - //! Address of instruction on this line in memory - quint64 numInMem; - bool operator ==(const LineNum& ln) - { - return ln.numInCode == numInCode; - } - }; - /*! - * \brief Struct for setting pattern's highlighting rules - */ - struct HighlightingRule - { - HighlightingRule() : isComment(false) { - } - //! Pattern to highlight - QRegExp pattern; - //! Highlighting format - foreground color, background color, bold style and etc. - QTextCharFormat format; - bool isComment; - }; - bool x86; - - //! Assembler constructor. Note that this is the stage where x86 is determined. - explicit Assembler(bool x86, QObject *parent = 0); - - //! Return the default path to the assembler. - virtual QString getAssemblerPath() = 0; - - //! Returns the default path to the linker. - virtual QString getLinkerPath() = 0; - - /*! - * \brief Get entry point offset in object file. - * \param lst listing file - * \param entryLabel entry point label name - main or start - * \return entry point address in object file - */ - virtual quint64 getMainOffset(QFile &lst, QString entryLabel) = 0; - - /*! - * \brief Parses the listing file \a lst and fills vector \a lines with results of parsing - * \param lst listing file - * \param lines vector with info to fill - * \param offset difference between address of instruction in object file - * and address of instruction in memory - */ - virtual void parseLstFile(QFile &lst, - QVector &lines, - quint64 offset) = 0; - - /*! - * \brief Sets highlighting for assembly listing - * \param highlightingRules highlighting rules to fill - * \param formats formats for different types of highlighted expressions - * (see NASM, MASM, FASM, GAS as examples) - * \param multiLineComments is needed to support multiline comments - * \param commentStartExpression multiline comment start ("/" + "*" in C for example) - * \param commentEndExpression multiline comment end ("*" + "/" in C for example) - */ - virtual void fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression) = 0; - - //! Returns the default start text (default project code) - virtual QString getStartText() = 0; - - //! Puts the debug string that makes frame (mov ebp, esp) - virtual void putDebugString(CodeEditor *code) = 0; - - //! Returns the default assembler options - virtual QString getAssemblerOptions() = 0; - - //! Returns the default linker options - virtual QString getLinkerOptions() = 0; - - //! Determines if the system is x86 - bool isx86(); - -signals: - -public slots: - +class Assembler : public QObject { + Q_OBJECT + public: + /*! + * \brief Struct for setting correspondence between + * program text line numbers and addresses in memory + */ + struct LineNum { + //! Program text line number + quint64 numInCode; + //! Address of instruction on this line in memory + quint64 numInMem; + bool operator==(const LineNum& ln) { return ln.numInCode == numInCode; } + }; + /*! + * \brief Struct for setting pattern's highlighting rules + */ + struct HighlightingRule { + HighlightingRule() : isComment(false) {} + //! Pattern to highlight + QRegExp pattern; + //! Highlighting format - foreground color, background color, bold style and etc. + QTextCharFormat format; + bool isComment; + }; + bool x86; + + //! Assembler constructor. Note that this is the stage where x86 is determined. + explicit Assembler(bool x86, QObject* parent = 0); + + //! Return the default path to the assembler. + virtual QString getAssemblerPath() = 0; + + //! Returns the default path to the linker. + virtual QString getLinkerPath() = 0; + + /*! + * \brief Get entry point offset in object file. + * \param lst listing file + * \param entryLabel entry point label name - main or start + * \return entry point address in object file + */ + virtual quint64 getMainOffset(QFile& lst, QString entryLabel) = 0; + + /*! + * \brief Parses the listing file + * \a lst and fills vector + * \a lines with results of parsing + * \param lst listing file + * \param programFilePath path to the main .asm file + * \param lines vector with info to fill + * \param offset difference between address of instruction in object + * file and address of instruction in memory + */ + virtual void parseLstFile(QFile& lst, QString& programFilePath, + QVector& lines, quint64 offset) = 0; + + /*! + * \brief Sets highlighting for assembly listing + * \param highlightingRules highlighting rules to fill + * \param formats formats for different types of highlighted expressions + * (see NASM, MASM, FASM, GAS as examples) + * \param multiLineComments is needed to support multiline comments + * \param commentStartExpression multiline comment start ("/" + "*" in C for example) + * \param commentEndExpression multiline comment end ("*" + "/" in C for example) + */ + virtual void fillHighligherRules( + QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, QRegExp& commentEndExpression) = 0; + + //! Returns the default start text (default project code) + virtual QString getStartText() = 0; + + //! Puts the debug string that makes frame (mov ebp, esp) + virtual void putDebugString(CodeEditor* code) = 0; + + //! Returns the default assembler options + virtual QString getAssemblerOptions() = 0; + + //! Returns the default linker options + virtual QString getLinkerOptions() = 0; + + //! Determines if the system is x86 + bool isx86(); + + signals: + + public slots: }; -#endif // ASSEMBLER_H - - - - - - - - - - - - - +#endif // ASSEMBLER_H /*! \mainpage SASM Dev Guide * * \section intro_sec Introduction * - * Below you will find what and where to modify appropriate header and source files when you want to add a feature. + * Below you will find what and where to modify appropriate header and source files when + * you want to add a feature. * * \section section1 Commenting * - * When commenting use doxygen's syntax. Place the comment above the intended line. After adding the feature, run - * doxygen.exe configfile to update the documentation. Be sure to double check the documentation to ensure the - * added comments were parsed correctly. + * When commenting use doxygen's syntax. Place the comment above the intended line. After + * adding the feature, run doxygen.exe configfile to update the documentation. Be sure to + * double check the documentation to ensure the added comments were parsed correctly. * * \section section2 Adding Assembler Support * - * Adding support is a relatively straight forward process. Each supported assembler is a derived Assembler and - * has its own header and cpp file. + * Adding support is a relatively straight forward process. Each supported assembler is a + * derived Assembler and has its own header and cpp file. * * \subsection step1 Step 1: Creating the header and cpp * - * The first step is to create the new header and cpp file for the assembler. These should be named all lowercase without gaps + * The first step is to create the new header and cpp file for the assembler. These should + * be named all lowercase without gaps * * \subsection step2 Step 2: Creating the assembler class * - * The decleration of the class may best be discussed in light of already supported assemblers. Take for example, NASM. The NASM - * class is defined as: - * class NASM : public Assembler + * The decleration of the class may best be discussed in light of already supported + * assemblers. Take for example, NASM. The NASM class is defined as: class NASM : public + * Assembler * * The generic definition is * class YOURASSEMBLER : public Assembler * - * The variables and methods of YOURASSEMBLER should be the virtual methods of Assembler. If you are unsure what to add, refer to - * the already supported assemler classes. You may copy and paste them. + * The variables and methods of YOURASSEMBLER should be the virtual methods of Assembler. + * If you are unsure what to add, refer to the already supported assemler classes. You may + * copy and paste them. * * \subsection step3 Step 3: Adding it to the Build Options * - * You should hopefully know enough QT to be able to add form controls. The code for modifying the build menu can be found in - * mainwindow.cpp. Refer to its documentation for more reference on where to add/modify code. + * You should hopefully know enough QT to be able to add form controls. The code for + * modifying the build menu can be found in mainwindow.cpp. Refer to its documentation for + * more reference on where to add/modify code. * * \section section3 Adding Language Support * * * \subsection help Help File * - * The help file, helpENG.html, needs to be translated and saved into a new help.html file. - * The - * void MainWindow::openHelp() - * must be modified to support the added language. This is done by adding another if statement. + * The help file, helpENG.html, needs to be translated and saved into a new help.html file. The void MainWindow::openHelp() must be modified to support the + * added language. This is done by adding another if statement. * * \subsection interface Interface language * - * New language_.ts file needs to be created and filled with translations using Qt Linguist. - * Compiled language_.qm and qt_.qm files need to be added in SASM folder. - * Support of new language needs to be added in settings (mainwindow.cpp) and in loading code (main.cpp). + * New language_.ts file needs to be created and filled with translations + * using Qt Linguist. Compiled language_.qm and qt_.qm files + * need to be added in SASM folder. Support of new language needs to be added in settings + * (mainwindow.cpp) and in loading code (main.cpp). */ - - - - - - - diff --git a/debugger.cpp b/debugger.cpp index bdca20da..795b18aa 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -46,738 +46,758 @@ */ namespace { - // read struct like { = , ,,, = } - // from stream. Values may be simple or complex, like {v1, v2, v3 .. } - // all i have to be simple, two-level complex values unsupported - bool readStruct(QTextStream& str, QMap* map); +// read struct like { = , ,,, = } +// from stream. Values may be simple or complex, like {v1, v2, v3 .. } +// all i have to be simple, two-level complex values unsupported +bool readStruct(QTextStream& str, QMap* map); +} // namespace + +Debugger::Debugger(QTextEdit* tEdit, const QString& exePathParam, + const QString& lstPathParam, const QString& programPathParam, + const QString& workingDirectoryPathParam, + const QString& inputPathParam, Assembler* assembler, QWidget* parent) + : QObject(parent) { + QSettings settings("SASM Project", "SASM"); + c = 0; + pid = 0; + firstAction = true; + textEdit = tEdit; + exePath = exePathParam; + lstPath = lstPathParam; + programPath = programPathParam; + workingDirectoryPath = workingDirectoryPathParam; + inputPath = inputPathParam; + registersOk = true; + this->assembler = assembler; +#ifdef Q_OS_WIN32 + QString gdb; + QString objdump; + if (settings.value("mode", QString("x86")).toString() == "x86") { + gdb = QCoreApplication::applicationDirPath() + "/MinGW/bin/gdb.exe"; + objdump = QCoreApplication::applicationDirPath() + "/MinGW/bin/objdump.exe"; + if (!QFile::exists(gdb)) + gdb = QCoreApplication::applicationDirPath() + "/Windows/MinGW/bin/gdb.exe"; + if (!QFile::exists(objdump)) + objdump = QCoreApplication::applicationDirPath() + "/Windows/MinGW/bin/objdump.exe"; + exitMessage = "mingw_CRTStartup"; + } else { + gdb = QCoreApplication::applicationDirPath() + "/MinGW64/bin/gdb.exe"; + objdump = QCoreApplication::applicationDirPath() + "/MinGW/bin/objdump.exe"; + if (!QFile::exists(gdb)) + gdb = QCoreApplication::applicationDirPath() + "/Windows/MinGW64/bin/gdb.exe"; + if (!QFile::exists(objdump)) + objdump = QCoreApplication::applicationDirPath() + "/Windows/MinGW/bin/objdump.exe"; + exitMessage = "__fu0__set_invalid_parameter_handler"; + } +#else + QString gdb = "gdb"; + QString objdump = "objdump"; + exitMessage = "libc_start_main"; +#endif + cExitMessage = QRegExp("\\[Inferior .* exited"); + + connect(this, SIGNAL(wasStopped()), this, SLOT(emitStarted())); + + // determine entry point + QProcess objdumpProcess; + QProcessEnvironment objdumpEnvironment = QProcessEnvironment::systemEnvironment(); + QStringList objdumpArguments; + objdumpArguments << "-f" << exePath; + objdumpEnvironment.insert("LC_MESSAGES", "en_US"); + objdumpProcess.setProcessEnvironment(objdumpEnvironment); + objdumpProcess.start(objdump, objdumpArguments); + objdumpProcess.waitForFinished(); + QString objdumpResult = QString(objdumpProcess.readAllStandardOutput()); + QString startAddress("start address "); + int index = objdumpResult.indexOf(startAddress); + objdumpResult = objdumpResult.mid(index + startAddress.length()); + entryPoint = objdumpResult.toLongLong(0, 16); + + QStringList arguments; + arguments << exePath; + + process = new QProcess; + // process->setWorkingDirectory(workingDirectoryPath); + process->start(gdb, arguments); + + QObject::connect(process, SIGNAL(readyReadStandardOutput()), this, + SLOT(readOutputToBuffer())); + QObject::connect(process, SIGNAL(readyReadStandardError()), this, + SLOT(readOutputToBuffer())); + + bufferTimer = new QTimer; + QObject::connect(bufferTimer, SIGNAL(timeout()), this, SLOT(processOutput()), + Qt::QueuedConnection); + bufferTimer->start(10); } - -Debugger::Debugger(QTextEdit *tEdit, - const QString &exePathParam, - const QString &workingDirectoryPathParam, - const QString &inputPathParam, - Assembler *assembler, - QWidget *parent) - : QObject(parent) -{ - QSettings settings("SASM Project", "SASM"); - c = 0; - pid = 0; - firstAction = true; - textEdit = tEdit; - exePath = exePathParam; - workingDirectoryPath = workingDirectoryPathParam; - inputPath = inputPathParam; - registersOk = true; - this->assembler = assembler; - #ifdef Q_OS_WIN32 - QString gdb; - QString objdump; - if (settings.value("mode", QString("x86")).toString() == "x86") { - gdb = QCoreApplication::applicationDirPath() + "/MinGW/bin/gdb.exe"; - objdump = QCoreApplication::applicationDirPath() + "/MinGW/bin/objdump.exe"; - if (! QFile::exists(gdb)) - gdb = QCoreApplication::applicationDirPath() + "/Windows/MinGW/bin/gdb.exe"; - if (! QFile::exists(objdump)) - objdump = QCoreApplication::applicationDirPath() + "/Windows/MinGW/bin/objdump.exe"; - exitMessage = "mingw_CRTStartup"; - } else { - gdb = QCoreApplication::applicationDirPath() + "/MinGW64/bin/gdb.exe"; - objdump = QCoreApplication::applicationDirPath() + "/MinGW/bin/objdump.exe"; - if (! QFile::exists(gdb)) - gdb = QCoreApplication::applicationDirPath() + "/Windows/MinGW64/bin/gdb.exe"; - if (! QFile::exists(objdump)) - objdump = QCoreApplication::applicationDirPath() + "/Windows/MinGW/bin/objdump.exe"; - exitMessage = "__fu0__set_invalid_parameter_handler"; - } - #else - QString gdb = "gdb"; - QString objdump = "objdump"; - exitMessage = "libc_start_main"; - #endif - cExitMessage = QRegExp("\\[Inferior .* exited"); - - connect(this, SIGNAL(wasStopped()), this, SLOT(emitStarted())); - - //determine entry point - QProcess objdumpProcess; - QProcessEnvironment objdumpEnvironment = QProcessEnvironment::systemEnvironment(); - QStringList objdumpArguments; - objdumpArguments << "-f" << exePath; - objdumpEnvironment.insert("LC_MESSAGES", "en_US"); - objdumpProcess.setProcessEnvironment(objdumpEnvironment); - objdumpProcess.start(objdump, objdumpArguments); - objdumpProcess.waitForFinished(); - QString objdumpResult = QString(objdumpProcess.readAllStandardOutput()); - QString startAddress("start address "); - int index = objdumpResult.indexOf(startAddress); - objdumpResult = objdumpResult.mid(index + startAddress.length()); - entryPoint = objdumpResult.toLongLong(0, 16); - - - QStringList arguments; - arguments << exePath; - - process = new QProcess; - process->start(gdb, arguments); - - QObject::connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutputToBuffer())); - QObject::connect(process, SIGNAL(readyReadStandardError()), this, SLOT(readOutputToBuffer())); - - bufferTimer = new QTimer; - QObject::connect(bufferTimer, SIGNAL(timeout()), this, SLOT(processOutput()), Qt::QueuedConnection); - bufferTimer->start(10); +void Debugger::emitStarted() { + disconnect(this, SIGNAL(wasStopped()), this, SLOT(emitStarted())); + emit started(); } -void Debugger::emitStarted() -{ - disconnect(this, SIGNAL(wasStopped()), this, SLOT(emitStarted())); - emit started(); +void Debugger::readOutputToBuffer() { + if (!process) return; + QByteArray error = process->readAllStandardError(); + errorBuffer += QString::fromLocal8Bit(error.constData(), error.size()); + QByteArray output = process->readAllStandardOutput(); + buffer += QString::fromLocal8Bit(output.constData(), output.size()); } -void Debugger::readOutputToBuffer() -{ - if (!process) - return; - QByteArray error = process->readAllStandardError(); - errorBuffer += QString::fromLocal8Bit(error.constData(), error.size()); - QByteArray output = process->readAllStandardOutput(); - buffer += QString::fromLocal8Bit(output.constData(), output.size()); +void Debugger::processOutput() { + bufferTimer->stop(); + int index = buffer.indexOf(QString("(gdb)")); + int linefeedIndex = errorBuffer.indexOf("\n"); + if (index != -1) { + // if whole message ready to processing (end of whole message is "(gdb)") + QString output = buffer.left(index); + QString error = errorBuffer.left(linefeedIndex); + buffer.remove(0, index + 5); // remove processed message + errorBuffer.remove(0, linefeedIndex + 1); + processMessage(output, error); + } + bufferTimer->start(10); } -void Debugger::processOutput() -{ - bufferTimer->stop(); - int index = buffer.indexOf(QString("(gdb)")); - int linefeedIndex = errorBuffer.indexOf("\n"); - if (index != -1) { //if whole message ready to processing (end of whole message is "(gdb)") - QString output = buffer.left(index); - QString error = errorBuffer.left(linefeedIndex); - buffer.remove(0, index + 5); //remove processed message - errorBuffer.remove(0, linefeedIndex + 1); - processMessage(output, error); +void Debugger::processMessage(QString output, QString error) { + if (error.indexOf("PC register is not available") != -1) { + emit printLog(tr("GDB error\n"), Qt::red); + emit finished(); + return; + } + if (c == 0) { // in start wait for printing of start gdb text like this: + /*GNU gdb (GDB) 7.4 + Copyright (C) 2012 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. Type "show copying" + and "show warranty" for details. + This GDB was configured as "i686-pc-mingw32". + For bug reporting instructions, please see: + ... + Reading symbols from + C:\Users\Dmitri\Dropbox\Projects\SASMstatic\release\Program\SASMprog.exe... done. + (gdb)*/ + c++; + doInput(QString("disas main\n"), none); + return; + } + + if (c == 1) { + if (error.indexOf("No symbol", 0, Qt::CaseInsensitive) != -1) { + dbgSymbols = false; + } else { + dbgSymbols = true; } - bufferTimer->start(10); -} - -void Debugger::processMessage(QString output, QString error) -{ - if (error.indexOf("PC register is not available") != -1) { - emit printLog(tr("GDB error\n"), Qt::red); - emit finished(); - return; + } + + if (dbgSymbols) { // debug symbols exists + if (c == 1 && output != " ") { + /*Dump of assembler code for function sasmStartL: + 0x00401390 <+0>: xor %eax,%eax + 0x00401392 <+2>: ret + 0x00401393 <+3>: add %dl,-0x77(%ebp) + End of assembler dump.*/ + // skip this information (for gdb 8.0) + c++; + run(); // perform Debugger::run(), that run program and open I/O files + return; } - if (c == 0) { //in start wait for printing of start gdb text like this: - /*GNU gdb (GDB) 7.4 - Copyright (C) 2012 Free Software Foundation, Inc. - License GPLv3+: GNU GPL version 3 or later - This is free software: you are free to change and redistribute it. - There is NO WARRANTY, to the extent permitted by law. Type "show copying" - and "show warranty" for details. - This GDB was configured as "i686-pc-mingw32". - For bug reporting instructions, please see: - ... - Reading symbols from C:\Users\Dmitri\Dropbox\Projects\SASMstatic\release\Program\SASMprog.exe... - done. - (gdb)*/ - c++; - doInput(QString("disas main\n"), none); - return; + + // determine run of program + // wait for message like this: Breakpoint 1, 0x00401390 in sasmStartL () + if (c == 2 && output.indexOf(QString(" in ")) != -1) { + // set accordance between program in memory and program in file + // in example we need 0x00401390 + + // count offset + QRegExp r = QRegExp("0x[0-9a-fA-F]{8,16}"); + int index = r.indexIn(output); + // take offset in hexadecimal representation (10 symbols) from string and convert it + // to int + offset = output.mid(index, r.matchedLength()).toULongLong(0, 16); + processLst(); // count accordance + + c++; + actionTypeQueue.enqueue(ni); + doInput("info inferiors\n", none); } + // if an error with the wrong name of the section has occurred + if ((c == 2 && output.indexOf(QString( + "Make breakpoint pending on future shared library load")) != -1) || + (c == 1 && output == " ")) { + actionTypeQueue.enqueue(anyAction); + processAction( + tr("An error has occurred in the debugger. Please check the names of the " + "sections.")); + QObject::disconnect(process, SIGNAL(readyReadStandardOutput()), this, + SLOT(readOutputToBuffer())); + emit finished(); + } + } else { // debug symbols does not exists (for example, non-gcc linker) if (c == 1) { - if (error.indexOf("No symbol",0,Qt::CaseInsensitive)!=-1) { - dbgSymbols = false; - } else { - dbgSymbols = true; - } + offset = entryPoint; // changes in processLst() + c++; + processLst(); // count accordance + run(); // perform Debugger::run(), that run program and open I/O files + return; } - if (dbgSymbols) { //debug symbols exists - if (c == 1 && output != " ") { - /*Dump of assembler code for function sasmStartL: - 0x00401390 <+0>: xor %eax,%eax - 0x00401392 <+2>: ret - 0x00401393 <+3>: add %dl,-0x77(%ebp) - End of assembler dump.*/ - //skip this information (for gdb 8.0) - c++; - run(); //perform Debugger::run(), that run program and open I/O files - return; - } + // determine run of program + // wait for message like this: Breakpoint 1, 0x00401390 in sasmStartL () + if (c == 2 && output.indexOf(QString(" in ")) != -1) { + c++; + actionTypeQueue.enqueue(ni); + doInput("info inferiors\n", none); + } + } + +// interrupt while debugging (program was stopped) +#ifdef Q_OS_WIN32 + QString interruptSig("SIGTRAP"); +#else + QString interruptSig("SIGINT"); +#endif + if (output.indexOf(interruptSig) != -1) { + stopped = true; + emit wasStopped(); + return; + } + + if (!pid) { + QRegExp r("Num +Description +Executable"); + int index = output.indexOf(r); + if (index != -1) { + QString processString("process "); + r = QRegExp(processString + "[0-9]+"); + index = output.indexOf(r); + output = output.mid(index + processString.length()); + output = output.split(QChar(' ')).at(0); + pid = output.toULongLong(0, 10); + return; + } + } - //determine run of program - //wait for message like this: Breakpoint 1, 0x00401390 in sasmStartL () - if (c == 2 && output.indexOf(QString(" in ")) != -1) { - //set accordance between program in memory and program in file - //in example we need 0x00401390 - - //count offset - QRegExp r = QRegExp("0x[0-9a-fA-F]{8,16}"); - int index = r.indexIn(output); - //take offset in hexadecimal representation (10 symbols) from string and convert it to int - offset = output.mid(index, r.matchedLength()).toULongLong(0, 16); - processLst(); //count accordance - - c++; - actionTypeQueue.enqueue(ni); - doInput("info inferiors\n", none); - } + // process all actions after start + if (c == 3) + if (output.indexOf(QString("$1 =")) == -1) // input file + processAction(output, error); +} - //if an error with the wrong name of the section has occurred - if ((c == 2 && output.indexOf(QString("Make breakpoint pending on future shared library load")) != -1) - || (c == 1 && output == " ")) { - actionTypeQueue.enqueue(anyAction); - processAction(tr("An error has occurred in the debugger. Please check the names of the sections.")); - QObject::disconnect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutputToBuffer())); - emit finished(); - } - } else { //debug symbols does not exists (for example, non-gcc linker) - if (c == 1) { - offset = entryPoint; //changes in processLst() - c++; - processLst(); //count accordance - run(); //perform Debugger::run(), that run program and open I/O files - return; - } +void Debugger::processAction(QString output, QString error) { + bool backtrace = (output.indexOf(QRegExp("#\\d+ 0x[0-9a-fA-F]{8,16} in .* ()")) != -1); + if (output.indexOf(exitMessage) != -1 && !backtrace) { + doInput("c\n", none); + return; + } + if (output.indexOf(QRegExp(cExitMessage)) != -1) { // if debug finished + // print output - message like bottom + /*Breakpoint 1, 0x08048510 in sasmStartL () + " + " Continuing. + abccba123 //program output + 567 //program output + [Inferior 1 (process 5693) exited normally] + " */ + + QRegExp continuingMsg("Continuing.\r?\n"); + QRegExp inferiorMsg("\\[Inferior "); + int continuingIndex = continuingMsg.indexIn(output); + int continuingLength = continuingMsg.matchedLength(); + int inferiorIndex = inferiorMsg.indexIn(output); + if (continuingIndex != -1) { + int outputLength = inferiorIndex - continuingIndex - continuingLength; + if (outputLength > 0) { + QString msg = output.mid(continuingIndex + continuingLength, + outputLength); // program output + emit printOutput(msg); + } + } - //determine run of program - //wait for message like this: Breakpoint 1, 0x00401390 in sasmStartL () - if (c == 2 && output.indexOf(QString(" in ")) != -1) { - c++; - actionTypeQueue.enqueue(ni); - doInput("info inferiors\n", none); + // exit from debugging + QObject::disconnect(process, SIGNAL(readyReadStandardOutput()), this, + SLOT(readOutputToBuffer())); + emit finished(); + return; + } + if (actionTypeQueue.isEmpty()) { + return; + } + DebugActionType actionType = actionTypeQueue.dequeue(); + + if (actionType == breakpoint) return; + + if (actionType == si || actionType == ni || actionType == showLine) { + // message is: line number + data + // print line number and other data if si or ni and print line number only if showLine + // scan line number in memory + QRegExp r = QRegExp("0x[0-9a-fA-F]{8,16}"); + int index = r.indexIn(output); + + // print output + if (index > 1 && !firstAction) { + QString msg = output.left(index); // left part - probably output of program; + msg.remove(0, 1); // remove first whitespace + QRegExp continuingMsg("Continuing.\r?\n"); + QRegExp breakpointMsg("\r?\nBreakpoint \\d+, "); + QRegExp threadMsg("\\[Switching to Thread [^\\]]*\\]\r?\n"); + QRegExp signalMsg("\r?\n(Program received signal.*)"); + msg.remove(continuingMsg); + msg.remove(breakpointMsg); + msg.remove(threadMsg); + if (signalMsg.indexIn(msg) != -1) { + QString recievedSignal = signalMsg.cap(1); + if (QRegExp("SIG(TRAP|INT)").indexIn(recievedSignal) == -1) { + emit printLog(recievedSignal, Qt::red); } + msg.remove(signalMsg); + } + emit printOutput(msg); } - - //interrupt while debugging (program was stopped) - #ifdef Q_OS_WIN32 - QString interruptSig("SIGTRAP"); - #else - QString interruptSig("SIGINT"); - #endif - if (output.indexOf(interruptSig) != -1) { - stopped = true; - emit wasStopped(); - return; + firstAction = false; + + quint64 lineNumber = output.mid(index, r.matchedLength()).toULongLong(0, 16); + // take line number in hexadecimal representation + //(10 symbols) in memory from string and convert it to int + + // find line number in accordance array and get number line in file with code + bool found = false; + for (int i = lines.count() - 1; i >= 0; i--) { + if (lineNumber == lines[i].numInMem) { + lineNumber = lines[i].numInCode; + found = true; + break; + } } - if (!pid) { - QRegExp r("Num +Description +Executable"); - int index = output.indexOf(r); - if (index != -1) { - QString processString("process "); - r = QRegExp(processString + "[0-9]+"); - index = output.indexOf(r); - output = output.mid(index + processString.length()); - output = output.split(QChar(' ')).at(0); - pid = output.toULongLong(0, 10); - return; - } + if (!found) { + // output = tr("Inside the macro or outside the program.") + '\n'; + emit inMacro(); + return; + } else { // if found highlight and print it + // highlight line number + emit highlightLine(lineNumber); + stopped = true; + emit wasStopped(); + + // print string number and all after it + // output = QString::number(lineNumber) + tr(" line") + + // output.mid(output.indexOf("()") + 2); + if (actionType == showLine) return; + output.remove(0, output.indexOf("()") + 2); } - - //process all actions after start - if (c == 3) - if (output.indexOf(QString("$1 =")) == -1) //input file - processAction(output, error); -} - -void Debugger::processAction(QString output, QString error) -{ - bool backtrace = (output.indexOf(QRegExp("#\\d+ 0x[0-9a-fA-F]{8,16} in .* ()")) != -1); - if (output.indexOf(exitMessage) != -1 && !backtrace) { - doInput("c\n", none); - return; + } + + if (actionType == anyAction) { + if (output[output.length() - 1] != '\n') output += QChar('\n'); + // process as ni or si + if (output.indexOf(QRegExp("0x[0-9a-fA-F]{8,16} in ")) != -1 && !backtrace) { + actionTypeQueue.enqueue(showLine); + processAction(output); } - if (output.indexOf(QRegExp(cExitMessage)) != -1) { //if debug finished - //print output - message like bottom - /*Breakpoint 1, 0x08048510 in sasmStartL () - " - " Continuing. - abccba123 //program output - 567 //program output - [Inferior 1 (process 5693) exited normally] - " */ - - QRegExp continuingMsg("Continuing.\r?\n"); - QRegExp inferiorMsg("\\[Inferior "); - int continuingIndex = continuingMsg.indexIn(output); - int continuingLength = continuingMsg.matchedLength(); - int inferiorIndex = inferiorMsg.indexIn(output); - if (continuingIndex != -1) { - int outputLength = inferiorIndex - continuingIndex - continuingLength; - if (outputLength > 0) { - QString msg = output.mid(continuingIndex + continuingLength, outputLength); //program output - emit printOutput(msg); - } + if (!error.isEmpty()) { + if (output != " \n") output = error + output; + else + output = error; + } + } + + if (actionType == infoMemory) { + bool isValid = false; + if (output.indexOf(QString("No symbol")) == -1 && + output.indexOf(QString("no debug info")) == -1 && output != QString(" ")) { + // if variable exists (isValid = true) + isValid = true; + int index = output.indexOf(QRegExp("\\$\\d+ = .*")); + if (index == -1) isValid = false; + else { + output = output.right(output.length() - index); + output = output.right(output.length() - output.indexOf(QChar('=')) - 1); + for (int i = output.size() - 1; i >= 0; i--) { + if (output[i].isSpace()) output.remove(i, 1); } - - //exit from debugging - QObject::disconnect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutputToBuffer())); - emit finished(); - return; + } } - if (actionTypeQueue.isEmpty()) { - return; + memoryInfo info; + if (isValid) info.value = output; + info.isValid = isValid; + watches.append(info); + if (watchesCount == watches.size()) { + emit printMemory(watches); + watches.clear(); } - DebugActionType actionType = actionTypeQueue.dequeue(); + return; + } - if (actionType == breakpoint) - return; - - if (actionType == si || actionType == ni || actionType == showLine) { - //message is: line number + data - //print line number and other data if si or ni and print line number only if showLine - //scan line number in memory - QRegExp r = QRegExp("0x[0-9a-fA-F]{8,16}"); - int index = r.indexIn(output); - - //print output - if (index > 1 && !firstAction) { - QString msg = output.left(index); //left part - probably output of program; - msg.remove(0, 1); //remove first whitespace - QRegExp continuingMsg("Continuing.\r?\n"); - QRegExp breakpointMsg("\r?\nBreakpoint \\d+, "); - QRegExp threadMsg("\\[Switching to Thread [^\\]]*\\]\r?\n"); - QRegExp signalMsg("\r?\n(Program received signal.*)"); - msg.remove(continuingMsg); - msg.remove(breakpointMsg); - msg.remove(threadMsg); - if (signalMsg.indexIn(msg) != -1) { - QString recievedSignal = signalMsg.cap(1); - if (QRegExp("SIG(TRAP|INT)").indexIn(recievedSignal) == -1) { - emit printLog(recievedSignal, Qt::red); - } - msg.remove(signalMsg); - } - emit printOutput(msg); - } - firstAction = false; - - quint64 lineNumber = output.mid(index, r.matchedLength()).toULongLong(0, 16); - //take line number in hexadecimal representation - //(10 symbols) in memory from string and convert it to int - - //find line number in accordance array and get number line in file with code - bool found = false; - for (int i = lines.count() - 1; i >= 0; i--) { - if (lineNumber == lines[i].numInMem) { - lineNumber = lines[i].numInCode; - found = true; - break; - } - } + if (actionType == infoRegisters) { + QTextStream registersStream(&output); + QList registers; + registersInfo info; + QSettings settings("SASM Project", "SASM"); - if (!found) { - //output = tr("Inside the macro or outside the program.") + '\n'; - emit inMacro(); - return; - } else { //if found highlight and print it - //highlight line number - emit highlightLine(lineNumber); - stopped = true; - emit wasStopped(); - - //print string number and all after it - //output = QString::number(lineNumber) + tr(" line") + output.mid(output.indexOf("()") + 2); - if (actionType == showLine) - return; - output.remove(0, output.indexOf("()") + 2); - } + QSet general; + QString ip; + QSet segment; + segment << "cs" + << "ds" + << "ss" + << "es" + << "fs" + << "gs"; + QSet flags; + flags << "eflags" + << "mxcsr"; + QSet fpu_info; + fpu_info << "fctrl" + << "fstat" + << "ftag" + << "fiseg" + << "fioff" + << "foseg" + << "fooff" + << "fop"; + QRegExp mmx("mm\\d+"); + QRegExp xmm("xmm\\d+"); + QRegExp ymm("ymm\\d+"); + QRegExp fpu_stack("st\\d+"); + + if (settings.value("mode", QString("x86")).toString() == "x86") { + // x86 + general << "eax" + << "ebx" + << "ecx" + << "edx" + << "esi" + << "edi" + << "esp" + << "ebp"; + ip = "eip"; + } else { + // x64 + general << "rax" + << "rbx" + << "rcx" + << "rdx" + << "rsi" + << "rdi" + << "rsp" + << "rbp" + << "r8" + << "r9" + << "r10" + << "r11" + << "r12" + << "r13" + << "r14" + << "r15"; + ip = "rip"; } - if (actionType == anyAction) { - if (output[output.length() - 1] != '\n') - output += QChar('\n'); - //process as ni or si - if (output.indexOf(QRegExp("0x[0-9a-fA-F]{8,16} in ")) != -1 - && !backtrace) { - actionTypeQueue.enqueue(showLine); - processAction(output); + for (int i = 0; !registersStream.atEnd(); i++) { + registersStream >> info.name; + + if (info.name.isEmpty()) { + // last empty line + break; + } + + if (general.contains(info.name) || segment.contains(info.name) || + fpu_info.contains(info.name) || info.name == ip || flags.contains(info.name) || + fpu_stack.exactMatch(info.name)) { + registersStream >> info.hexValue; + registersStream.skipWhiteSpace(); + info.decValue = registersStream.readLine(); + } else if (mmx.exactMatch(info.name) || xmm.exactMatch(info.name) || + ymm.exactMatch(info.name)) { + QMap fields; + + if (!readStruct(registersStream, &fields)) { + // bad news + emit printLog(QString("can not parse register data: ") + info.name + "\n", + Qt::red); + break; } - if (!error.isEmpty()) { - if (output != " \n") - output = error + output; - else - output = error; - } - } - if (actionType == infoMemory) { - bool isValid = false; - if (output.indexOf(QString("No symbol")) == -1 && - output.indexOf(QString("no debug info")) == -1 && output != QString(" ")) { - //if variable exists (isValid = true) - isValid = true; - int index = output.indexOf(QRegExp("\\$\\d+ = .*")); - if (index == -1) - isValid = false; - else { - output = output.right(output.length() - index); - output = output.right(output.length() - output.indexOf(QChar('=')) - 1); - for (int i = output.size() - 1; i >= 0; i--) { - if (output[i].isSpace()) - output.remove(i, 1); - } - } - } - memoryInfo info; - if (isValid) - info.value = output; - info.isValid = isValid; - watches.append(info); - if (watchesCount == watches.size()) { - emit printMemory(watches); - watches.clear(); - } + if (mmx.exactMatch(info.name)) info.decValue = fields["v8_int8"]; + else if (xmm.exactMatch(info.name)) + info.decValue = fields["uint128"]; + else if (ymm.exactMatch(info.name)) + info.decValue = fields["v2_int128"]; + + info.hexValue = ""; + } else { + // unknown register, try to skip it. + registersStream.readLine(); + emit printLog(QString("unknown register: ") + info.name + "\n", Qt::red); + continue; + } + + registers.append(info); + if (i == 0 && info.name != "eax" && info.name != "rax" && registersOk) { + doInput(QString("info registers\n"), infoRegisters); + registersOk = false; return; + } } - if (actionType == infoRegisters) { - QTextStream registersStream(&output); - QList registers; - registersInfo info; - QSettings settings("SASM Project", "SASM"); - - QSet general; - QString ip; - QSet segment; - segment << "cs" << "ds" << "ss" << "es" << "fs" << "gs"; - QSet flags; - flags << "eflags" << "mxcsr"; - QSet fpu_info; - fpu_info << "fctrl" << "fstat" << "ftag" << "fiseg" << "fioff" << "foseg" << "fooff" << "fop"; - QRegExp mmx("mm\\d+"); - QRegExp xmm("xmm\\d+"); - QRegExp ymm("ymm\\d+"); - QRegExp fpu_stack("st\\d+"); - - if (settings.value("mode", QString("x86")).toString() == "x86") { - //x86 - general << "eax" << "ebx" << "ecx" << "edx" << "esi" << "edi" << "esp" << "ebp"; - ip = "eip"; - } else { - //x64 - general << "rax" << "rbx" << "rcx" << "rdx" << "rsi" << "rdi" << "rsp" << "rbp" << - "r8" << "r9" << "r10" << "r11" << "r12" << "r13" << "r14" << "r15"; - ip = "rip"; - } - - for (int i = 0; !registersStream.atEnd(); i++) { - registersStream >> info.name; - - if (info.name.isEmpty()) { - // last empty line - break; - } - - if (general.contains(info.name) || segment.contains(info.name) || fpu_info.contains(info.name) || - info.name == ip || flags.contains(info.name) || fpu_stack.exactMatch(info.name)) { - registersStream >> info.hexValue; - registersStream.skipWhiteSpace(); - info.decValue = registersStream.readLine(); - } else if (mmx.exactMatch(info.name) || xmm.exactMatch(info.name) || ymm.exactMatch(info.name)) { - QMap fields; - - if (!readStruct(registersStream, &fields)) { - // bad news - emit printLog(QString("can not parse register data: ") + info.name + "\n", Qt::red); - break; - } - - if (mmx.exactMatch(info.name)) - info.decValue = fields["v8_int8"]; - else if (xmm.exactMatch(info.name)) - info.decValue = fields["uint128"]; - else if (ymm.exactMatch(info.name)) - info.decValue = fields["v2_int128"]; - - info.hexValue = ""; - } else { - // unknown register, try to skip it. - registersStream.readLine(); - emit printLog(QString("unknown register: ") + info.name + "\n", Qt::red); - continue; - } - - registers.append(info); - if (i == 0 && info.name != "eax" && info.name != "rax" && registersOk) { - doInput(QString("info registers\n"), infoRegisters); - registersOk = false; - return; - } - } + emit printRegisters(registers); + return; + } - emit printRegisters(registers); - return; - } - - if (output == QString("\r\n") || output == QString("\n") || - output == QString("\r\n\n") || output == QString("\n\n")) //if empty - return; + if (output == QString("\r\n") || output == QString("\n") || + output == QString("\r\n\n") || output == QString("\n\n")) // if empty + return; - //print information to log field - emit printLog(output); + // print information to log field + emit printLog(output); } -bool Debugger::isStopped() -{ - return stopped; +bool Debugger::isStopped() { return stopped; } + +void Debugger::pause() { + if (pid == 0) return; + actionTypeQueue.clear(); +#ifdef Q_OS_WIN32 + HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD) pid); + if (proc != NULL) { + DebugBreakProcess(proc); + CloseHandle(proc); + } +#else + kill(pid, SIGINT); +#endif } -void Debugger::pause() -{ - if (pid == 0) - return; - actionTypeQueue.clear(); - #ifdef Q_OS_WIN32 - HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); - if (proc != NULL) { - DebugBreakProcess(proc); - CloseHandle(proc); - } - #else - kill(pid, SIGINT); - #endif +void Debugger::doInput(QString command, DebugActionType actionType) { + if (actionType != none) actionTypeQueue.enqueue(actionType); + // put \n after commands! + if (actionType == ni || actionType == si || actionType == showLine) { + emit highlightLine(-2); // does not turn off debug mode + stopped = false; + } + if (process) process->write(command.toLatin1()); } -void Debugger::doInput(QString command, DebugActionType actionType) -{ - if (actionType != none) - actionTypeQueue.enqueue(actionType); - //put \n after commands! - if (actionType == ni || actionType == si || actionType == showLine) { - emit highlightLine(-2); //does not turn off debug mode - stopped = false; +void Debugger::setWatchesCount(int count) { watchesCount = count; } + +void Debugger::processLst() { + // set accordance with .lst file and program in memory + QFile lst; + lst.setFileName(lstPath); + if (lst.open(QIODevice::ReadOnly)) { + // heuristic: + // if debug symbols exists - offset is difference between main labels in listing and + // in executable otherwise - offset is difference between entry point, labeled as + // "start", in listing and in executable + quint64 mainOffset; + if (dbgSymbols) mainOffset = assembler->getMainOffset(lst, "main"); + else + mainOffset = assembler->getMainOffset(lst, "start"); + lst.close(); + if ((qint64) mainOffset == -1) { + actionTypeQueue.enqueue(anyAction); + processAction( + tr("Entry point was not found! Entry point should have label \"main\" (if gcc " + "linker is used) or \"start\" (otherwise).")); + QObject::disconnect(process, SIGNAL(readyReadStandardOutput()), this, + SLOT(readOutputToBuffer())); + emit finished(); + return; + } + offset -= mainOffset; + lst.open(QIODevice::ReadOnly); + assembler->parseLstFile(lst, programPath, lines, offset); + lst.close(); + if (lines.isEmpty()) { + actionTypeQueue.enqueue(anyAction); + processAction(tr("Executable sections were not found! ") + + tr("For correct debugging executable sections should have name " + "\".text\" or \".code\" (for MASM only).")); + QObject::disconnect(process, SIGNAL(readyReadStandardOutput()), this, + SLOT(readOutputToBuffer())); + emit finished(); + return; } - if (process) - process->write(command.toLatin1()); + } } -void Debugger::setWatchesCount(int count) -{ - watchesCount = count; +void Debugger::run() { + // set breakpoint on main, run program amd open output and input files + // put \n after commands! + // b main and run before others! + if (dbgSymbols) { + doInput(QString("b main\n"), none); + } else { + doInput("b *0x" + QString::number(entryPoint, 16) + "\n", none); + } + + //! Read input.txt + QString runCommand = "run"; + QFile inputFile(inputPath); + if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&inputFile); + for (auto&& arg : in.readAll().split(' ')) runCommand.append(' ').append(arg); + } + runCommand.append('\n'); + + doInput(QString("cd " + workingDirectoryPath + "\n"), none); + doInput(QString(runCommand), none); + doInput(QString("p (int) dup2((int) open(\"%1\",0),0)\n").arg(inputPath), none); } -void Debugger::processLst() -{ - //set accordance with .lst file and program in memory - QFile lst; - lst.setFileName(Common::pathInTemp("program.lst")); - if (lst.open(QIODevice::ReadOnly)) { - //heuristic: - //if debug symbols exists - offset is difference between main labels in listing and in executable - //otherwise - offset is difference between entry point, labeled as "start", in listing and in executable - quint64 mainOffset; - if (dbgSymbols) - mainOffset = assembler->getMainOffset(lst, "main"); - else - mainOffset = assembler->getMainOffset(lst, "start"); - lst.close(); - if ((qint64) mainOffset == -1) { - actionTypeQueue.enqueue(anyAction); - processAction( - tr("Entry point was not found! Entry point should have label \"main\" (if gcc linker is used) or \"start\" (otherwise).")); - QObject::disconnect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutputToBuffer())); - emit finished(); - return; - } - offset -= mainOffset; - lst.open(QIODevice::ReadOnly); - assembler->parseLstFile(lst, lines, offset); - lst.close(); - if (lines.isEmpty()) { - actionTypeQueue.enqueue(anyAction); - processAction( - tr("Executable sections were not found! ") + - tr("For correct debugging executable sections should have name \".text\" or \".code\" (for MASM only).")); - QObject::disconnect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutputToBuffer())); - emit finished(); - return; - } +void Debugger::changeBreakpoint(quint64 lineNumber, bool isAdded) { + bool wasStarted = false; + if (!isStopped()) { + wasStarted = true; + QEventLoop eventLoop; + connect(this, SIGNAL(wasStopped()), &eventLoop, SLOT(quit())); + pause(); + eventLoop.exec(); + } + quint64 numInMem = 0; + LineNum brkpoint; + for (int i = 0; i < lines.count(); i++) // find address of line + if (lineNumber <= lines[i].numInCode) { + numInMem = lines[i].numInMem; + break; } + brkpoint.numInCode = lineNumber; + brkpoint.numInMem = numInMem; + + LineNum pair; + int count = 0; + foreach (pair, breakPairs) { + if (pair.numInMem == numInMem) count++; + } + if (isAdded) { // if breakpoint was added then set it + breakPairs.append(brkpoint); + if (count == 0) + doInput(QString("b *0x") + QString::number(numInMem, 16) + QString("\n"), + breakpoint); + } else { // if breakpoint was deleted then remove it + breakPairs.removeOne(brkpoint); + if (count == 1) + doInput(QString("clear *0x") + QString::number(numInMem, 16) + QString("\n"), + breakpoint); + } + if (wasStarted) emit needToContinue(); } -void Debugger::run() -{ - //set breakpoint on main, run program amd open output and input files - //put \n after commands! - //b main and run before others! - if (dbgSymbols) - doInput(QString("b main\n"), none); - else { - doInput("b *0x" + QString::number(entryPoint, 16) + "\n", none); +Debugger::~Debugger() { + emit highlightLine(-1); + if (process->state() == QProcess::Running) { + doInput("quit\n", none); + process->waitForFinished(1000); + if (process->state() == QProcess::Running) { // if still running + doInput("quit\n", none); + process->terminate(); } - doInput(QString("cd " + workingDirectoryPath + "\n"), none); - doInput(QString("run\n"), none); - doInput(QString("p (int) dup2((int) open(\"%1\",0),0)\n").arg(inputPath), none); + } + delete process; + process = 0; + lines.clear(); + delete bufferTimer; } -void Debugger::changeBreakpoint(quint64 lineNumber, bool isAdded) -{ - bool wasStarted = false; - if (!isStopped()) { - wasStarted = true; - QEventLoop eventLoop; - connect(this, SIGNAL(wasStopped()), &eventLoop, SLOT(quit())); - pause(); - eventLoop.exec(); - } - quint64 numInMem = 0; - LineNum brkpoint; - for (int i = 0; i < lines.count(); i++) //find address of line - if (lineNumber <= lines[i].numInCode) { - numInMem = lines[i].numInMem; - break; - } - brkpoint.numInCode = lineNumber; - brkpoint.numInMem = numInMem; - - LineNum pair; - int count = 0; - foreach (pair, breakPairs) { - if (pair.numInMem == numInMem) - count++; - } - if (isAdded) { //if breakpoint was added then set it - breakPairs.append(brkpoint); - if (count == 0) - doInput(QString("b *0x") + QString::number(numInMem, 16) + QString("\n"), breakpoint); - } else { //if breakpoint was deleted then remove it - breakPairs.removeOne(brkpoint); - if (count == 1) - doInput(QString("clear *0x") + QString::number(numInMem, 16) + QString("\n"), breakpoint); +namespace { + +// read struct like { = , ,,, = } +// from stream. Values may be simple or complex, like {v1, v2, v3 .. } +// all vi have to be simple, two-level complex values unsupported +// +// test end of stream before any reading, desperately trying not to hang on it +bool readStruct(QTextStream& str, QMap* map) { + str.skipWhiteSpace(); + if (str.atEnd()) return false; + + QChar c; + str >> c; + if (c != '{') return false; + + // struct begin + while (!str.atEnd()) { + str.skipWhiteSpace(); + + // may be it just empty + str >> c; + if (c == '}') return true; + + // read name, until space or '=' + QString name; + name += c; + + for (;;) { + if (str.atEnd()) return false; + str >> c; + if (c.isSpace() || (c == '=')) break; + name += c; } - if (wasStarted) - emit needToContinue(); -} -Debugger::~Debugger() { - emit highlightLine(-1); - if (process->state() == QProcess::Running) { - doInput("quit\n", none); - process->waitForFinished(1000); - if (process->state() == QProcess::Running) { //if still running - doInput("quit\n", none); - process->terminate(); - } + // read '=' + if (c != '=') { + str.skipWhiteSpace(); + + if (str.atEnd()) return false; + str >> c; + if (c != '=') // it has to be assignment + return false; } - delete process; - process = 0; - lines.clear(); - delete bufferTimer; -} -namespace { + str.skipWhiteSpace(); - // read struct like { = , ,,, = } - // from stream. Values may be simple or complex, like {v1, v2, v3 .. } - // all vi have to be simple, two-level complex values unsupported - // - // test end of stream before any reading, desperately trying not to hang on it - bool readStruct(QTextStream& str, QMap* map) { - str.skipWhiteSpace(); - if (str.atEnd()) - return false; - - QChar c; - str >> c; - if (c != '{') - return false; - - // struct begin - while (!str.atEnd()) { - str.skipWhiteSpace(); - - // may be it just empty - str >> c; - if (c == '}') - return true; - - // read name, until space or '=' - QString name; - name += c; - - for (;;) { - if (str.atEnd()) - return false; - str >> c; - if (c.isSpace() || (c == '=')) break; - name += c; - } - - // read '=' - if (c != '=') { - str.skipWhiteSpace(); - - if (str.atEnd()) - return false; - str >> c; - if (c != '=') // it has to be assignment - return false; - } - - str.skipWhiteSpace(); - - // read value, simple (until space, or ',', or '}') or complex (until '}') - QString value; - - if (str.atEnd()) - return false; - str >> c; - - if (c != '{') { - // simple value - value += c; - - for (;;) { - if (str.atEnd()) - return false; - str >> c; - if (c.isSpace() || (c == ',') || (c == '}')) break; - value += c; - } - } else { - // complex value - value += '{'; - - for (;;) { - if (str.atEnd()) - return false; - str >> c; - if (c == '}') break; - if (c.isSpace()) { - // replace all space characters by simple space - // and skip spaces after '{' and after space - if (!value.endsWith('{') && !value.endsWith(' ')) - value += ' '; - } else { - value += c; - } - } - - value += '}'; - c = ' '; // it was not last }, just end of value - } - - (*map)[name] = value; - - // to next name-value pair - if (c.isSpace()) { - str.skipWhiteSpace(); - if (str.atEnd()) - return false; - str >> c; - } - - if (c == '}') // end of struct - return true; - if (c != ',') // it has to be comma - return false; + // read value, simple (until space, or ',', or '}') or complex (until '}') + QString value; + + if (str.atEnd()) return false; + str >> c; + + if (c != '{') { + // simple value + value += c; + for (;;) { + if (str.atEnd()) return false; + str >> c; + if (c.isSpace() || (c == ',') || (c == '}')) break; + value += c; + } + } else { + // complex value + value += '{'; + + for (;;) { + if (str.atEnd()) return false; + str >> c; + if (c == '}') break; + if (c.isSpace()) { + // replace all space characters by simple space + // and skip spaces after '{' and after space + if (!value.endsWith('{') && !value.endsWith(' ')) value += ' '; + } else { + value += c; } + } - return false; + value += '}'; + c = ' '; // it was not last }, just end of value } + + (*map)[name] = value; + + // to next name-value pair + if (c.isSpace()) { + str.skipWhiteSpace(); + if (str.atEnd()) return false; + str >> c; + } + + if (c == '}') // end of struct + return true; + if (c != ',') // it has to be comma + return false; + } + + return false; } +} // namespace diff --git a/debugger.h b/debugger.h index f3c62e3c..b7e40bdf 100644 --- a/debugger.h +++ b/debugger.h @@ -83,6 +83,8 @@ class Debugger : public QObject public: Debugger(QTextEdit *tEdit, const QString &exePathParam, + const QString &lstPathParam, + const QString &programPathParam, const QString &workingDirectoryPathParam, const QString &inputPathParam, Assembler *assembler, @@ -133,6 +135,12 @@ class Debugger : public QObject //! Path to executable QString exePath; + //! Path to .lst file + QString lstPath; + + //! Path to .asm file + QString programPath; + //! Path to working directory QString workingDirectoryPath; diff --git a/fasm.cpp b/fasm.cpp index 734b5b34..bfe1873f 100644 --- a/fasm.cpp +++ b/fasm.cpp @@ -45,435 +45,834 @@ * Implements the FASM assembler */ -FASM::FASM(bool x86, QObject *parent) : - GccBasedAssembler(x86, parent) -{ -} +FASM::FASM(bool x86, QObject* parent) : GccBasedAssembler(x86, parent) {} -QString FASM::getAssemblerPath() -{ - #ifdef Q_OS_WIN32 - return Common::applicationDataPath() + "/FASM/fasm.exe"; - #else - return "fasm"; - #endif +QString FASM::getAssemblerPath() { +#ifdef Q_OS_WIN32 + return Common::applicationDataPath() + "/FASM/fasm.exe"; +#else + return "fasm"; +#endif } -QString FASM::getListingFilePath(QFile &lstOut) -{ - QString listingPath = Common::pathInTemp("fasmListing.txt"); - QFile::remove(listingPath); - QProcess getLst; - QStringList getLstArguments; - getLstArguments << lstOut.fileName() << listingPath; - getLst.setWorkingDirectory(Common::applicationDataPath() + "/include"); - #ifdef Q_OS_WIN32 - getLst.start(Common::applicationDataPath() + "/FASM/listing.exe", getLstArguments); - #else - getLst.start("listing", getLstArguments); - #endif - getLst.waitForFinished(); - return listingPath; +QString FASM::getListingFilePath(QFile& lstOut) { + QString listingPath = Common::pathInTemp("fasmListing.txt"); + QFile::remove(listingPath); + QProcess getLst; + QStringList getLstArguments; + getLstArguments << lstOut.fileName() << listingPath; + getLst.setWorkingDirectory(Common::applicationDataPath() + "/include"); +#ifdef Q_OS_WIN32 + getLst.start(Common::applicationDataPath() + "/FASM/listing.exe", getLstArguments); +#else + getLst.start("listing", getLstArguments); +#endif + getLst.waitForFinished(); + return listingPath; } -quint64 FASM::getMainOffset(QFile &lstOut, QString entryLabel) -{ - QFile lst(getListingFilePath(lstOut)); - lst.open(QFile::ReadOnly); - QTextStream lstStream(&lst); - QRegExp mainLabel(entryLabel + ":"); - bool flag = false; - while (!lstStream.atEnd()) { - QString line = lstStream.readLine(); - if (flag) { - line = line.split(QChar(':')).at(0); - if (line.length() > 16) - continue; - lst.close(); - return line.toULongLong(0, 16); - } else { - if (line.indexOf(mainLabel) != -1) - flag = true; - } +quint64 FASM::getMainOffset(QFile& lstOut, QString entryLabel) { + QFile lst(getListingFilePath(lstOut)); + lst.open(QFile::ReadOnly); + QTextStream lstStream(&lst); + QRegExp mainLabel(entryLabel + ":"); + bool flag = false; + while (!lstStream.atEnd()) { + QString line = lstStream.readLine(); + if (flag) { + line = line.split(QChar(':')).at(0); + if (line.length() > 16) continue; + lst.close(); + return line.toULongLong(0, 16); + } else { + if (line.indexOf(mainLabel) != -1) flag = true; } - lst.close(); - return -1; + } + lst.close(); + return -1; } -void FASM::parseLstFile(QFile &lstOut, QVector &lines, quint64 offset) -{ - QFile lst(getListingFilePath(lstOut)); - lst.open(QFile::ReadOnly); +void FASM::parseLstFile(QFile& lstOut, QString& programFilePath, + QVector& lines, quint64 offset) { + QFile lst(getListingFilePath(lstOut)); + lst.open(QFile::ReadOnly); - QTextStream lstStream(&lst); - QList > instrList; - while (!lstStream.atEnd()) { - QString line = lstStream.readLine(); - int index = line.indexOf(QChar(':')); - if (index == -1 || index > 16) - continue; - QString first = line.left(index); - QString second = line.mid(index + 1); - int k = 0; - while (k < second.length() && second[k].isSpace()) - k++; - second.remove(0, k); - instrList.append(QPair(first.toULongLong(0, 16) + offset, second)); + QTextStream lstStream(&lst); + QList > instrList; + while (!lstStream.atEnd()) { + QString line = lstStream.readLine(); + int index = line.indexOf(QChar(':')); + if (index == -1 || index > 16) continue; + QString first = line.left(index); + QString second = line.mid(index + 1); + int k = 0; + while (k < second.length() && second[k].isSpace()) k++; + second.remove(0, k); + instrList.append(QPair(first.toULongLong(0, 16) + offset, second)); + } + lst.close(); + QFile programFile(programFilePath); + programFile.open(QFile::ReadOnly); + QTextStream programStream(&programFile); + int i = 0; // offset in list + int numInCode = 0; + while (!programStream.atEnd()) { + if (i >= instrList.size()) { + break; } - lst.close(); - QFile programFile(Common::pathInTemp("program.asm")); - programFile.open(QFile::ReadOnly); - QTextStream programStream(&programFile); - int i = 0; //offset in list - int numInCode = 0; - while (!programStream.atEnd()) { - if (i >= instrList.size()) { - break; - } - QString line = programStream.readLine(); - numInCode++; - int k = 0; - while (k < line.length() && line[k].isSpace()) - k++; - line.remove(0, k); - if (line == instrList[i].second) { - LineNum l; - l.numInCode = numInCode; - l.numInMem = instrList[i].first; - lines.append(l); - i++; - } + QString line = programStream.readLine(); + numInCode++; + int k = 0; + while (k < line.length() && line[k].isSpace()) k++; + line.remove(0, k); + if (line == instrList[i].second) { + LineNum l; + l.numInCode = numInCode; + l.numInMem = instrList[i].first; + lines.append(l); + i++; } - programFile.close(); + } + programFile.close(); } -QString FASM::getStartText() -{ - #ifdef Q_OS_WIN32 - if (isx86()) { - return QString("format ELF\n\nsection '.text' executable\npublic _main\n") + - QString("_main:\n ;write your code here\n xor eax, eax\n ret"); - } else { - return QString("format ELF64\n\nsection '.text' executable\npublic main\n") + - QString("main:\n ;write your code here\n xor rax, rax\n ret"); - } - #else - if (isx86()) { - return QString("format ELF\n\nsection '.text' executable\npublic main\n") + - QString("main:\n ;write your code here\n xor eax, eax\n ret"); - } else { - return QString("format ELF64\n\nsection '.text' executable\npublic main\n") + - QString("main:\n ;write your code here\n xor rax, rax\n ret"); - } - #endif +QString FASM::getStartText() { +#ifdef Q_OS_WIN32 + if (isx86()) { + return QString("format ELF\n\nsection '.text' executable\npublic _main\n") + + QString("_main:\n ;write your code here\n xor eax, eax\n ret"); + } else { + return QString("format ELF64\n\nsection '.text' executable\npublic main\n") + + QString("main:\n ;write your code here\n xor rax, rax\n ret"); + } +#else + if (isx86()) { + return QString("format ELF\n\nsection '.text' executable\npublic main\n") + + QString("main:\n ;write your code here\n xor eax, eax\n ret"); + } else { + return QString("format ELF64\n\nsection '.text' executable\npublic main\n") + + QString("main:\n ;write your code here\n xor rax, rax\n ret"); + } +#endif } -void FASM::putDebugString(CodeEditor *code) -{ - //add : mov ebp, esp for making frame for correct debugging if this code has not been added yet - int index = code->toPlainText().indexOf(QRegExp("main:")); - if (index != -1) { - index = code->toPlainText().indexOf(QChar(':'), index); - if (isx86()) { - if (code->toPlainText().indexOf( - QRegExp("\\s+[Mm][Oo][Vv] +[Ee][Bb][Pp] *, *[Ee][Ss][Pp]"), index + 1) != index + 1) { - QTextCursor cursor = code->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); - cursor.insertText(QString("\n mov ebp, esp; for correct debugging")); - } - } else { - if (code->toPlainText().indexOf( - QRegExp("\\s+[Mm][Oo][Vv] +[Rr][Bb][Pp] *, *[Rr][Ss][Pp]"), index + 1) != index + 1) { - QTextCursor cursor = code->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); - cursor.insertText(QString("\n mov rbp, rsp; for correct debugging")); - } - } +void FASM::putDebugString(CodeEditor* code) { + // add : mov ebp, esp for making frame for correct debugging if this code has not been + // added yet + int index = code->toPlainText().indexOf(QRegExp("main:")); + if (index != -1) { + index = code->toPlainText().indexOf(QChar(':'), index); + if (isx86()) { + if (code->toPlainText().indexOf( + QRegExp("\\s+[Mm][Oo][Vv] +[Ee][Bb][Pp] *, *[Ee][Ss][Pp]"), index + 1) != + index + 1) { + QTextCursor cursor = code->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); + cursor.insertText(QString("\n mov ebp, esp; for correct debugging")); + } + } else { + if (code->toPlainText().indexOf( + QRegExp("\\s+[Mm][Oo][Vv] +[Rr][Bb][Pp] *, *[Rr][Ss][Pp]"), index + 1) != + index + 1) { + QTextCursor cursor = code->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); + cursor.insertText(QString("\n mov rbp, rsp; for correct debugging")); + } } + } } -QString FASM::getAssemblerOptions() -{ - return "$SOURCE$ $PROGRAM.OBJ$ -s $LSTOUTPUT$"; -} +QString FASM::getAssemblerOptions() { return "$SOURCE$ $PROGRAM.OBJ$ -s $LSTOUTPUT$"; } -void FASM::fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression) -{ - typedef Assembler::HighlightingRule HighlightingRule; - QTextCharFormat &keywordFormat = *formats[0]; - QTextCharFormat ®isterFormat = *formats[1]; - QTextCharFormat &numberFormat = *formats[2]; - QTextCharFormat &memoryFormat = *formats[3]; - QTextCharFormat &labelFormat = *formats[4]; - QTextCharFormat &commentFormat = *formats[5]; - QTextCharFormat &systemFormat = *formats[6]; - //QTextCharFormat &iomacrosFormat = *formats[7]; - QTextCharFormat "ationFormat = *formats[8]; - QTextCharFormat &labelWithDotFormat = *formats[9]; +void FASM::fillHighligherRules(QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, + QRegExp& commentEndExpression) { + typedef Assembler::HighlightingRule HighlightingRule; + QTextCharFormat& keywordFormat = *formats[0]; + QTextCharFormat& registerFormat = *formats[1]; + QTextCharFormat& numberFormat = *formats[2]; + QTextCharFormat& memoryFormat = *formats[3]; + QTextCharFormat& labelFormat = *formats[4]; + QTextCharFormat& commentFormat = *formats[5]; + QTextCharFormat& systemFormat = *formats[6]; + // QTextCharFormat &iomacrosFormat = *formats[7]; + QTextCharFormat& quotationFormat = *formats[8]; + QTextCharFormat& labelWithDotFormat = *formats[9]; - //setting up regular expressions - HighlightingRule rule; + // setting up regular expressions + HighlightingRule rule; - //keywords - QStringList keywordPatterns; - keywordPatterns << "\\bAAA\\b" << "\\bAAD\\b" << "\\bAAM\\b" << "\\bAAS\\b" << - "\\bADC\\b" << "\\bADD\\b" << "\\bAND\\b" << "\\bCALL\\b" << - "\\bCBW\\b" << "\\bCLC\\b" << "\\bCLD\\b" << "\\bCLI\\b" << - "\\bCMC\\b" << "\\bCMP\\b" << "\\bCMPSB\\b" << "\\bCMPSW\\b" << - "\\bCWD\\b" << "\\bDAA\\b" << "\\bDAS\\b" << "\\bDEC\\b" << - "\\bDIV\\b" << "\\bESC\\b" << "\\bHLT\\b" << "\\bIDIV\\b" << - "\\bIMUL\\b" << "\\bIN\\b" << "\\bINC\\b" << "\\bINT\\b" << - "\\bINTO\\b" << "\\bIRET\\b" << "\\bJA\\b" << "\\bJAE\\b" << - "\\bJB\\b" << "\\bJBE\\b" << "\\bJC\\b" << "\\bJCXZ\\b" << - "\\bJE\\b" << "\\bJG\\b" << "\\bJGE\\b" << "\\bJL\\b" << - "\\bJLE\\b" << "\\bJNA\\b" << "\\bJNAE\\b" << "\\bJNB\\b" << - "\\bJNBE\\b" << "\\bJNC\\b" << "\\bJNE\\b" << "\\bJNG\\b" << - "\\bJNGE\\b" << "\\bJNL\\b" << "\\bJNLE\\b" << "\\bJNO\\b" << - "\\bJNP\\b" << "\\bJNS\\b" << "\\bJNZ\\b" << "\\bJO\\b" << - "\\bJP\\b" << "\\bJPE\\b" << "\\bJPO\\b" << "\\bJS\\b" << - "\\bJZ\\b" << "\\bJMP\\b" << "\\bLAHF\\b" << "\\bLDS\\b" << - "\\bLEA\\b" << "\\bLES\\b" << "\\bLOCK\\b" << "\\bLODSB\\b" << - "\\bLODSW\\b" << "\\bLOOP\\b" << "\\bLOOPE\\b" << "\\bLOOPNE\\b" << - "\\bLOOPNZ\\b" << "\\bLOOPZ\\b" << "\\bMOV\\b" << "\\bMOVSB\\b" << - "\\bMOVSW\\b" << "\\bMUL\\b" << "\\bNEG\\b" << "\\bNOP\\b" << - "\\bNOT\\b" << "\\bOR\\b" << "\\bOUT\\b" << "\\bPOP\\b" << - "\\bPOPF\\b" << "\\bPUSH\\b" << "\\bPUSHF\\b" << "\\bRCL\\b" << - "\\bRCR\\b" << "\\bREP\\b" << "\\bREPE\\b" << "\\bREPNE\\b" << - "\\bREPNZ\\b" << "\\bREPZ\\b" << "\\bRET\\b" << "\\bRETN\\b" << - "\\bRETF\\b" << "\\bROL\\b" << "\\bROR\\b" << "\\bSAHF\\b" << - "\\bSAL\\b" << "\\bSAR\\b" << "\\bSBB\\b" << "\\bSCASB\\b" << - "\\bSCASW\\b" << "\\bSHL\\b" << "\\bSHR\\b" << "\\bSTC\\b" << - "\\bSTD\\b" << "\\bSTI\\b" << "\\bSTOSB\\b" << "\\bSTOSW\\b" << - "\\bSUB\\b" << "\\bTEST\\b" << "\\bWAIT\\b" << "\\bXCHG\\b" << - "\\bXLAT\\b" << "\\bXOR\\b" << "\\bBOUND\\b" << "\\bENTER\\b" << - "\\bINS\\b" << "\\bLEAVE\\b" << "\\bOUTS\\b" << "\\bPOPA\\b" << - "\\bPUSHA\\b" << "\\bARPL\\b" << "\\bCLTS\\b" << "\\bLAR\\b" << - "\\bLGDT\\b" << "\\bLIDT\\b" << "\\bLLDT\\b" << "\\bLMSW\\b" << - "\\bLOADALL\\b" << "\\bLSL\\b" << "\\bLTR\\b" << "\\bSGDT\\b" << - "\\bSIDT\\b" << "\\bSLDT\\b" << "\\bSMSW\\b" << "\\bSTR\\b" << - "\\bVERR\\b" << "\\bVERW\\b" << "\\bBSF\\b" << "\\bBSR\\b" << - "\\bBT\\b" << "\\bBTC\\b" << "\\bBTR\\b" << "\\bBTS\\b" << - "\\bCDQ\\b" << "\\bCMPSD\\b" << "\\bCWDE\\b" << "\\bINSD\\b" << - "\\bIRET\\b" << "\\bIRETW\\b" << "\\bIRETD\\b" << "\\bJCXZ\\b" << - "\\bJECXZ\\b" << "\\bLFS\\b" << "\\bLGS\\b" << "\\bLSS\\b" << - "\\bLODSD\\b" << "\\bMOVSD\\b" << "\\bMOVSX\\b" << "\\bMOVZX\\b" << - "\\bOUTSD\\b" << "\\bPOPAD\\b" << "\\bPOPFD\\b" << "\\bPUSHAD\\b" << - "\\bPUSHFD\\b" << "\\bSCASD\\b" << "\\bSETA\\b" << "\\bSETAE\\b" << - "\\bSETB\\b" << "\\bSETBE\\b" << "\\bSETC\\b" << "\\bSETE\\b" << - "\\bSETG\\b" << "\\bSETGE\\b" << "\\bSETL\\b" << "\\bSETLE\\b" << - "\\bSETNA\\b" << "\\bSETNAE\\b" << "\\bSETNB\\b" << "\\bSETNBE\\b" << - "\\bSETNC\\b" << "\\bSETNE\\b" << "\\bSETNG\\b" << "\\bSETNGE\\b" << - "\\bSETNL\\b" << "\\bSETNLE\\b" << "\\bSETNO\\b" << "\\bSETNP\\b" << - "\\bSETNS\\b" << "\\bSETNZ\\b" << "\\bSETO\\b" << "\\bSETP\\b" << - "\\bSETPE\\b" << "\\bSETPO\\b" << "\\bSETS\\b" << "\\bSETZ\\b" << - "\\bSHLD\\b" << "\\bSHRD\\b" << "\\bSTOSD\\b" << - "\\bPOPAD\\b" << "\\bPOPFD\\b" << "\\bPUSHAD\\b" << "\\bPUSHFD\\b" << - "\\bSCASD\\b" << "\\bBSWAP\\b" << "\\bCMPXCHG\\b" << "\\bINVD\\b" << - "\\bINVLPG\\b" << "\\bWBINVD\\b" << "\\bXADD\\b" << "\\bCPUID\\b" << - "\\bCMPXCHG8B\\b" << "\\bRDMSR\\b" << "\\bRDTSC\\b" << "\\bWRMSR\\b" << - "\\bRSM\\b" << "\\bRDPMC\\b" << "\\bCMOVA\\b" << "\\bCMOVAE\\b" << - "\\bCMOVB\\b" << "\\bCMOVBE\\b" << "\\bCMOVC\\b" << "\\bCMOVE\\b" << - "\\bCMOVG\\b" << "\\bCMOVGE\\b" << "\\bCMOVL\\b" << "\\bCMOVLE\\b" << - "\\bCMOVNA\\b" << "\\bCMOVNAE\\b" << "\\bCMOVNB\\b" << "\\bCMOVNBE\\b" << - "\\bCMOVNC\\b" << "\\bCMOVNE\\b" << "\\bCMOVNG\\b" << "\\bCMOVNGE\\b" << - "\\bCMOVNL\\b" << "\\bCMOVNLE\\b" << "\\bCMOVNO\\b" << "\\bCMOVNP\\b" << - "\\bCMOVNS\\b" << "\\bCMOVNZ\\b" << "\\bCMOVO\\b" << "\\bCMOVP\\b" << - "\\bCMOVPE\\b" << "\\bCMOVPO\\b" << "\\bCMOVS\\b" << "\\bCMOVZ\\b" << - "\\bF2XM1\\b" << "\\bFABS\\b" << "\\bFADD\\b" << "\\bFADDP\\b" << - "\\bFBLD\\b" << "\\bFBSTP\\b" << "\\bFCHS\\b" << "\\bFCLEX\\b" << - "\\bFCOM\\b" << "\\bFCOMP\\b" << "\\bFCOMPP\\b" << "\\bFDECSTP\\b" << - "\\bFDISI\\b" << "\\bFDIV\\b" << "\\bFDIVP\\b" << "\\bFDIVR\\b" << - "\\bFDIVRP\\b" << "\\bFENI\\b" << "\\bFFREE\\b" << "\\bFIADD\\b" << - "\\bFICOM\\b" << "\\bFICOMP\\b" << "\\bFIDIV\\b" << "\\bFIDIVR\\b" << - "\\bFILD\\b" << "\\bFIMUL\\b" << "\\bFINCSTP\\b" << "\\bFINIT\\b" << - "\\bFIST\\b" << "\\bFISTP\\b" << "\\bFISUB\\b" << "\\bFISUBR\\b" << - "\\bFLD\\b" << "\\bFLD1\\b" << "\\bFLDCW\\b" << "\\bFLDENV\\b" << - "\\bFLDENVW\\b" << "\\bFLDL2E\\b" << "\\bFLDL2T\\b" << "\\bFLDLG2\\b" << - "\\bFLDLN2\\b" << "\\bFLDPI\\b" << "\\bFLDZ\\b" << "\\bFMUL\\b" << - "\\bFMULP\\b" << "\\bFNCLEX\\b" << "\\bFNDISI\\b" << "\\bFNENI\\b" << - "\\bFNINIT\\b" << "\\bFNOP\\b" << "\\bFNSAVE\\b" << "\\bFNSAVEW\\b" << - "\\bFNSTCW\\b" << "\\bFNSTENV\\b" << "\\bFNSTENVW\\b" << "\\bFNSTSW\\b" << - "\\bFPATAN\\b" << "\\bFPREM\\b" << "\\bFPTAN\\b" << "\\bFRNDINT\\b" << - "\\bFRSTOR\\b" << "\\bFRSTORW\\b" << "\\bFSAVE\\b" << "\\bFSAVEW\\b" << - "\\bFSCALE\\b" << "\\bFSQRT\\b" << "\\bFST\\b" << "\\bFSTCW\\b" << - "\\bFSTENV\\b" << "\\bFSTENVW\\b" << "\\bFSTP\\b" << "\\bFSTSW\\b" << - "\\bFSUB\\b" << "\\bFSUBP\\b" << "\\bFSUBR\\b" << "\\bFSUBRP\\b" << - "\\bFTST\\b" << "\\bFWAIT\\b" << "\\bFXAM\\b" << "\\bFXCH\\b" << - "\\bFXTRACT\\b" << "\\bFYL2X\\b" << "\\bFYL2XP1\\b" << "\\bFSETPM\\b" << - "\\bFCOS\\b" << "\\bFLDENVD\\b" << "\\bFSAVED\\b" << "\\bFSTENVD\\b" << - "\\bFPREM1\\b" << "\\bFRSTORD\\b" << "\\bFSIN\\b" << "\\bFSINCOS\\b" << - "\\bFSTENVD\\b" << "\\bFUCOM\\b" << "\\bFUCOMP\\b" << "\\bFUCOMPP\\b" << - "\\bFCMOVB\\b" << "\\bFCMOVBE\\b" << "\\bFCMOVE\\b" << "\\bFCMOVNB\\b" << - "\\bFCMOVNBE\\b" << "\\bFCMOVNE\\b" << "\\bFCMOVNU\\b" << "\\bFCMOVU\\b" << - "\\bFCOMI\\b" << "\\bFCOMIP\\b" << "\\bFUCOMI\\b" << "\\bFUCOMIP\\b" << - "\\bCDQE\\b" << "\\bCQO\\b" << "\\bMOVMSKPS\\b" << "\\bMOVMSKPD\\b" << - "\\bPOPCNT\\b" << "\\bLZCNT\\b" << "\\bCMPSQ\\b" << "\\bSCASQ\\b" << - "\\bMOVSQ\\b" << "\\bLODSQ\\b" << "\\bSTOSQ\\b" << "\\bJRCXZ\\b" << - "\\bIRETQ\\b" << "\\bPUSHFQ\\b" << "\\bPOPFQ\\b" << "\\bCMPXCHG16B\\b" << - "\\bJRCXZ\\b" << "\\bINSB\\b" << "\\bINSW\\b" << "\\bOUTSB\\b" << - "\\bOUTSW\\b" << "\\bLFENCE\\b" << "\\bSFENCE\\b" << "\\bMFENCE\\b" << - "\\bPREFETCH\\b" << "\\bPREFETCHL\\b" << "\\bPREFETCHW\\b" << "\\bCLFLUSH\\b" << - "\\bSYSENTER\\b" << "\\bSYSEXIT\\b" << "\\bSYSCALL\\b" << "\\bSYSRET\\b"; - foreach (const QString &pattern, keywordPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - rule.format = keywordFormat; - highlightingRules.append(rule); - } - - //memory - rule.format = memoryFormat; - QStringList memoryPatterns; - rule.pattern = QRegExp("\\["); - highlightingRules.append(rule); - rule.pattern = QRegExp("\\]"); + // keywords + QStringList keywordPatterns; + keywordPatterns << "\\bAAA\\b" + << "\\bAAD\\b" + << "\\bAAM\\b" + << "\\bAAS\\b" + << "\\bADC\\b" + << "\\bADD\\b" + << "\\bAND\\b" + << "\\bCALL\\b" + << "\\bCBW\\b" + << "\\bCLC\\b" + << "\\bCLD\\b" + << "\\bCLI\\b" + << "\\bCMC\\b" + << "\\bCMP\\b" + << "\\bCMPSB\\b" + << "\\bCMPSW\\b" + << "\\bCWD\\b" + << "\\bDAA\\b" + << "\\bDAS\\b" + << "\\bDEC\\b" + << "\\bDIV\\b" + << "\\bESC\\b" + << "\\bHLT\\b" + << "\\bIDIV\\b" + << "\\bIMUL\\b" + << "\\bIN\\b" + << "\\bINC\\b" + << "\\bINT\\b" + << "\\bINTO\\b" + << "\\bIRET\\b" + << "\\bJA\\b" + << "\\bJAE\\b" + << "\\bJB\\b" + << "\\bJBE\\b" + << "\\bJC\\b" + << "\\bJCXZ\\b" + << "\\bJE\\b" + << "\\bJG\\b" + << "\\bJGE\\b" + << "\\bJL\\b" + << "\\bJLE\\b" + << "\\bJNA\\b" + << "\\bJNAE\\b" + << "\\bJNB\\b" + << "\\bJNBE\\b" + << "\\bJNC\\b" + << "\\bJNE\\b" + << "\\bJNG\\b" + << "\\bJNGE\\b" + << "\\bJNL\\b" + << "\\bJNLE\\b" + << "\\bJNO\\b" + << "\\bJNP\\b" + << "\\bJNS\\b" + << "\\bJNZ\\b" + << "\\bJO\\b" + << "\\bJP\\b" + << "\\bJPE\\b" + << "\\bJPO\\b" + << "\\bJS\\b" + << "\\bJZ\\b" + << "\\bJMP\\b" + << "\\bLAHF\\b" + << "\\bLDS\\b" + << "\\bLEA\\b" + << "\\bLES\\b" + << "\\bLOCK\\b" + << "\\bLODSB\\b" + << "\\bLODSW\\b" + << "\\bLOOP\\b" + << "\\bLOOPE\\b" + << "\\bLOOPNE\\b" + << "\\bLOOPNZ\\b" + << "\\bLOOPZ\\b" + << "\\bMOV\\b" + << "\\bMOVSB\\b" + << "\\bMOVSW\\b" + << "\\bMUL\\b" + << "\\bNEG\\b" + << "\\bNOP\\b" + << "\\bNOT\\b" + << "\\bOR\\b" + << "\\bOUT\\b" + << "\\bPOP\\b" + << "\\bPOPF\\b" + << "\\bPUSH\\b" + << "\\bPUSHF\\b" + << "\\bRCL\\b" + << "\\bRCR\\b" + << "\\bREP\\b" + << "\\bREPE\\b" + << "\\bREPNE\\b" + << "\\bREPNZ\\b" + << "\\bREPZ\\b" + << "\\bRET\\b" + << "\\bRETN\\b" + << "\\bRETF\\b" + << "\\bROL\\b" + << "\\bROR\\b" + << "\\bSAHF\\b" + << "\\bSAL\\b" + << "\\bSAR\\b" + << "\\bSBB\\b" + << "\\bSCASB\\b" + << "\\bSCASW\\b" + << "\\bSHL\\b" + << "\\bSHR\\b" + << "\\bSTC\\b" + << "\\bSTD\\b" + << "\\bSTI\\b" + << "\\bSTOSB\\b" + << "\\bSTOSW\\b" + << "\\bSUB\\b" + << "\\bTEST\\b" + << "\\bWAIT\\b" + << "\\bXCHG\\b" + << "\\bXLAT\\b" + << "\\bXOR\\b" + << "\\bBOUND\\b" + << "\\bENTER\\b" + << "\\bINS\\b" + << "\\bLEAVE\\b" + << "\\bOUTS\\b" + << "\\bPOPA\\b" + << "\\bPUSHA\\b" + << "\\bARPL\\b" + << "\\bCLTS\\b" + << "\\bLAR\\b" + << "\\bLGDT\\b" + << "\\bLIDT\\b" + << "\\bLLDT\\b" + << "\\bLMSW\\b" + << "\\bLOADALL\\b" + << "\\bLSL\\b" + << "\\bLTR\\b" + << "\\bSGDT\\b" + << "\\bSIDT\\b" + << "\\bSLDT\\b" + << "\\bSMSW\\b" + << "\\bSTR\\b" + << "\\bVERR\\b" + << "\\bVERW\\b" + << "\\bBSF\\b" + << "\\bBSR\\b" + << "\\bBT\\b" + << "\\bBTC\\b" + << "\\bBTR\\b" + << "\\bBTS\\b" + << "\\bCDQ\\b" + << "\\bCMPSD\\b" + << "\\bCWDE\\b" + << "\\bINSD\\b" + << "\\bIRET\\b" + << "\\bIRETW\\b" + << "\\bIRETD\\b" + << "\\bJCXZ\\b" + << "\\bJECXZ\\b" + << "\\bLFS\\b" + << "\\bLGS\\b" + << "\\bLSS\\b" + << "\\bLODSD\\b" + << "\\bMOVSD\\b" + << "\\bMOVSX\\b" + << "\\bMOVZX\\b" + << "\\bOUTSD\\b" + << "\\bPOPAD\\b" + << "\\bPOPFD\\b" + << "\\bPUSHAD\\b" + << "\\bPUSHFD\\b" + << "\\bSCASD\\b" + << "\\bSETA\\b" + << "\\bSETAE\\b" + << "\\bSETB\\b" + << "\\bSETBE\\b" + << "\\bSETC\\b" + << "\\bSETE\\b" + << "\\bSETG\\b" + << "\\bSETGE\\b" + << "\\bSETL\\b" + << "\\bSETLE\\b" + << "\\bSETNA\\b" + << "\\bSETNAE\\b" + << "\\bSETNB\\b" + << "\\bSETNBE\\b" + << "\\bSETNC\\b" + << "\\bSETNE\\b" + << "\\bSETNG\\b" + << "\\bSETNGE\\b" + << "\\bSETNL\\b" + << "\\bSETNLE\\b" + << "\\bSETNO\\b" + << "\\bSETNP\\b" + << "\\bSETNS\\b" + << "\\bSETNZ\\b" + << "\\bSETO\\b" + << "\\bSETP\\b" + << "\\bSETPE\\b" + << "\\bSETPO\\b" + << "\\bSETS\\b" + << "\\bSETZ\\b" + << "\\bSHLD\\b" + << "\\bSHRD\\b" + << "\\bSTOSD\\b" + << "\\bPOPAD\\b" + << "\\bPOPFD\\b" + << "\\bPUSHAD\\b" + << "\\bPUSHFD\\b" + << "\\bSCASD\\b" + << "\\bBSWAP\\b" + << "\\bCMPXCHG\\b" + << "\\bINVD\\b" + << "\\bINVLPG\\b" + << "\\bWBINVD\\b" + << "\\bXADD\\b" + << "\\bCPUID\\b" + << "\\bCMPXCHG8B\\b" + << "\\bRDMSR\\b" + << "\\bRDTSC\\b" + << "\\bWRMSR\\b" + << "\\bRSM\\b" + << "\\bRDPMC\\b" + << "\\bCMOVA\\b" + << "\\bCMOVAE\\b" + << "\\bCMOVB\\b" + << "\\bCMOVBE\\b" + << "\\bCMOVC\\b" + << "\\bCMOVE\\b" + << "\\bCMOVG\\b" + << "\\bCMOVGE\\b" + << "\\bCMOVL\\b" + << "\\bCMOVLE\\b" + << "\\bCMOVNA\\b" + << "\\bCMOVNAE\\b" + << "\\bCMOVNB\\b" + << "\\bCMOVNBE\\b" + << "\\bCMOVNC\\b" + << "\\bCMOVNE\\b" + << "\\bCMOVNG\\b" + << "\\bCMOVNGE\\b" + << "\\bCMOVNL\\b" + << "\\bCMOVNLE\\b" + << "\\bCMOVNO\\b" + << "\\bCMOVNP\\b" + << "\\bCMOVNS\\b" + << "\\bCMOVNZ\\b" + << "\\bCMOVO\\b" + << "\\bCMOVP\\b" + << "\\bCMOVPE\\b" + << "\\bCMOVPO\\b" + << "\\bCMOVS\\b" + << "\\bCMOVZ\\b" + << "\\bF2XM1\\b" + << "\\bFABS\\b" + << "\\bFADD\\b" + << "\\bFADDP\\b" + << "\\bFBLD\\b" + << "\\bFBSTP\\b" + << "\\bFCHS\\b" + << "\\bFCLEX\\b" + << "\\bFCOM\\b" + << "\\bFCOMP\\b" + << "\\bFCOMPP\\b" + << "\\bFDECSTP\\b" + << "\\bFDISI\\b" + << "\\bFDIV\\b" + << "\\bFDIVP\\b" + << "\\bFDIVR\\b" + << "\\bFDIVRP\\b" + << "\\bFENI\\b" + << "\\bFFREE\\b" + << "\\bFIADD\\b" + << "\\bFICOM\\b" + << "\\bFICOMP\\b" + << "\\bFIDIV\\b" + << "\\bFIDIVR\\b" + << "\\bFILD\\b" + << "\\bFIMUL\\b" + << "\\bFINCSTP\\b" + << "\\bFINIT\\b" + << "\\bFIST\\b" + << "\\bFISTP\\b" + << "\\bFISUB\\b" + << "\\bFISUBR\\b" + << "\\bFLD\\b" + << "\\bFLD1\\b" + << "\\bFLDCW\\b" + << "\\bFLDENV\\b" + << "\\bFLDENVW\\b" + << "\\bFLDL2E\\b" + << "\\bFLDL2T\\b" + << "\\bFLDLG2\\b" + << "\\bFLDLN2\\b" + << "\\bFLDPI\\b" + << "\\bFLDZ\\b" + << "\\bFMUL\\b" + << "\\bFMULP\\b" + << "\\bFNCLEX\\b" + << "\\bFNDISI\\b" + << "\\bFNENI\\b" + << "\\bFNINIT\\b" + << "\\bFNOP\\b" + << "\\bFNSAVE\\b" + << "\\bFNSAVEW\\b" + << "\\bFNSTCW\\b" + << "\\bFNSTENV\\b" + << "\\bFNSTENVW\\b" + << "\\bFNSTSW\\b" + << "\\bFPATAN\\b" + << "\\bFPREM\\b" + << "\\bFPTAN\\b" + << "\\bFRNDINT\\b" + << "\\bFRSTOR\\b" + << "\\bFRSTORW\\b" + << "\\bFSAVE\\b" + << "\\bFSAVEW\\b" + << "\\bFSCALE\\b" + << "\\bFSQRT\\b" + << "\\bFST\\b" + << "\\bFSTCW\\b" + << "\\bFSTENV\\b" + << "\\bFSTENVW\\b" + << "\\bFSTP\\b" + << "\\bFSTSW\\b" + << "\\bFSUB\\b" + << "\\bFSUBP\\b" + << "\\bFSUBR\\b" + << "\\bFSUBRP\\b" + << "\\bFTST\\b" + << "\\bFWAIT\\b" + << "\\bFXAM\\b" + << "\\bFXCH\\b" + << "\\bFXTRACT\\b" + << "\\bFYL2X\\b" + << "\\bFYL2XP1\\b" + << "\\bFSETPM\\b" + << "\\bFCOS\\b" + << "\\bFLDENVD\\b" + << "\\bFSAVED\\b" + << "\\bFSTENVD\\b" + << "\\bFPREM1\\b" + << "\\bFRSTORD\\b" + << "\\bFSIN\\b" + << "\\bFSINCOS\\b" + << "\\bFSTENVD\\b" + << "\\bFUCOM\\b" + << "\\bFUCOMP\\b" + << "\\bFUCOMPP\\b" + << "\\bFCMOVB\\b" + << "\\bFCMOVBE\\b" + << "\\bFCMOVE\\b" + << "\\bFCMOVNB\\b" + << "\\bFCMOVNBE\\b" + << "\\bFCMOVNE\\b" + << "\\bFCMOVNU\\b" + << "\\bFCMOVU\\b" + << "\\bFCOMI\\b" + << "\\bFCOMIP\\b" + << "\\bFUCOMI\\b" + << "\\bFUCOMIP\\b" + << "\\bCDQE\\b" + << "\\bCQO\\b" + << "\\bMOVMSKPS\\b" + << "\\bMOVMSKPD\\b" + << "\\bPOPCNT\\b" + << "\\bLZCNT\\b" + << "\\bCMPSQ\\b" + << "\\bSCASQ\\b" + << "\\bMOVSQ\\b" + << "\\bLODSQ\\b" + << "\\bSTOSQ\\b" + << "\\bJRCXZ\\b" + << "\\bIRETQ\\b" + << "\\bPUSHFQ\\b" + << "\\bPOPFQ\\b" + << "\\bCMPXCHG16B\\b" + << "\\bJRCXZ\\b" + << "\\bINSB\\b" + << "\\bINSW\\b" + << "\\bOUTSB\\b" + << "\\bOUTSW\\b" + << "\\bLFENCE\\b" + << "\\bSFENCE\\b" + << "\\bMFENCE\\b" + << "\\bPREFETCH\\b" + << "\\bPREFETCHL\\b" + << "\\bPREFETCHW\\b" + << "\\bCLFLUSH\\b" + << "\\bSYSENTER\\b" + << "\\bSYSEXIT\\b" + << "\\bSYSCALL\\b" + << "\\bSYSRET\\b"; + foreach (const QString& pattern, keywordPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); + rule.format = keywordFormat; highlightingRules.append(rule); - memoryPatterns << "\\bdb\\b" << "\\bdw\\b" << "\\bdu\\b" << - "\\bdd\\b" << "\\bdp\\b" << "\\bdf\\b" << - "\\bdq\\b" << "\\bdt\\b" << "\\bequ\\b" << - "\\brb\\b" << "\\brw\\b" << "\\brd\\b" << - "\\brp\\b" << "\\brf\\b" << "\\brq\\b" << - "\\brt\\b" << - "\\bbyte[\\s\\[]" << "\\bword[\\s\\[]" << - "\\bdword[\\s\\[]" << "\\bfword[\\s\\[]" << - "\\bpword[\\s\\[]" << "\\bqword[\\s\\[]" << - "\\btword[\\s\\[]" << "\\bdqword[\\s\\[]" << - "\\bxword[\\s\\[]" << "\\bqqword[\\s\\[]" << - "\\byword[\\s\\[]" << "\\btbyte[\\s\\[]" << - "\\bdup\\b" << "\\bfile\\b" << "\\bptr\\b" << - "\\blabel\\b"; - foreach (const QString &pattern, memoryPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } + } - //labels - rule.pattern = QRegExp("\\S+:"); - rule.format = labelFormat; + // memory + rule.format = memoryFormat; + QStringList memoryPatterns; + rule.pattern = QRegExp("\\["); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\]"); + highlightingRules.append(rule); + memoryPatterns << "\\bdb\\b" + << "\\bdw\\b" + << "\\bdu\\b" + << "\\bdd\\b" + << "\\bdp\\b" + << "\\bdf\\b" + << "\\bdq\\b" + << "\\bdt\\b" + << "\\bequ\\b" + << "\\brb\\b" + << "\\brw\\b" + << "\\brd\\b" + << "\\brp\\b" + << "\\brf\\b" + << "\\brq\\b" + << "\\brt\\b" + << "\\bbyte[\\s\\[]" + << "\\bword[\\s\\[]" + << "\\bdword[\\s\\[]" + << "\\bfword[\\s\\[]" + << "\\bpword[\\s\\[]" + << "\\bqword[\\s\\[]" + << "\\btword[\\s\\[]" + << "\\bdqword[\\s\\[]" + << "\\bxword[\\s\\[]" + << "\\bqqword[\\s\\[]" + << "\\byword[\\s\\[]" + << "\\btbyte[\\s\\[]" + << "\\bdup\\b" + << "\\bfile\\b" + << "\\bptr\\b" + << "\\blabel\\b"; + foreach (const QString& pattern, memoryPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - //numbers - rule.format = numberFormat; - rule.pattern = QRegExp("\\b[\\-\\+]?\\d+[bod]?\\b"); - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b0[bo]\\d+\\b"); - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b[0-9A-Fa-f]+h\\b"); //hexadecimal notation - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b0[xh][0-9A-Fa-f]+\\b"); //hexadecimal notation - highlightingRules.append(rule); + // labels + rule.pattern = QRegExp("\\S+:"); + rule.format = labelFormat; + highlightingRules.append(rule); - //registers - QStringList registerPatterns; - registerPatterns << "\\beax\\b" << "\\bebx\\b" << "\\becx\\b" << - "\\bedx\\b" << "\\bebp\\b" << "\\besp\\b" << - "\\bedi\\b" << "\\besi\\b" << "\\bax\\b" << - "\\bbx\\b" << "\\bcx\\b" << "\\bdx\\b" << - "\\bbp\\b" << "\\bsp\\b" << "\\bsi\\b" << - "\\bdi\\b" << "\\bal\\b" << "\\bah\\b" << - "\\bbl\\b" << "\\bbh\\b" << "\\bcl\\b" << - "\\bch\\b" << "\\bdl\\b" << "\\bdh\\b" << - "\\brax\\b" << "\\brbx\\b" << "\\brcx\\b" << //x64 - "\\brdx\\b" << "\\brbp\\b" << "\\brsp\\b" << - "\\brdi\\b" << "\\brsi\\b" << "\\bspl\\b" << - "\\bbpl\\b" << "\\bsil\\b" << "\\bdil\\b" << - "\\br8\\b" << "\\br8d\\b" << "\\br8w\\b" << - "\\br8b\\b" << "\\br9\\b" << "\\br9d\\b" << - "\\br9w\\b" << "\\br9b\\b" << "\\br10\\b" << - "\\br10d\\b" << "\\br10w\\b" << "\\br10b\\b" << - "\\br11\\b" << "\\br11d\\b" << "\\br11w\\b" << - "\\br11b\\b" << "\\br12\\b" << "\\br12d\\b" << - "\\br12w\\b" << "\\br12b\\b" << "\\br13\\b" << - "\\br13d\\b" << "\\br13w\\b" << "\\br13b\\b" << - "\\br14\\b" << "\\br14d\\b" << "\\br14w\\b" << - "\\br14b\\b" << "\\br15\\b" << "\\br15d\\b" << - "\\br15w\\b" << "\\br15b\\b"; - foreach (const QString &pattern, registerPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - rule.format = registerFormat; - highlightingRules.append(rule); - } + // numbers + rule.format = numberFormat; + rule.pattern = QRegExp("\\b[\\-\\+]?\\d+[bod]?\\b"); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b0[bo]\\d+\\b"); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b[0-9A-Fa-f]+h\\b"); // hexadecimal notation + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b0[xh][0-9A-Fa-f]+\\b"); // hexadecimal notation + highlightingRules.append(rule); - //.labels and numbers with point - rule.pattern = QRegExp("\\.[^\\s:]+[^:]"); - rule.format = labelWithDotFormat; - highlightingRules.append(rule); - rule.pattern = QRegExp("\\.[^\\s:]+:"); - rule.format = labelFormat; - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b[\\-\\+]?\\d+\\.\\d+\\b"); - rule.format = numberFormat; + // registers + QStringList registerPatterns; + registerPatterns << "\\beax\\b" + << "\\bebx\\b" + << "\\becx\\b" + << "\\bedx\\b" + << "\\bebp\\b" + << "\\besp\\b" + << "\\bedi\\b" + << "\\besi\\b" + << "\\bax\\b" + << "\\bbx\\b" + << "\\bcx\\b" + << "\\bdx\\b" + << "\\bbp\\b" + << "\\bsp\\b" + << "\\bsi\\b" + << "\\bdi\\b" + << "\\bal\\b" + << "\\bah\\b" + << "\\bbl\\b" + << "\\bbh\\b" + << "\\bcl\\b" + << "\\bch\\b" + << "\\bdl\\b" + << "\\bdh\\b" + << "\\brax\\b" + << "\\brbx\\b" + << "\\brcx\\b" << // x64 + "\\brdx\\b" + << "\\brbp\\b" + << "\\brsp\\b" + << "\\brdi\\b" + << "\\brsi\\b" + << "\\bspl\\b" + << "\\bbpl\\b" + << "\\bsil\\b" + << "\\bdil\\b" + << "\\br8\\b" + << "\\br8d\\b" + << "\\br8w\\b" + << "\\br8b\\b" + << "\\br9\\b" + << "\\br9d\\b" + << "\\br9w\\b" + << "\\br9b\\b" + << "\\br10\\b" + << "\\br10d\\b" + << "\\br10w\\b" + << "\\br10b\\b" + << "\\br11\\b" + << "\\br11d\\b" + << "\\br11w\\b" + << "\\br11b\\b" + << "\\br12\\b" + << "\\br12d\\b" + << "\\br12w\\b" + << "\\br12b\\b" + << "\\br13\\b" + << "\\br13d\\b" + << "\\br13w\\b" + << "\\br13b\\b" + << "\\br14\\b" + << "\\br14d\\b" + << "\\br14w\\b" + << "\\br14b\\b" + << "\\br15\\b" + << "\\br15d\\b" + << "\\br15w\\b" + << "\\br15b\\b"; + foreach (const QString& pattern, registerPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); + rule.format = registerFormat; highlightingRules.append(rule); + } - //system instructions and preprocessor commands - rule.format = systemFormat; - QStringList systemPatterns; - systemPatterns << "\\bformat\\b" << "\\buse16\\b" << "\\buse32\\b" << - "\\bbinary\\b" << "\\bMZ\\b" << "\\bsegment\\b" << - "\\bPE\\b" << "\\bstack\\b" << "\\bheap\\b" << - "\\bconsole\\b" << "\\bnative\\b" << "\\bGUI\\b" << - "\\bEFI\\b" << "\\bEFIboot\\b" << "\\bEFIruntime\\b" << - "\\bDLL\\b" << "\\bWDM\\b" << "\\blarge\\b" << - "\\bat\\b" << "\\bon\\b" << "\\bPE64\\b" << - "\\bsection\\b" << "\\bcode\\b" << "\\bdata\\b" << - "\\breadable\\b" << "\\bwriteable\\b" << "\\bexecutable\\b" << - "\\bshareable\\b" << "\\bdiscardable\\b" << "\\bnotpageable\\b" << - "\\bexport\\b" << "\\bimport\\b" << "\\bresource\\b" << - "\\bfixups\\b" << "\\bentry\\b" << - "\\brva\\b" << "\\bCOFF\\b" << "\\bMS COFF\\b" << - "\\bMS64 COFF\\b" << "\\blinkremove\\b" << "\\blinkinfo\\b" << - "\\bmod\\b" << "\\bshort\\b" << - "\\bnear\\b" << "\\bfar\\b" << - "\\bextrn\\b" << "\\bpublic\\b" << - "\\bas\\b" << "\\bstatic\\b" << "\\bELF\\b" << - "\\bELF64\\b" << "\\bplt\\b" << "\\binterpreter\\b" << - "\\bdynamic\\b" << "\\bnote\\b" << "\\bif\\b" << - "\\belse\\b" << "\\bend\\b" << "\\bused\\b" << - "\\bdefined\\b" << "\\brelativeto\\b" << "\\beq\\b" << - "\\bin\\b" << "\\beqtype\\b" << "\\btimes\\b" << - "\\brepeat\\b" << "\\bbreak\\b" << "\\bwhile\\b" << - "\\borg\\b" << "\\bload\\b" << "\\bfrom\\b" << - "\\bstore\\b" << "\\bvirtual\\b" << "\\balign\\b" << - "\\bdisplay\\b" << "\\berr\\b" << "\\bassert\\b" << - "\\binclude\\b" << "\\brestore\\b" << "\\bmacro\\b" << - "\\bpurge\\b" << "\\bforward\\b" << "\\breverse\\b" << - "\\bcommon\\b" << "\\bstruc\\b" << "\\brept\\b" << - "\\birp\\b" << "\\birps\\b" << "\\bmatch\\b" << - "\\bfix\\b"; - foreach (const QString &pattern, systemPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } + //.labels and numbers with point + rule.pattern = QRegExp("\\.[^\\s:]+[^:]"); + rule.format = labelWithDotFormat; + highlightingRules.append(rule); + rule.pattern = QRegExp("\\.[^\\s:]+:"); + rule.format = labelFormat; + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b[\\-\\+]?\\d+\\.\\d+\\b"); + rule.format = numberFormat; + highlightingRules.append(rule); - //quotations - rule.pattern = QRegExp("\".*\""); - rule.format = quotationFormat; - rule.pattern.setMinimal(true); + // system instructions and preprocessor commands + rule.format = systemFormat; + QStringList systemPatterns; + systemPatterns << "\\bformat\\b" + << "\\buse16\\b" + << "\\buse32\\b" + << "\\bbinary\\b" + << "\\bMZ\\b" + << "\\bsegment\\b" + << "\\bPE\\b" + << "\\bstack\\b" + << "\\bheap\\b" + << "\\bconsole\\b" + << "\\bnative\\b" + << "\\bGUI\\b" + << "\\bEFI\\b" + << "\\bEFIboot\\b" + << "\\bEFIruntime\\b" + << "\\bDLL\\b" + << "\\bWDM\\b" + << "\\blarge\\b" + << "\\bat\\b" + << "\\bon\\b" + << "\\bPE64\\b" + << "\\bsection\\b" + << "\\bcode\\b" + << "\\bdata\\b" + << "\\breadable\\b" + << "\\bwriteable\\b" + << "\\bexecutable\\b" + << "\\bshareable\\b" + << "\\bdiscardable\\b" + << "\\bnotpageable\\b" + << "\\bexport\\b" + << "\\bimport\\b" + << "\\bresource\\b" + << "\\bfixups\\b" + << "\\bentry\\b" + << "\\brva\\b" + << "\\bCOFF\\b" + << "\\bMS COFF\\b" + << "\\bMS64 COFF\\b" + << "\\blinkremove\\b" + << "\\blinkinfo\\b" + << "\\bmod\\b" + << "\\bshort\\b" + << "\\bnear\\b" + << "\\bfar\\b" + << "\\bextrn\\b" + << "\\bpublic\\b" + << "\\bas\\b" + << "\\bstatic\\b" + << "\\bELF\\b" + << "\\bELF64\\b" + << "\\bplt\\b" + << "\\binterpreter\\b" + << "\\bdynamic\\b" + << "\\bnote\\b" + << "\\bif\\b" + << "\\belse\\b" + << "\\bend\\b" + << "\\bused\\b" + << "\\bdefined\\b" + << "\\brelativeto\\b" + << "\\beq\\b" + << "\\bin\\b" + << "\\beqtype\\b" + << "\\btimes\\b" + << "\\brepeat\\b" + << "\\bbreak\\b" + << "\\bwhile\\b" + << "\\borg\\b" + << "\\bload\\b" + << "\\bfrom\\b" + << "\\bstore\\b" + << "\\bvirtual\\b" + << "\\balign\\b" + << "\\bdisplay\\b" + << "\\berr\\b" + << "\\bassert\\b" + << "\\binclude\\b" + << "\\brestore\\b" + << "\\bmacro\\b" + << "\\bpurge\\b" + << "\\bforward\\b" + << "\\breverse\\b" + << "\\bcommon\\b" + << "\\bstruc\\b" + << "\\brept\\b" + << "\\birp\\b" + << "\\birps\\b" + << "\\bmatch\\b" + << "\\bfix\\b"; + foreach (const QString& pattern, systemPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - rule.pattern = QRegExp("'.*'"); - rule.pattern.setMinimal(true); - highlightingRules.append(rule); + // quotations + rule.pattern = QRegExp("\".*\""); + rule.format = quotationFormat; + rule.pattern.setMinimal(true); + highlightingRules.append(rule); - rule.pattern = QRegExp("`.*`"); - rule.pattern.setMinimal(true); - highlightingRules.append(rule); + rule.pattern = QRegExp("'.*'"); + rule.pattern.setMinimal(true); + highlightingRules.append(rule); - //comments - rule.pattern = QRegExp(";[^\n]*"); - rule.format = commentFormat; - rule.isComment = true; - highlightingRules.append(rule); - multiLineComments = false; - commentStartExpression = QRegExp(); - commentEndExpression = QRegExp(); + rule.pattern = QRegExp("`.*`"); + rule.pattern.setMinimal(true); + highlightingRules.append(rule); + + // comments + rule.pattern = QRegExp(";[^\n]*"); + rule.format = commentFormat; + rule.isComment = true; + highlightingRules.append(rule); + multiLineComments = false; + commentStartExpression = QRegExp(); + commentEndExpression = QRegExp(); } diff --git a/fasm.h b/fasm.h index c424de69..e68a50f1 100644 --- a/fasm.h +++ b/fasm.h @@ -41,8 +41,9 @@ #ifndef FASM_H #define FASM_H -#include #include +#include + #include "gccbasedassembler.h" /** @@ -55,28 +56,26 @@ * */ -class FASM : public GccBasedAssembler -{ - Q_OBJECT -public: - explicit FASM(bool x86, QObject *parent = 0); - QString getAssemblerPath(); - quint64 getMainOffset(QFile &lstOut, QString entryLabel); - void parseLstFile(QFile &lstOut, QVector &lines, quint64 offset); - void fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression); - QString getStartText(); - void putDebugString(CodeEditor *code); - QString getAssemblerOptions(); - QString getListingFilePath(QFile &lstOut); - -signals: +class FASM : public GccBasedAssembler { + Q_OBJECT + public: + explicit FASM(bool x86, QObject* parent = 0); + QString getAssemblerPath(); + quint64 getMainOffset(QFile& lstOut, QString entryLabel); + void parseLstFile(QFile& lstOut, QString& programFilePath, + QVector& lines, quint64 offset); + void fillHighligherRules(QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, + QRegExp& commentEndExpression); + QString getStartText(); + void putDebugString(CodeEditor* code); + QString getAssemblerOptions(); + QString getListingFilePath(QFile& lstOut); -public slots: + signals: + public slots: }; -#endif // FASM_H +#endif // FASM_H diff --git a/gas.cpp b/gas.cpp index f18ad3bb..551b1213 100644 --- a/gas.cpp +++ b/gas.cpp @@ -45,409 +45,747 @@ * Implements the GAS assembler. */ -GAS::GAS(bool x86, QObject *parent) : - GccBasedAssembler(x86, parent) -{ -} +GAS::GAS(bool x86, QObject* parent) : GccBasedAssembler(x86, parent) {} -QString GAS::getAssemblerPath() -{ - #ifdef Q_OS_WIN32 - if (isx86()) - return Common::applicationDataPath() + "/GAS/32/as.exe"; - else - return Common::applicationDataPath() + "/GAS/64/as.exe"; - #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) - return "/usr/bin/as"; - #else - return "as"; - #endif +QString GAS::getAssemblerPath() { +#ifdef Q_OS_WIN32 + if (isx86()) return Common::applicationDataPath() + "/GAS/32/as.exe"; + else + return Common::applicationDataPath() + "/GAS/64/as.exe"; +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__DragonFly__) + return "/usr/bin/as"; +#else + return "as"; +#endif } -quint64 GAS::getMainOffset(QFile &lst, QString entryLabel) -{ - QTextStream lstStream(&lst); - QRegExp mainLabel(entryLabel + ":"); - bool flag = false; - while (!lstStream.atEnd()) { - QString line = lstStream.readLine(); - if (flag) { - if (line.length() <= 19) { //omit strings with data only - //if in list : line number, address, data and it is all (without instruction) - - //omit this string - continue; - } - QByteArray lineArr = line.toLocal8Bit(); - const char *s = lineArr.constData(); - quint64 a, b, c; - if (sscanf(s, "%llu %llx %llx", &a, &b, &c) == 3) { - if (!(b == 0 && c == 0)) { //exclude 0 0 - return b; - } - } - } else { - if (line.indexOf(mainLabel) != -1) - flag = true; +quint64 GAS::getMainOffset(QFile& lst, QString entryLabel) { + QTextStream lstStream(&lst); + QRegExp mainLabel(entryLabel + ":"); + bool flag = false; + while (!lstStream.atEnd()) { + QString line = lstStream.readLine(); + if (flag) { + if (line.length() <= 19) { // omit strings with data only + // if in list : line number, address, data and it is all (without instruction) - + // omit this string + continue; + } + QByteArray lineArr = line.toLocal8Bit(); + const char* s = lineArr.constData(); + quint64 a, b, c; + if (sscanf(s, "%llu %llx %llx", &a, &b, &c) == 3) { + if (!(b == 0 && c == 0)) { // exclude 0 0 + return b; } + } + } else { + if (line.indexOf(mainLabel) != -1) flag = true; } - return -1; + } + return -1; } -void GAS::parseLstFile(QFile &lst, QVector &lines, quint64 offset) -{ - bool inTextSection = false; - QRegExp sectionTextRegExp("\\.text"); - QRegExp sectionBssRegExp("\\.bss"); - QRegExp sectionDataRegExp("\\.data"); - QTextStream lstStream(&lst); - while (!lstStream.atEnd()) { - QString line = lstStream.readLine(); - if (line.indexOf(sectionTextRegExp) != -1) { - inTextSection = true; - } else if (line.indexOf(sectionDataRegExp) != -1 || line.indexOf(sectionBssRegExp) != -1) { - inTextSection = false; - } - if (line.length() <= 19) { //omit strings with data only - //if in list : line number, address, data and it is all (without instruction) - - //omit this string and subtract 1 from offset - continue; - } - if (inTextSection) { - QByteArray lineArr = line.toLocal8Bit(); - const char *s = lineArr.constData(); - quint64 a, b, c; - if (sscanf(s, "%llu %llx %llx", &a, &b, &c) == 3){ - if (!(b == 0 && c == 0)) { //exclude 0 0 - LineNum l; - l.numInCode = a; - l.numInMem = b + offset; - lines.append(l); - } - } +void GAS::parseLstFile(QFile& lst, QString& programFilePath, + QVector& lines, quint64 offset) { + bool inTextSection = false; + QRegExp sectionTextRegExp("\\.text"); + QRegExp sectionBssRegExp("\\.bss"); + QRegExp sectionDataRegExp("\\.data"); + QTextStream lstStream(&lst); + while (!lstStream.atEnd()) { + QString line = lstStream.readLine(); + if (line.indexOf(sectionTextRegExp) != -1) { + inTextSection = true; + } else if (line.indexOf(sectionDataRegExp) != -1 || + line.indexOf(sectionBssRegExp) != -1) { + inTextSection = false; + } + if (line.length() <= 19) { // omit strings with data only + // if in list : line number, address, data and it is all (without instruction) - + // omit this string and subtract 1 from offset + continue; + } + if (inTextSection) { + QByteArray lineArr = line.toLocal8Bit(); + const char* s = lineArr.constData(); + quint64 a, b, c; + if (sscanf(s, "%llu %llx %llx", &a, &b, &c) == 3) { + if (!(b == 0 && c == 0)) { // exclude 0 0 + LineNum l; + l.numInCode = a; + l.numInMem = b + offset; + lines.append(l); } + } } + } } -QString GAS::getStartText() -{ - if (isx86()) { - #ifdef Q_OS_WIN32 - return QString(".text\n.global _main\n_main:\n # write your code here\n xorl %eax, %eax\n ret\n"); - #else - return QString(".text\n.global main\nmain:\n # write your code here\n xorl %eax, %eax\n ret\n"); - #endif - } else { - return QString(".text\n.global main\nmain:\n # write your code here\n xorq %rax, %rax\n ret\n"); - } +QString GAS::getStartText() { + if (isx86()) { +#ifdef Q_OS_WIN32 + return QString( + ".text\n.global _main\n_main:\n # write your code here\n xorl %eax, " + "%eax\n ret\n"); +#else + return QString( + ".text\n.global main\nmain:\n # write your code here\n xorl %eax, %eax\n " + " ret\n"); +#endif + } else { + return QString( + ".text\n.global main\nmain:\n # write your code here\n xorq %rax, %rax\n " + " ret\n"); + } } -void GAS::putDebugString(CodeEditor *code) -{ - //add : mov ebp, esp for making frame for correct debugging if this code has not been added yet - int index = code->toPlainText().indexOf(QRegExp("CMAIN:|main:")); - if (index != -1) { - index = code->toPlainText().indexOf(QChar(':'), index); - int intelIndex = code->toPlainText().lastIndexOf("intel_syntax", index + 1); - int attIndex = code->toPlainText().lastIndexOf("att_syntax", index + 1); - if (intelIndex == -1 || attIndex > intelIndex) { //AT&T syntax - if (isx86()) { - if (code->toPlainText().indexOf( - QRegExp("\\s+[Mm][Oo][Vv][Ll] +%?[Ee][Ss][Pp] *, *%?[Ee][Bb][Pp]"), index + 1) != index + 1) { - QTextCursor cursor = code->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); - cursor.insertText(QString("\n movl %esp, %ebp #for correct debugging")); - } - } else { - if (code->toPlainText().indexOf( - QRegExp("\\s+[Mm][Oo][Vv][Qq] +%?[Rr][Ss][Pp] *, *%?[Rr][Bb][Pp]"), index + 1) != index + 1) { - QTextCursor cursor = code->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); - cursor.insertText(QString("\n movq %rsp, %rbp #for correct debugging")); - } - } - } else { //Intel syntax - if (isx86()) { - if (code->toPlainText().indexOf( - QRegExp("\\s+[Mm][Oo][Vv] +%?[Ee][Bb][Pp] *, *%?[Ee][Ss][Pp]"), index + 1) != index + 1) { - QTextCursor cursor = code->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); - cursor.insertText(QString("\n mov %ebp, %esp #for correct debugging")); - } - } else { - if (code->toPlainText().indexOf( - QRegExp("\\s+[Mm][Oo][Vv] +%?[Rr][Bb][Pp] *, *%?[Rr][Ss][Pp]"), index + 1) != index + 1) { - QTextCursor cursor = code->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); - cursor.insertText(QString("\n mov %rbp, %rsp #for correct debugging")); - } - } +void GAS::putDebugString(CodeEditor* code) { + // add : mov ebp, esp for making frame for correct debugging if this code has not been + // added yet + int index = code->toPlainText().indexOf(QRegExp("CMAIN:|main:")); + if (index != -1) { + index = code->toPlainText().indexOf(QChar(':'), index); + int intelIndex = code->toPlainText().lastIndexOf("intel_syntax", index + 1); + int attIndex = code->toPlainText().lastIndexOf("att_syntax", index + 1); + if (intelIndex == -1 || attIndex > intelIndex) { // AT&T syntax + if (isx86()) { + if (code->toPlainText().indexOf( + QRegExp("\\s+[Mm][Oo][Vv][Ll] +%?[Ee][Ss][Pp] *, *%?[Ee][Bb][Pp]"), + index + 1) != index + 1) { + QTextCursor cursor = code->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); + cursor.insertText(QString("\n movl %esp, %ebp #for correct debugging")); + } + } else { + if (code->toPlainText().indexOf( + QRegExp("\\s+[Mm][Oo][Vv][Qq] +%?[Rr][Ss][Pp] *, *%?[Rr][Bb][Pp]"), + index + 1) != index + 1) { + QTextCursor cursor = code->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); + cursor.insertText(QString("\n movq %rsp, %rbp #for correct debugging")); + } + } + } else { // Intel syntax + if (isx86()) { + if (code->toPlainText().indexOf( + QRegExp("\\s+[Mm][Oo][Vv] +%?[Ee][Bb][Pp] *, *%?[Ee][Ss][Pp]"), + index + 1) != index + 1) { + QTextCursor cursor = code->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); + cursor.insertText(QString("\n mov %ebp, %esp #for correct debugging")); + } + } else { + if (code->toPlainText().indexOf( + QRegExp("\\s+[Mm][Oo][Vv] +%?[Rr][Bb][Pp] *, *%?[Rr][Ss][Pp]"), + index + 1) != index + 1) { + QTextCursor cursor = code->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); + cursor.insertText(QString("\n mov %rbp, %rsp #for correct debugging")); } + } } + } } -QString GAS::getAssemblerOptions() -{ - QString options; - if (isx86()) - options = "$SOURCE$ -o $PROGRAM.OBJ$ --32 -a=$LSTOUTPUT$"; - else - options = "$SOURCE$ -o $PROGRAM.OBJ$ --64 -a=$LSTOUTPUT$"; - return options; +QString GAS::getAssemblerOptions() { + QString options; + if (isx86()) options = "$SOURCE$ -o $PROGRAM.OBJ$ --32 -a=$LSTOUTPUT$"; + else + options = "$SOURCE$ -o $PROGRAM.OBJ$ --64 -a=$LSTOUTPUT$"; + return options; } +void GAS::fillHighligherRules(QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, + QRegExp& commentEndExpression) { + typedef Assembler::HighlightingRule HighlightingRule; + QTextCharFormat& keywordFormat = *formats[0]; + QTextCharFormat& registerFormat = *formats[1]; + QTextCharFormat& numberFormat = *formats[2]; + QTextCharFormat& memoryFormat = *formats[3]; + QTextCharFormat& labelFormat = *formats[4]; + QTextCharFormat& commentFormat = *formats[5]; + QTextCharFormat& systemFormat = *formats[6]; + // QTextCharFormat &iomacrosFormat = *formats[7]; + QTextCharFormat& quotationFormat = *formats[8]; + QTextCharFormat& labelWithDotFormat = *formats[9]; -void GAS::fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression) -{ - typedef Assembler::HighlightingRule HighlightingRule; - QTextCharFormat &keywordFormat = *formats[0]; - QTextCharFormat ®isterFormat = *formats[1]; - QTextCharFormat &numberFormat = *formats[2]; - QTextCharFormat &memoryFormat = *formats[3]; - QTextCharFormat &labelFormat = *formats[4]; - QTextCharFormat &commentFormat = *formats[5]; - QTextCharFormat &systemFormat = *formats[6]; - //QTextCharFormat &iomacrosFormat = *formats[7]; - QTextCharFormat "ationFormat = *formats[8]; - QTextCharFormat &labelWithDotFormat = *formats[9]; - - //setting up regular expressions - HighlightingRule rule; - - //keywords - QStringList keywordPatterns; - keywordPatterns << "\\bAAA\\b" << "\\bAAD\\b" << "\\bAAM\\b" << "\\bAAS\\b" << - "\\bADC\\b" << "\\bADD\\b" << "\\bAND\\b" << "\\bCALL\\b" << - "\\bCBW\\b" << "\\bCLC\\b" << "\\bCLD\\b" << "\\bCLI\\b" << - "\\bCMC\\b" << "\\bCMP\\b" << "\\bCMPSB\\b" << "\\bCMPSW\\b" << - "\\bCWD\\b" << "\\bDAA\\b" << "\\bDAS\\b" << "\\bDEC\\b" << - "\\bDIV\\b" << "\\bESC\\b" << "\\bHLT\\b" << "\\bIDIV\\b" << - "\\bIMUL\\b" << "\\bIN\\b" << "\\bINC\\b" << "\\bINT\\b" << - "\\bINTO\\b" << "\\bIRET\\b" << "\\bJA\\b" << "\\bJAE\\b" << - "\\bJB\\b" << "\\bJBE\\b" << "\\bJC\\b" << "\\bJCXZ\\b" << - "\\bJE\\b" << "\\bJG\\b" << "\\bJGE\\b" << "\\bJL\\b" << - "\\bJLE\\b" << "\\bJNA\\b" << "\\bJNAE\\b" << "\\bJNB\\b" << - "\\bJNBE\\b" << "\\bJNC\\b" << "\\bJNE\\b" << "\\bJNG\\b" << - "\\bJNGE\\b" << "\\bJNL\\b" << "\\bJNLE\\b" << "\\bJNO\\b" << - "\\bJNP\\b" << "\\bJNS\\b" << "\\bJNZ\\b" << "\\bJO\\b" << - "\\bJP\\b" << "\\bJPE\\b" << "\\bJPO\\b" << "\\bJS\\b" << - "\\bJZ\\b" << "\\bJMP\\b" << "\\bLAHF\\b" << "\\bLDS\\b" << - "\\bLEA\\b" << "\\bLES\\b" << "\\bLOCK\\b" << "\\bLODSB\\b" << - "\\bLODSW\\b" << "\\bLOOP\\b" << "\\bLOOPE\\b" << "\\bLOOPNE\\b" << - "\\bLOOPNZ\\b" << "\\bLOOPZ\\b" << "\\bMOV\\b" << "\\bMOVSB\\b" << - "\\bMOVSW\\b" << "\\bMUL\\b" << "\\bNEG\\b" << "\\bNOP\\b" << - "\\bNOT\\b" << "\\bOR\\b" << "\\bOUT\\b" << "\\bPOP\\b" << - "\\bPOPF\\b" << "\\bPUSH\\b" << "\\bPUSHF\\b" << "\\bRCL\\b" << - "\\bRCR\\b" << "\\bREP\\b" << "\\bREPE\\b" << "\\bREPNE\\b" << - "\\bREPNZ\\b" << "\\bREPZ\\b" << "\\bRET\\b" << "\\bRETN\\b" << - "\\bRETF\\b" << "\\bROL\\b" << "\\bROR\\b" << "\\bSAHF\\b" << - "\\bSAL\\b" << "\\bSAR\\b" << "\\bSBB\\b" << "\\bSCASB\\b" << - "\\bSCASW\\b" << "\\bSHL\\b" << "\\bSHR\\b" << "\\bSTC\\b" << - "\\bSTD\\b" << "\\bSTI\\b" << "\\bSTOSB\\b" << "\\bSTOSW\\b" << - "\\bSUB\\b" << "\\bTEST\\b" << "\\bWAIT\\b" << "\\bXCHG\\b" << - "\\bXLAT\\b" << "\\bXOR\\b" << "\\bBOUND\\b" << "\\bENTER\\b" << - "\\bINS\\b" << "\\bLEAVE\\b" << "\\bOUTS\\b" << "\\bPOPA\\b" << - "\\bPUSHA\\b" << "\\bARPL\\b" << "\\bCLTS\\b" << "\\bLAR\\b" << - "\\bLGDT\\b" << "\\bLIDT\\b" << "\\bLLDT\\b" << "\\bLMSW\\b" << - "\\bLOADALL\\b" << "\\bLSL\\b" << "\\bLTR\\b" << "\\bSGDT\\b" << - "\\bSIDT\\b" << "\\bSLDT\\b" << "\\bSMSW\\b" << "\\bSTR\\b" << - "\\bVERR\\b" << "\\bVERW\\b" << "\\bBSF\\b" << "\\bBSR\\b" << - "\\bBT\\b" << "\\bBTC\\b" << "\\bBTR\\b" << "\\bBTS\\b" << - "\\bCDQ\\b" << "\\bCMPSD\\b" << "\\bCWDE\\b" << "\\bINSD\\b" << - "\\bIRET\\b" << "\\bIRETW\\b" << "\\bIRETD\\b" << "\\bJCXZ\\b" << - "\\bJECXZ\\b" << "\\bLFS\\b" << "\\bLGS\\b" << "\\bLSS\\b" << - "\\bLODSD\\b" << "\\bMOVSD\\b" << "\\bMOVSX\\b" << "\\bMOVZX\\b" << - "\\bOUTSD\\b" << "\\bPOPAD\\b" << "\\bPOPFD\\b" << "\\bPUSHAD\\b" << - "\\bPUSHFD\\b" << "\\bSCASD\\b" << "\\bSETA\\b" << "\\bSETAE\\b" << - "\\bSETB\\b" << "\\bSETBE\\b" << "\\bSETC\\b" << "\\bSETE\\b" << - "\\bSETG\\b" << "\\bSETGE\\b" << "\\bSETL\\b" << "\\bSETLE\\b" << - "\\bSETNA\\b" << "\\bSETNAE\\b" << "\\bSETNB\\b" << "\\bSETNBE\\b" << - "\\bSETNC\\b" << "\\bSETNE\\b" << "\\bSETNG\\b" << "\\bSETNGE\\b" << - "\\bSETNL\\b" << "\\bSETNLE\\b" << "\\bSETNO\\b" << "\\bSETNP\\b" << - "\\bSETNS\\b" << "\\bSETNZ\\b" << "\\bSETO\\b" << "\\bSETP\\b" << - "\\bSETPE\\b" << "\\bSETPO\\b" << "\\bSETS\\b" << "\\bSETZ\\b" << - "\\bSHLD\\b" << "\\bSHRD\\b" << "\\bSTOSD\\b" << - "\\bPOPAD\\b" << "\\bPOPFD\\b" << "\\bPUSHAD\\b" << "\\bPUSHFD\\b" << - "\\bSCASD\\b" << "\\bBSWAP\\b" << "\\bCMPXCHG\\b" << "\\bINVD\\b" << - "\\bINVLPG\\b" << "\\bWBINVD\\b" << "\\bXADD\\b" << "\\bCPUID\\b" << - "\\bCMPXCHG8B\\b" << "\\bRDMSR\\b" << "\\bRDTSC\\b" << "\\bWRMSR\\b" << - "\\bRSM\\b" << "\\bRDPMC\\b" << "\\bCMOVA\\b" << "\\bCMOVAE\\b" << - "\\bCMOVB\\b" << "\\bCMOVBE\\b" << "\\bCMOVC\\b" << "\\bCMOVE\\b" << - "\\bCMOVG\\b" << "\\bCMOVGE\\b" << "\\bCMOVL\\b" << "\\bCMOVLE\\b" << - "\\bCMOVNA\\b" << "\\bCMOVNAE\\b" << "\\bCMOVNB\\b" << "\\bCMOVNBE\\b" << - "\\bCMOVNC\\b" << "\\bCMOVNE\\b" << "\\bCMOVNG\\b" << "\\bCMOVNGE\\b" << - "\\bCMOVNL\\b" << "\\bCMOVNLE\\b" << "\\bCMOVNO\\b" << "\\bCMOVNP\\b" << - "\\bCMOVNS\\b" << "\\bCMOVNZ\\b" << "\\bCMOVO\\b" << "\\bCMOVP\\b" << - "\\bCMOVPE\\b" << "\\bCMOVPO\\b" << "\\bCMOVS\\b" << "\\bCMOVZ\\b" << - "\\bF2XM1\\b" << "\\bFABS\\b" << "\\bFADD\\b" << "\\bFADDP\\b" << - "\\bFBLD\\b" << "\\bFBSTP\\b" << "\\bFCHS\\b" << "\\bFCLEX\\b" << - "\\bFCOM\\b" << "\\bFCOMP\\b" << "\\bFCOMPP\\b" << "\\bFDECSTP\\b" << - "\\bFDISI\\b" << "\\bFDIV\\b" << "\\bFDIVP\\b" << "\\bFDIVR\\b" << - "\\bFDIVRP\\b" << "\\bFENI\\b" << "\\bFFREE\\b" << "\\bFIADD\\b" << - "\\bFICOM\\b" << "\\bFICOMP\\b" << "\\bFIDIV\\b" << "\\bFIDIVR\\b" << - "\\bFILD\\b" << "\\bFIMUL\\b" << "\\bFINCSTP\\b" << "\\bFINIT\\b" << - "\\bFIST\\b" << "\\bFISTP\\b" << "\\bFISUB\\b" << "\\bFISUBR\\b" << - "\\bFLD\\b" << "\\bFLD1\\b" << "\\bFLDCW\\b" << "\\bFLDENV\\b" << - "\\bFLDENVW\\b" << "\\bFLDL2E\\b" << "\\bFLDL2T\\b" << "\\bFLDLG2\\b" << - "\\bFLDLN2\\b" << "\\bFLDPI\\b" << "\\bFLDZ\\b" << "\\bFMUL\\b" << - "\\bFMULP\\b" << "\\bFNCLEX\\b" << "\\bFNDISI\\b" << "\\bFNENI\\b" << - "\\bFNINIT\\b" << "\\bFNOP\\b" << "\\bFNSAVE\\b" << "\\bFNSAVEW\\b" << - "\\bFNSTCW\\b" << "\\bFNSTENV\\b" << "\\bFNSTENVW\\b" << "\\bFNSTSW\\b" << - "\\bFPATAN\\b" << "\\bFPREM\\b" << "\\bFPTAN\\b" << "\\bFRNDINT\\b" << - "\\bFRSTOR\\b" << "\\bFRSTORW\\b" << "\\bFSAVE\\b" << "\\bFSAVEW\\b" << - "\\bFSCALE\\b" << "\\bFSQRT\\b" << "\\bFST\\b" << "\\bFSTCW\\b" << - "\\bFSTENV\\b" << "\\bFSTENVW\\b" << "\\bFSTP\\b" << "\\bFSTSW\\b" << - "\\bFSUB\\b" << "\\bFSUBP\\b" << "\\bFSUBR\\b" << "\\bFSUBRP\\b" << - "\\bFTST\\b" << "\\bFWAIT\\b" << "\\bFXAM\\b" << "\\bFXCH\\b" << - "\\bFXTRACT\\b" << "\\bFYL2X\\b" << "\\bFYL2XP1\\b" << "\\bFSETPM\\b" << - "\\bFCOS\\b" << "\\bFLDENVD\\b" << "\\bFSAVED\\b" << "\\bFSTENVD\\b" << - "\\bFPREM1\\b" << "\\bFRSTORD\\b" << "\\bFSIN\\b" << "\\bFSINCOS\\b" << - "\\bFSTENVD\\b" << "\\bFUCOM\\b" << "\\bFUCOMP\\b" << "\\bFUCOMPP\\b" << - "\\bFCMOVB\\b" << "\\bFCMOVBE\\b" << "\\bFCMOVE\\b" << "\\bFCMOVNB\\b" << - "\\bFCMOVNBE\\b" << "\\bFCMOVNE\\b" << "\\bFCMOVNU\\b" << "\\bFCMOVU\\b" << - "\\bFCOMI\\b" << "\\bFCOMIP\\b" << "\\bFUCOMI\\b" << "\\bFUCOMIP\\b" << - "\\bCDQE\\b" << "\\bCQO\\b" << "\\bMOVMSKPS\\b" << "\\bMOVMSKPD\\b" << - "\\bPOPCNT\\b" << "\\bLZCNT\\b" << "\\bCMPSQ\\b" << "\\bSCASQ\\b" << - "\\bMOVSQ\\b" << "\\bLODSQ\\b" << "\\bSTOSQ\\b" << "\\bJRCXZ\\b" << - "\\bIRETQ\\b" << "\\bPUSHFQ\\b" << "\\bPOPFQ\\b" << "\\bCMPXCHG16B\\b" << - "\\bJRCXZ\\b" << "\\bINSB\\b" << "\\bINSW\\b" << "\\bOUTSB\\b" << - "\\bOUTSW\\b" << "\\bLFENCE\\b" << "\\bSFENCE\\b" << "\\bMFENCE\\b" << - "\\bPREFETCH\\b" << "\\bPREFETCHL\\b" << "\\bPREFETCHW\\b" << "\\bCLFLUSH\\b" << - "\\bSYSENTER\\b" << "\\bSYSEXIT\\b" << "\\bSYSCALL\\b" << "\\bSYSRET\\b"; - foreach (QString pattern, keywordPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - rule.format = keywordFormat; - highlightingRules.append(rule); - //with prefix - int index = pattern.length() - 2; - pattern.insert(index, 'b'); - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - pattern[index] = 'w'; - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - pattern[index] = 'l'; - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - pattern[index] = 'q'; - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } + // setting up regular expressions + HighlightingRule rule; - //memory - rule.format = memoryFormat; - QStringList memoryPatterns; - memoryPatterns << "\\(" << "\\)"; - foreach (const QString &pattern, memoryPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } - - //labels - rule.pattern = QRegExp("\\S+:"); - rule.format = labelFormat; + // keywords + QStringList keywordPatterns; + keywordPatterns << "\\bAAA\\b" + << "\\bAAD\\b" + << "\\bAAM\\b" + << "\\bAAS\\b" + << "\\bADC\\b" + << "\\bADD\\b" + << "\\bAND\\b" + << "\\bCALL\\b" + << "\\bCBW\\b" + << "\\bCLC\\b" + << "\\bCLD\\b" + << "\\bCLI\\b" + << "\\bCMC\\b" + << "\\bCMP\\b" + << "\\bCMPSB\\b" + << "\\bCMPSW\\b" + << "\\bCWD\\b" + << "\\bDAA\\b" + << "\\bDAS\\b" + << "\\bDEC\\b" + << "\\bDIV\\b" + << "\\bESC\\b" + << "\\bHLT\\b" + << "\\bIDIV\\b" + << "\\bIMUL\\b" + << "\\bIN\\b" + << "\\bINC\\b" + << "\\bINT\\b" + << "\\bINTO\\b" + << "\\bIRET\\b" + << "\\bJA\\b" + << "\\bJAE\\b" + << "\\bJB\\b" + << "\\bJBE\\b" + << "\\bJC\\b" + << "\\bJCXZ\\b" + << "\\bJE\\b" + << "\\bJG\\b" + << "\\bJGE\\b" + << "\\bJL\\b" + << "\\bJLE\\b" + << "\\bJNA\\b" + << "\\bJNAE\\b" + << "\\bJNB\\b" + << "\\bJNBE\\b" + << "\\bJNC\\b" + << "\\bJNE\\b" + << "\\bJNG\\b" + << "\\bJNGE\\b" + << "\\bJNL\\b" + << "\\bJNLE\\b" + << "\\bJNO\\b" + << "\\bJNP\\b" + << "\\bJNS\\b" + << "\\bJNZ\\b" + << "\\bJO\\b" + << "\\bJP\\b" + << "\\bJPE\\b" + << "\\bJPO\\b" + << "\\bJS\\b" + << "\\bJZ\\b" + << "\\bJMP\\b" + << "\\bLAHF\\b" + << "\\bLDS\\b" + << "\\bLEA\\b" + << "\\bLES\\b" + << "\\bLOCK\\b" + << "\\bLODSB\\b" + << "\\bLODSW\\b" + << "\\bLOOP\\b" + << "\\bLOOPE\\b" + << "\\bLOOPNE\\b" + << "\\bLOOPNZ\\b" + << "\\bLOOPZ\\b" + << "\\bMOV\\b" + << "\\bMOVSB\\b" + << "\\bMOVSW\\b" + << "\\bMUL\\b" + << "\\bNEG\\b" + << "\\bNOP\\b" + << "\\bNOT\\b" + << "\\bOR\\b" + << "\\bOUT\\b" + << "\\bPOP\\b" + << "\\bPOPF\\b" + << "\\bPUSH\\b" + << "\\bPUSHF\\b" + << "\\bRCL\\b" + << "\\bRCR\\b" + << "\\bREP\\b" + << "\\bREPE\\b" + << "\\bREPNE\\b" + << "\\bREPNZ\\b" + << "\\bREPZ\\b" + << "\\bRET\\b" + << "\\bRETN\\b" + << "\\bRETF\\b" + << "\\bROL\\b" + << "\\bROR\\b" + << "\\bSAHF\\b" + << "\\bSAL\\b" + << "\\bSAR\\b" + << "\\bSBB\\b" + << "\\bSCASB\\b" + << "\\bSCASW\\b" + << "\\bSHL\\b" + << "\\bSHR\\b" + << "\\bSTC\\b" + << "\\bSTD\\b" + << "\\bSTI\\b" + << "\\bSTOSB\\b" + << "\\bSTOSW\\b" + << "\\bSUB\\b" + << "\\bTEST\\b" + << "\\bWAIT\\b" + << "\\bXCHG\\b" + << "\\bXLAT\\b" + << "\\bXOR\\b" + << "\\bBOUND\\b" + << "\\bENTER\\b" + << "\\bINS\\b" + << "\\bLEAVE\\b" + << "\\bOUTS\\b" + << "\\bPOPA\\b" + << "\\bPUSHA\\b" + << "\\bARPL\\b" + << "\\bCLTS\\b" + << "\\bLAR\\b" + << "\\bLGDT\\b" + << "\\bLIDT\\b" + << "\\bLLDT\\b" + << "\\bLMSW\\b" + << "\\bLOADALL\\b" + << "\\bLSL\\b" + << "\\bLTR\\b" + << "\\bSGDT\\b" + << "\\bSIDT\\b" + << "\\bSLDT\\b" + << "\\bSMSW\\b" + << "\\bSTR\\b" + << "\\bVERR\\b" + << "\\bVERW\\b" + << "\\bBSF\\b" + << "\\bBSR\\b" + << "\\bBT\\b" + << "\\bBTC\\b" + << "\\bBTR\\b" + << "\\bBTS\\b" + << "\\bCDQ\\b" + << "\\bCMPSD\\b" + << "\\bCWDE\\b" + << "\\bINSD\\b" + << "\\bIRET\\b" + << "\\bIRETW\\b" + << "\\bIRETD\\b" + << "\\bJCXZ\\b" + << "\\bJECXZ\\b" + << "\\bLFS\\b" + << "\\bLGS\\b" + << "\\bLSS\\b" + << "\\bLODSD\\b" + << "\\bMOVSD\\b" + << "\\bMOVSX\\b" + << "\\bMOVZX\\b" + << "\\bOUTSD\\b" + << "\\bPOPAD\\b" + << "\\bPOPFD\\b" + << "\\bPUSHAD\\b" + << "\\bPUSHFD\\b" + << "\\bSCASD\\b" + << "\\bSETA\\b" + << "\\bSETAE\\b" + << "\\bSETB\\b" + << "\\bSETBE\\b" + << "\\bSETC\\b" + << "\\bSETE\\b" + << "\\bSETG\\b" + << "\\bSETGE\\b" + << "\\bSETL\\b" + << "\\bSETLE\\b" + << "\\bSETNA\\b" + << "\\bSETNAE\\b" + << "\\bSETNB\\b" + << "\\bSETNBE\\b" + << "\\bSETNC\\b" + << "\\bSETNE\\b" + << "\\bSETNG\\b" + << "\\bSETNGE\\b" + << "\\bSETNL\\b" + << "\\bSETNLE\\b" + << "\\bSETNO\\b" + << "\\bSETNP\\b" + << "\\bSETNS\\b" + << "\\bSETNZ\\b" + << "\\bSETO\\b" + << "\\bSETP\\b" + << "\\bSETPE\\b" + << "\\bSETPO\\b" + << "\\bSETS\\b" + << "\\bSETZ\\b" + << "\\bSHLD\\b" + << "\\bSHRD\\b" + << "\\bSTOSD\\b" + << "\\bPOPAD\\b" + << "\\bPOPFD\\b" + << "\\bPUSHAD\\b" + << "\\bPUSHFD\\b" + << "\\bSCASD\\b" + << "\\bBSWAP\\b" + << "\\bCMPXCHG\\b" + << "\\bINVD\\b" + << "\\bINVLPG\\b" + << "\\bWBINVD\\b" + << "\\bXADD\\b" + << "\\bCPUID\\b" + << "\\bCMPXCHG8B\\b" + << "\\bRDMSR\\b" + << "\\bRDTSC\\b" + << "\\bWRMSR\\b" + << "\\bRSM\\b" + << "\\bRDPMC\\b" + << "\\bCMOVA\\b" + << "\\bCMOVAE\\b" + << "\\bCMOVB\\b" + << "\\bCMOVBE\\b" + << "\\bCMOVC\\b" + << "\\bCMOVE\\b" + << "\\bCMOVG\\b" + << "\\bCMOVGE\\b" + << "\\bCMOVL\\b" + << "\\bCMOVLE\\b" + << "\\bCMOVNA\\b" + << "\\bCMOVNAE\\b" + << "\\bCMOVNB\\b" + << "\\bCMOVNBE\\b" + << "\\bCMOVNC\\b" + << "\\bCMOVNE\\b" + << "\\bCMOVNG\\b" + << "\\bCMOVNGE\\b" + << "\\bCMOVNL\\b" + << "\\bCMOVNLE\\b" + << "\\bCMOVNO\\b" + << "\\bCMOVNP\\b" + << "\\bCMOVNS\\b" + << "\\bCMOVNZ\\b" + << "\\bCMOVO\\b" + << "\\bCMOVP\\b" + << "\\bCMOVPE\\b" + << "\\bCMOVPO\\b" + << "\\bCMOVS\\b" + << "\\bCMOVZ\\b" + << "\\bF2XM1\\b" + << "\\bFABS\\b" + << "\\bFADD\\b" + << "\\bFADDP\\b" + << "\\bFBLD\\b" + << "\\bFBSTP\\b" + << "\\bFCHS\\b" + << "\\bFCLEX\\b" + << "\\bFCOM\\b" + << "\\bFCOMP\\b" + << "\\bFCOMPP\\b" + << "\\bFDECSTP\\b" + << "\\bFDISI\\b" + << "\\bFDIV\\b" + << "\\bFDIVP\\b" + << "\\bFDIVR\\b" + << "\\bFDIVRP\\b" + << "\\bFENI\\b" + << "\\bFFREE\\b" + << "\\bFIADD\\b" + << "\\bFICOM\\b" + << "\\bFICOMP\\b" + << "\\bFIDIV\\b" + << "\\bFIDIVR\\b" + << "\\bFILD\\b" + << "\\bFIMUL\\b" + << "\\bFINCSTP\\b" + << "\\bFINIT\\b" + << "\\bFIST\\b" + << "\\bFISTP\\b" + << "\\bFISUB\\b" + << "\\bFISUBR\\b" + << "\\bFLD\\b" + << "\\bFLD1\\b" + << "\\bFLDCW\\b" + << "\\bFLDENV\\b" + << "\\bFLDENVW\\b" + << "\\bFLDL2E\\b" + << "\\bFLDL2T\\b" + << "\\bFLDLG2\\b" + << "\\bFLDLN2\\b" + << "\\bFLDPI\\b" + << "\\bFLDZ\\b" + << "\\bFMUL\\b" + << "\\bFMULP\\b" + << "\\bFNCLEX\\b" + << "\\bFNDISI\\b" + << "\\bFNENI\\b" + << "\\bFNINIT\\b" + << "\\bFNOP\\b" + << "\\bFNSAVE\\b" + << "\\bFNSAVEW\\b" + << "\\bFNSTCW\\b" + << "\\bFNSTENV\\b" + << "\\bFNSTENVW\\b" + << "\\bFNSTSW\\b" + << "\\bFPATAN\\b" + << "\\bFPREM\\b" + << "\\bFPTAN\\b" + << "\\bFRNDINT\\b" + << "\\bFRSTOR\\b" + << "\\bFRSTORW\\b" + << "\\bFSAVE\\b" + << "\\bFSAVEW\\b" + << "\\bFSCALE\\b" + << "\\bFSQRT\\b" + << "\\bFST\\b" + << "\\bFSTCW\\b" + << "\\bFSTENV\\b" + << "\\bFSTENVW\\b" + << "\\bFSTP\\b" + << "\\bFSTSW\\b" + << "\\bFSUB\\b" + << "\\bFSUBP\\b" + << "\\bFSUBR\\b" + << "\\bFSUBRP\\b" + << "\\bFTST\\b" + << "\\bFWAIT\\b" + << "\\bFXAM\\b" + << "\\bFXCH\\b" + << "\\bFXTRACT\\b" + << "\\bFYL2X\\b" + << "\\bFYL2XP1\\b" + << "\\bFSETPM\\b" + << "\\bFCOS\\b" + << "\\bFLDENVD\\b" + << "\\bFSAVED\\b" + << "\\bFSTENVD\\b" + << "\\bFPREM1\\b" + << "\\bFRSTORD\\b" + << "\\bFSIN\\b" + << "\\bFSINCOS\\b" + << "\\bFSTENVD\\b" + << "\\bFUCOM\\b" + << "\\bFUCOMP\\b" + << "\\bFUCOMPP\\b" + << "\\bFCMOVB\\b" + << "\\bFCMOVBE\\b" + << "\\bFCMOVE\\b" + << "\\bFCMOVNB\\b" + << "\\bFCMOVNBE\\b" + << "\\bFCMOVNE\\b" + << "\\bFCMOVNU\\b" + << "\\bFCMOVU\\b" + << "\\bFCOMI\\b" + << "\\bFCOMIP\\b" + << "\\bFUCOMI\\b" + << "\\bFUCOMIP\\b" + << "\\bCDQE\\b" + << "\\bCQO\\b" + << "\\bMOVMSKPS\\b" + << "\\bMOVMSKPD\\b" + << "\\bPOPCNT\\b" + << "\\bLZCNT\\b" + << "\\bCMPSQ\\b" + << "\\bSCASQ\\b" + << "\\bMOVSQ\\b" + << "\\bLODSQ\\b" + << "\\bSTOSQ\\b" + << "\\bJRCXZ\\b" + << "\\bIRETQ\\b" + << "\\bPUSHFQ\\b" + << "\\bPOPFQ\\b" + << "\\bCMPXCHG16B\\b" + << "\\bJRCXZ\\b" + << "\\bINSB\\b" + << "\\bINSW\\b" + << "\\bOUTSB\\b" + << "\\bOUTSW\\b" + << "\\bLFENCE\\b" + << "\\bSFENCE\\b" + << "\\bMFENCE\\b" + << "\\bPREFETCH\\b" + << "\\bPREFETCHL\\b" + << "\\bPREFETCHW\\b" + << "\\bCLFLUSH\\b" + << "\\bSYSENTER\\b" + << "\\bSYSEXIT\\b" + << "\\bSYSCALL\\b" + << "\\bSYSRET\\b"; + foreach (QString pattern, keywordPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); + rule.format = keywordFormat; highlightingRules.append(rule); - - //numbers - rule.format = numberFormat; - rule.pattern = QRegExp("\\b[\\-\\+]?\\d+[bod]?\\b"); + // with prefix + int index = pattern.length() - 2; + pattern.insert(index, 'b'); + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); - rule.pattern = QRegExp("\\b0[bo]\\d+\\b"); + pattern[index] = 'w'; + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); - rule.pattern = QRegExp("\\b[0-9A-Fa-f]+h\\b"); //hexadecimal notation + pattern[index] = 'l'; + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); - rule.pattern = QRegExp("\\b0[xh][0-9A-Fa-f]+\\b"); //hexadecimal notation + pattern[index] = 'q'; + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - //registers - QStringList registerPatterns; - registerPatterns << "\\beax\\b" << "\\bebx\\b" << "\\becx\\b" << - "\\bedx\\b" << "\\bebp\\b" << "\\besp\\b" << - "\\bedi\\b" << "\\besi\\b" << "\\bax\\b" << - "\\bbx\\b" << "\\bcx\\b" << "\\bdx\\b" << - "\\bbp\\b" << "\\bsp\\b" << "\\bsi\\b" << - "\\bdi\\b" << "\\bal\\b" << "\\bah\\b" << - "\\bbl\\b" << "\\bbh\\b" << "\\bcl\\b" << - "\\bch\\b" << "\\bdl\\b" << "\\bdh\\b" << - "\\brax\\b" << "\\brbx\\b" << "\\brcx\\b" << //x64 - "\\brdx\\b" << "\\brbp\\b" << "\\brsp\\b" << - "\\brdi\\b" << "\\brsi\\b" << "\\bspl\\b" << - "\\bbpl\\b" << "\\bsil\\b" << "\\bdil\\b" << - "\\br8\\b" << "\\br8d\\b" << "\\br8w\\b" << - "\\br8b\\b" << "\\br9\\b" << "\\br9d\\b" << - "\\br9w\\b" << "\\br9b\\b" << "\\br10\\b" << - "\\br10d\\b" << "\\br10w\\b" << "\\br10b\\b" << - "\\br11\\b" << "\\br11d\\b" << "\\br11w\\b" << - "\\br11b\\b" << "\\br12\\b" << "\\br12d\\b" << - "\\br12w\\b" << "\\br12b\\b" << "\\br13\\b" << - "\\br13d\\b" << "\\br13w\\b" << "\\br13b\\b" << - "\\br14\\b" << "\\br14d\\b" << "\\br14w\\b" << - "\\br14b\\b" << "\\br15\\b" << "\\br15d\\b" << - "\\br15w\\b" << "\\br15b\\b"; - foreach (const QString &pattern, registerPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - rule.format = registerFormat; - highlightingRules.append(rule); - rule.pattern = QRegExp('%' + pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } - - //.labels and numbers with point - rule.pattern = QRegExp("\\.[^\\s:]+[^:]"); - rule.format = labelWithDotFormat; + // memory + rule.format = memoryFormat; + QStringList memoryPatterns; + memoryPatterns << "\\(" + << "\\)"; + foreach (const QString& pattern, memoryPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); - rule.pattern = QRegExp("\\.[^\\s:]+:"); - rule.format = labelFormat; + } + + // labels + rule.pattern = QRegExp("\\S+:"); + rule.format = labelFormat; + highlightingRules.append(rule); + + // numbers + rule.format = numberFormat; + rule.pattern = QRegExp("\\b[\\-\\+]?\\d+[bod]?\\b"); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b0[bo]\\d+\\b"); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b[0-9A-Fa-f]+h\\b"); // hexadecimal notation + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b0[xh][0-9A-Fa-f]+\\b"); // hexadecimal notation + highlightingRules.append(rule); + + // registers + QStringList registerPatterns; + registerPatterns << "\\beax\\b" + << "\\bebx\\b" + << "\\becx\\b" + << "\\bedx\\b" + << "\\bebp\\b" + << "\\besp\\b" + << "\\bedi\\b" + << "\\besi\\b" + << "\\bax\\b" + << "\\bbx\\b" + << "\\bcx\\b" + << "\\bdx\\b" + << "\\bbp\\b" + << "\\bsp\\b" + << "\\bsi\\b" + << "\\bdi\\b" + << "\\bal\\b" + << "\\bah\\b" + << "\\bbl\\b" + << "\\bbh\\b" + << "\\bcl\\b" + << "\\bch\\b" + << "\\bdl\\b" + << "\\bdh\\b" + << "\\brax\\b" + << "\\brbx\\b" + << "\\brcx\\b" << // x64 + "\\brdx\\b" + << "\\brbp\\b" + << "\\brsp\\b" + << "\\brdi\\b" + << "\\brsi\\b" + << "\\bspl\\b" + << "\\bbpl\\b" + << "\\bsil\\b" + << "\\bdil\\b" + << "\\br8\\b" + << "\\br8d\\b" + << "\\br8w\\b" + << "\\br8b\\b" + << "\\br9\\b" + << "\\br9d\\b" + << "\\br9w\\b" + << "\\br9b\\b" + << "\\br10\\b" + << "\\br10d\\b" + << "\\br10w\\b" + << "\\br10b\\b" + << "\\br11\\b" + << "\\br11d\\b" + << "\\br11w\\b" + << "\\br11b\\b" + << "\\br12\\b" + << "\\br12d\\b" + << "\\br12w\\b" + << "\\br12b\\b" + << "\\br13\\b" + << "\\br13d\\b" + << "\\br13w\\b" + << "\\br13b\\b" + << "\\br14\\b" + << "\\br14d\\b" + << "\\br14w\\b" + << "\\br14b\\b" + << "\\br15\\b" + << "\\br15d\\b" + << "\\br15w\\b" + << "\\br15b\\b"; + foreach (const QString& pattern, registerPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); + rule.format = registerFormat; highlightingRules.append(rule); - rule.pattern = QRegExp("\\b[\\-\\+]?\\d+\\.\\d+\\b"); - rule.format = numberFormat; + rule.pattern = QRegExp('%' + pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - //system instructions and preprocessor commands - rule.format = systemFormat; - QStringList systemPatterns; - systemPatterns << "\\.\\w+\\b"; - foreach (const QString &pattern, systemPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } + //.labels and numbers with point + rule.pattern = QRegExp("\\.[^\\s:]+[^:]"); + rule.format = labelWithDotFormat; + highlightingRules.append(rule); + rule.pattern = QRegExp("\\.[^\\s:]+:"); + rule.format = labelFormat; + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b[\\-\\+]?\\d+\\.\\d+\\b"); + rule.format = numberFormat; + highlightingRules.append(rule); - //quotations - rule.pattern = QRegExp("\".*\""); - rule.pattern.setMinimal(true); - rule.format = quotationFormat; + // system instructions and preprocessor commands + rule.format = systemFormat; + QStringList systemPatterns; + systemPatterns << "\\.\\w+\\b"; + foreach (const QString& pattern, systemPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - rule.pattern = QRegExp("'.*'"); - rule.pattern.setMinimal(true); - highlightingRules.append(rule); + // quotations + rule.pattern = QRegExp("\".*\""); + rule.pattern.setMinimal(true); + rule.format = quotationFormat; + highlightingRules.append(rule); - rule.pattern = QRegExp("`.*`"); - rule.pattern.setMinimal(true); - highlightingRules.append(rule); + rule.pattern = QRegExp("'.*'"); + rule.pattern.setMinimal(true); + highlightingRules.append(rule); - //comments - commentStartExpression = QRegExp("/\\*"); - commentEndExpression = QRegExp("[^\\\\]\\*/"); - rule.format = commentFormat; - rule.pattern = QRegExp("#[^\n]*"); - rule.isComment = true; - highlightingRules.append(rule); - multiLineComments = true; + rule.pattern = QRegExp("`.*`"); + rule.pattern.setMinimal(true); + highlightingRules.append(rule); + + // comments + commentStartExpression = QRegExp("/\\*"); + commentEndExpression = QRegExp("[^\\\\]\\*/"); + rule.format = commentFormat; + rule.pattern = QRegExp("#[^\n]*"); + rule.isComment = true; + highlightingRules.append(rule); + multiLineComments = true; } diff --git a/gas.h b/gas.h index b32d0a14..bdb7027d 100644 --- a/gas.h +++ b/gas.h @@ -52,26 +52,24 @@ * */ -class GAS : public GccBasedAssembler -{ - Q_OBJECT -public: - explicit GAS(bool x86, QObject *parent = 0); - QString getAssemblerPath(); - quint64 getMainOffset(QFile &lst, QString entryLabel); - void parseLstFile(QFile &lst, QVector &lines, quint64 offset); - void fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression); - QString getStartText(); - void putDebugString(CodeEditor *code); - QString getAssemblerOptions(); -signals: - -public slots: - +class GAS : public GccBasedAssembler { + Q_OBJECT + public: + explicit GAS(bool x86, QObject* parent = 0); + QString getAssemblerPath(); + quint64 getMainOffset(QFile& lst, QString entryLabel); + void parseLstFile(QFile& lst, QString& programFilePath, + QVector& lines, quint64 offset); + void fillHighligherRules(QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, + QRegExp& commentEndExpression); + QString getStartText(); + void putDebugString(CodeEditor* code); + QString getAssemblerOptions(); + signals: + + public slots: }; -#endif // GAS_H +#endif // GAS_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 03be5505..f40ce9a8 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -45,1855 +45,1831 @@ * Code for all of the windows and features. */ -MainWindow::MainWindow(const QStringList &args, QWidget *parent) - : QMainWindow(parent), settings("SASM Project", "SASM") -{ - setWindowTitle("SASM"); - setWindowIcon(QIcon(":images/mainIcon.png")); - - //! Set save and open directory - saveOpenDirectory = settings.value("saveopendirectory", QString(Common::applicationDataPath() + "/Projects")).toString(); - - //! Initial variables - programIsBuilded = false; - prevCodeEditor = 0; - findDialog = 0; - settingsWindow = 0; - closeFromCloseAll = false; - settingsStartTextEditor = 0; - help = 0; - registersWindow = 0; - memoryWindow = 0; - debugger = 0; - programStopped = true; - highlighter = 0; - tabs = 0; - memoryDock = 0; - registersDock = 0; - - //! Initialize assembler - assembler = 0; - recreateAssembler(true); - - //! Set code field start text - startText = settings.value("starttext", QString()).toString(); - if (startText.isEmpty()) { - settings.setValue("starttext", assembler->getStartText()); - startText = assembler->getStartText(); - } - - timer = new QTimer; - timer->setInterval(100); - timer->stop(); - connect(timer, SIGNAL(timeout()), this, SLOT(testStopOfProgram())); - runProcess = new QProcess(); - - initUi(); - createActions(); - createMenus(); - createToolBars(); - refreshEditMenu(); - setAcceptDrops(true); - - //! Restore log splitter state - splitter->restoreState(settings.value("logsplitterstate").toByteArray()); - - //! Open documents from command line - for (int i = 1; i < args.size(); i++) - openFile(args[i]); -} - -void MainWindow::enableOrDisableLinkingEdit(int disableLinkingCheckboxState) -{ - bool enabled = (disableLinkingCheckboxState == Qt::Unchecked); - settingsUi.linkingOptionsEdit->setEnabled(enabled); - settingsUi.linkerPathEdit->setEnabled(enabled); -} - -void MainWindow::initUi() -{ - //! Resize - settings.beginGroup("MainWindow"); - resize(settings.value("size", QSize(1024, 650)).toSize()); //default 1024x650 - move(settings.value("pos", QPoint(200, 200)).toPoint()); - //! Set maximized - setWindowState(windowState() | (Qt::WindowState) settings.value("maximized", (int) Qt::WindowNoState).toInt()); - settings.endGroup(); - - //! Get Started window - getStartedWidget = new GetStartedWidget; - connect(getStartedWidget->newButton, SIGNAL(clicked()), this, SLOT(newFile())); - connect(getStartedWidget->openButton, SIGNAL(clicked()), this, SLOT(openFile())); - connect(getStartedWidget->prevSessionButton, SIGNAL(clicked()), this, SLOT(restorePrevSession())); - - //! Create form - splitter = new QSplitter; - splitter->setOrientation(Qt::Vertical); - workLayout = new QVBoxLayout; - workLayout->addWidget(splitter); - workLayout->setMargin(0); - workLayout->setSpacing(0); - workWidget = new QWidget; - workWidget->setLayout(workLayout); - - //! Stacked widget - mainWidget = new QStackedWidget; - mainWidget->addWidget(getStartedWidget); - mainWidget->addWidget(workWidget); - mainWidget->setCurrentIndex(0); //get started - setCentralWidget(mainWidget); - - //! Create highlighter - highlighter = new Highlighter(assembler); - - //! Create tabs - tabs = new QTabWidget; - connect(tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(deleteTab(int))); - connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(changeCurrentTab(int))); - tabs->setTabsClosable(true); - tabs->setMovable(true); - - //! Create compiler field - compilerOut = new RuQTextEdit; - compilerOut->setReadOnly(true); - QFont compilerOutFont; - compilerOutFont.setPointSize(settings.value("fontsize", 12).toInt()); - compilerOut->setFont(compilerOutFont); - compilerOut->setText(tr("Build log:") + '\n'); - - //! Create gdb command widget - debugAnyCommandWidget = new DebugAnyCommandWidget; - - //! Add widgets on splitter - splitter->addWidget(tabs); - splitter->addWidget(compilerOut); - workLayout->addWidget(debugAnyCommandWidget); - int compilerOutSize = 100; - debugAnyCommandWidget->close(); - debugAnyCommandWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - splitter->setSizes(QList() << splitter->size().height() - compilerOutSize << compilerOutSize); - //! Restore previous session if it in settings - if (settings.value("startwindow", 0).toInt() == 1) - restorePrevSession(true); -} - -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("File")); - fileMenu->addAction(newAction); - fileMenu->addSeparator(); - fileMenu->addAction(openAction); - fileMenu->addAction(closeAction); - fileMenu->addSeparator(); - fileMenu->addAction(saveAction); - fileMenu->addAction(saveAsAction); - fileMenu->addAction(saveExeAction); - fileMenu->addSeparator(); - fileMenu->addAction(exitAction); - editMenu = menuBar()->addMenu(tr("Edit")); - editMenu->addAction(findAction); - editMenu->addSeparator(); - editMenu->addAction(undoAction); - editMenu->addAction(redoAction); - editMenu->addSeparator(); - editMenu->addAction(cutAction); - editMenu->addAction(copyAction); - editMenu->addAction(pasteAction); - editMenu->addAction(deleteAction); - editMenu->addSeparator(); - editMenu->addAction(selectAllAction); - editMenu->addSeparator(); - editMenu->addAction(commentAction); - editMenu->addAction(uncommentAction); - editMenu->addSeparator(); - editMenu->addAction(putTabAction); - editMenu->addAction(deleteTabAction); - connect(editMenu, SIGNAL(aboutToShow()), this, SLOT(refreshEditMenu())); - connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(refreshEditMenu())); - buildMenu = menuBar()->addMenu(tr("Build")); - buildMenu->addAction(buildAction); - buildMenu->addSeparator(); - buildMenu->addAction(runAction); - #ifdef Q_OS_WIN32 - buildMenu->addAction(runExeAction); - #endif - buildMenu->addSeparator(); - buildMenu->addAction(stopAction); - debugMenu = menuBar()->addMenu(tr("Debug")); - debugMenu->addAction(debugAction); - debugMenu->addSeparator(); - debugMenu->addAction(debugNextNiAction); - debugMenu->addAction(debugNextAction); - debugMenu->addSeparator(); - debugMenu->addAction(debugToggleBreakpointAction); - debugMenu->addAction(debugShowRegistersAction); - debugMenu->addAction(debugShowMemoryAction); - debugMenu->addSeparator(); - debugMenu->addAction(stopAction); - settingsMenu = menuBar()->addMenu(tr("Settings")); - settingsMenu->addAction(settingsAction); - helpMenu = menuBar()->addMenu(tr("Help")); - helpMenu->addAction(helpAction); - helpMenu->addAction(aboutAction); -} - -void MainWindow::createActions() -{ - QSettings keySettings(Common::applicationDataPath() + "/keys.ini", QSettings::IniFormat); - - newAction = new QAction(QIcon(":/images/new.png"), tr("New"), this); - QString key = keySettings.value("new", "default").toString(); - QKeySequence stdKey(QKeySequence::New); - if (key == "default") - key = stdKey.toString(); - newAction->setShortcut(key); - connect(newAction, SIGNAL(triggered()), this, SLOT(newFile())); - - openAction = new QAction(QIcon(":/images/open.png"), tr("Open"), this); - key = keySettings.value("open", "default").toString(); - stdKey = QKeySequence(QKeySequence::Open); - if (key == "default") - key = stdKey.toString(); - openAction->setShortcut(key); - connect(openAction, SIGNAL(triggered()), this, SLOT(openFile())); - - closeAction = new QAction(tr("Close file"), this); - key = keySettings.value("close", "default").toString(); - stdKey = QKeySequence(QKeySequence::Close); - if (key == "default") - key = stdKey.toString(); - closeAction->setShortcut(key); - connect(closeAction, SIGNAL(triggered()), this, SLOT(closeFile())); - - - saveAction = new QAction(QIcon(":/images/save.png"), tr("Save"), this); - key = keySettings.value("save", "default").toString(); - stdKey = QKeySequence(QKeySequence::Save); - if (key == "default") - key = stdKey.toString(); - saveAction->setShortcut(key); - connect(saveAction, SIGNAL(triggered()), this, SLOT(saveFile())); - - saveAsAction = new QAction(tr("Save as"), this); - key = keySettings.value("saveAs", "default").toString(); - stdKey = QKeySequence(QKeySequence::SaveAs); - if (key == "default") - key = stdKey.toString(); - saveAsAction->setShortcut(key); - connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAsFile())); - - saveExeAction = new QAction(tr("Save .exe"), this); - key = keySettings.value("save_exe", "default").toString(); - if (key == "default") - key = "Ctrl+Shift+E"; - saveExeAction->setShortcut(QKeySequence(key)); - connect(saveExeAction, SIGNAL(triggered()), this, SLOT(saveExe())); - - exitAction = new QAction(tr("Exit"), this); - key = keySettings.value("exit", "default").toString(); - stdKey = QKeySequence(QString("Ctrl+Q")); - if (key == "default") - key = stdKey.toString(); - exitAction->setShortcut(key); - connect(exitAction, SIGNAL(triggered()), this, SLOT(closeApp())); - - findAction = new QAction(tr("Find and replace"), this); - key = keySettings.value("find", "default").toString(); - stdKey = QKeySequence(QKeySequence::Find); - if (key == "default") - key = stdKey.toString(); - findAction->setShortcut(key); - connect(findAction, SIGNAL(triggered()), this, SLOT(find())); - - - undoAction = new QAction(QIcon(":/images/undo.png"), tr("Undo"), this); - key = keySettings.value("undo", "default").toString(); - stdKey = QKeySequence(QKeySequence::Undo); - if (key == "default") - key = stdKey.toString(); - undoAction->setShortcut(key); - - redoAction = new QAction(QIcon(":/images/redo.png"), tr("Redo"), this); - key = keySettings.value("redo", "default").toString(); - stdKey = QKeySequence(QKeySequence::Redo); - if (key == "default") - key = stdKey.toString(); - redoAction->setShortcut(key); - - cutAction = new QAction(QIcon(":/images/cut.png"), tr("Cut"), this); - key = keySettings.value("cut", "default").toString(); - stdKey = QKeySequence(QKeySequence::Cut); - if (key == "default") - key = stdKey.toString(); - cutAction->setShortcut(key); - - copyAction = new QAction(QIcon(":/images/copy.png"), tr("Copy"), this); - key = keySettings.value("copy", "default").toString(); - stdKey = QKeySequence(QKeySequence::Copy); - if (key == "default") - key = stdKey.toString(); - copyAction->setShortcut(key); - - pasteAction = new QAction(QIcon(":/images/paste.png"), tr("Paste"), this); - key = keySettings.value("paste", "default").toString(); - stdKey = QKeySequence(QKeySequence::Paste); - if (key == "default") - key = stdKey.toString(); - pasteAction->setShortcut(key); - - deleteAction = new QAction(tr("Delete"), this); - key = keySettings.value("delete", "default").toString(); - stdKey = QKeySequence(QKeySequence::Delete); - if (key == "default") - key = stdKey.toString(); - deleteAction->setShortcut(key); - - selectAllAction = new QAction(tr("Select all"), this); - key = keySettings.value("selectAll", "default").toString(); - stdKey = QKeySequence(QKeySequence::SelectAll); - if (key == "default") - key = stdKey.toString(); - selectAllAction->setShortcut(key); - - commentAction = new QAction(tr("Comment"), this); - key = keySettings.value("comment", "default").toString(); - stdKey = QKeySequence(QString("Shift+Ctrl+A")); - if (key == "default") - key = stdKey.toString(); - commentAction->setShortcut(key); - - uncommentAction = new QAction(tr("Remove comment"), this); - key = keySettings.value("uncomment", "default").toString(); - stdKey = QKeySequence(QString("Shift+Ctrl+Q")); - if (key == "default") - key = stdKey.toString(); - uncommentAction->setShortcut(key); - - putTabAction = new QAction(tr("Indent"), this); - key = keySettings.value("putTab", "default").toString(); - stdKey = QKeySequence(QString("Tab")); - if (key == "default") - key = stdKey.toString(); - putTabAction->setShortcut(key); - - deleteTabAction = new QAction(tr("Remove indent"), this); - key = keySettings.value("deleteTab", "default").toString(); - stdKey = QKeySequence(QString("Shift+Tab")); - if (key == "default") - key = stdKey.toString(); - deleteTabAction->setShortcut(key); - //! Action in edit menu connects in refreshEditMenu function! - - - buildAction = new QAction(QIcon(":/images/build.png"), tr("Build this"), this); - key = keySettings.value("build", "default").toString(); - stdKey = QKeySequence(QString("Ctrl+F9")); - if (key == "default") - key = stdKey.toString(); - buildAction->setShortcut(key); - connect(buildAction, SIGNAL(triggered()), this, SLOT(buildProgram())); - - runAction = new QAction(QIcon(":/images/run.png"), tr("Build and run"), this); - key = keySettings.value("run", "default").toString(); - stdKey = QKeySequence(QString("F9")); - if (key == "default") - key = stdKey.toString(); - runAction->setShortcut(key); - connect(runAction, SIGNAL(triggered()), this, SLOT(runProgram())); - - runExeAction = new QAction(tr("Run in new window"), this); - connect(runExeAction, SIGNAL(triggered()), this, SLOT(runExeProgram())); - - stopAction = new QAction(QIcon(":/images/stop.png"), tr("Stop"), this); - connect(stopAction, SIGNAL(triggered()), this, SLOT(stopProgram())); - //! Enable in runProgram(), disable in stop - stopAction->setEnabled(false); - - debugAction = new QAction(QIcon(":/images/debug.png"), tr("Debug"), this); - key = keySettings.value("debug", "default").toString(); - stdKey = QKeySequence(QString("F5")); - if (key == "default") - key = stdKey.toString(); - debugAction->setShortcut(key); - debugKey = key; - connect(debugAction, SIGNAL(triggered()), this, SLOT(debug())); - - debugNextNiAction = new QAction(QIcon(":/images/stepover.png"), tr("Step over"), this); - key = keySettings.value("stepOver", "default").toString(); - stdKey = QKeySequence(QString("F10")); - if (key == "default") - key = stdKey.toString(); - debugNextNiAction->setShortcut(key); - connect(debugNextNiAction, SIGNAL(triggered()), this, SLOT(debugNextNi())); - - debugNextAction = new QAction(QIcon(":/images/stepinto.png"), tr("Step into"), this); - key = keySettings.value("stepInto", "default").toString(); - stdKey = QKeySequence(QString("F11")); - if (key == "default") - key = stdKey.toString(); - debugNextAction->setShortcut(key); - connect(debugNextAction, SIGNAL(triggered()), this, SLOT(debugNext())); - - debugToggleBreakpointAction = new QAction(tr("Toggle breakpoint"), this); - key = keySettings.value("breakpoint", "default").toString(); - stdKey = QKeySequence(QString("F8")); - if (key == "default") - key = stdKey.toString(); - debugToggleBreakpointAction->setShortcut(key); - connect(debugToggleBreakpointAction, SIGNAL(triggered()), this, SLOT(debugToggleBreakpoint())); - - debugShowRegistersAction = new QAction(tr("Show registers"), this); - key = keySettings.value("showRegisters", "default").toString(); - stdKey = QKeySequence(QString("Ctrl+R")); - if (key == "default") - key = stdKey.toString(); - debugShowRegistersAction->setShortcut(key); - debugShowRegistersAction->setCheckable(true); - connect(debugShowRegistersAction, SIGNAL(toggled(bool)), this, SLOT(debugShowRegisters()), Qt::QueuedConnection); - - debugShowMemoryAction = new QAction(tr("Show memory"), this); - key = keySettings.value("showMemory", "default").toString(); - stdKey = QKeySequence(QString("Ctrl+M")); - if (key == "default") - key = stdKey.toString(); - debugShowMemoryAction->setShortcut(key); - debugShowMemoryAction->setCheckable(true); - connect(debugShowMemoryAction, SIGNAL(toggled(bool)), this, SLOT(debugShowMemory()), Qt::QueuedConnection); - - disableDebugActions(true); - - - settingsAction = new QAction(tr("Settings"), this); - connect(settingsAction, SIGNAL(triggered()), this, SLOT(openSettings())); - - connect(mainWidget, SIGNAL(currentChanged(int)), this, SLOT(changeActionsState(int))); - //! Disable some actions if get started widget opened - changeActionsState(mainWidget->currentIndex()); - - helpAction = new QAction(tr("Help"), this); - key = keySettings.value("help", "default").toString(); - stdKey = QKeySequence(QKeySequence::HelpContents); - if (key == "default") - key = stdKey.toString(); - helpAction->setShortcut(key); - connect(helpAction, SIGNAL(triggered()), this, SLOT(openHelp())); - - aboutAction = new QAction(tr("About"), this); - connect(aboutAction, SIGNAL(triggered()), this, SLOT(openAbout())); -} - -void MainWindow::createToolBars() -{ - fileToolBar = addToolBar(tr("File")); - fileToolBar->addAction(newAction); - fileToolBar->addAction(openAction); - fileToolBar->addAction(saveAction); - fileToolBar->setObjectName("File"); - - editToolBar = addToolBar(tr("Edit")); - editToolBar->addAction(undoAction); - editToolBar->addAction(redoAction); - editToolBar->addAction(cutAction); - editToolBar->addAction(copyAction); - editToolBar->addAction(pasteAction); - editToolBar->setObjectName("Edit"); - - buildToolBar = addToolBar(tr("Build")); - buildToolBar->addAction(buildAction); - buildToolBar->addAction(runAction); - buildToolBar->addAction(stopAction); - buildToolBar->setObjectName("Build"); - - debugToolBar = addToolBar(tr("Debug")); - debugToolBar->addAction(debugAction); - debugToolBar->addAction(debugNextNiAction); - debugToolBar->addAction(debugNextAction); - debugToolBar->addAction(stopAction); - debugToolBar->setObjectName("Debug"); - - restoreState(settings.value("windowstate").toByteArray()); -} - -void MainWindow::refreshEditMenu() -{ - CodeEditor *codeEditor = 0; - - //! Disconnect from previous - if (prevCodeEditor) { - disconnect(commentAction, SIGNAL(triggered()), prevCodeEditor, SLOT(commentSelectedCode())); - disconnect(uncommentAction, SIGNAL(triggered()), prevCodeEditor, SLOT(uncommentSelectedCode())); - disconnect(undoAction, SIGNAL(triggered()), prevCodeEditor, SLOT(undo())); - disconnect(redoAction, SIGNAL(triggered()), prevCodeEditor, SLOT(redo())); - disconnect(cutAction, SIGNAL(triggered()), prevCodeEditor, SLOT(cut())); - disconnect(copyAction, SIGNAL(triggered()), prevCodeEditor, SLOT(copy())); - disconnect(pasteAction, SIGNAL(triggered()), prevCodeEditor, SLOT(paste())); - disconnect(deleteAction, SIGNAL(triggered()), prevCodeEditor, SLOT(deleteSelected())); - disconnect(selectAllAction, SIGNAL(triggered()), prevCodeEditor, SLOT(selectAll())); - disconnect(putTabAction, SIGNAL(triggered()), prevCodeEditor, SLOT(putTab())); - disconnect(deleteTabAction, SIGNAL(triggered()), prevCodeEditor, SLOT(deleteTab())); - - disconnect(prevCodeEditor, SIGNAL(undoAvailable(bool)), undoAction, SLOT(setEnabled(bool))); - disconnect(prevCodeEditor, SIGNAL(redoAvailable(bool)), redoAction, SLOT(setEnabled(bool))); - } - - //! Connect to current - if (tabs->currentIndex() != -1) { - codeEditor = ((Tab *) tabs->currentWidget())->code; - connect(commentAction, SIGNAL(triggered()), codeEditor, SLOT(commentSelectedCode())); - connect(uncommentAction, SIGNAL(triggered()), codeEditor, SLOT(uncommentSelectedCode())); - connect(undoAction, SIGNAL(triggered()), codeEditor, SLOT(undo())); - connect(redoAction, SIGNAL(triggered()), codeEditor, SLOT(redo())); - connect(cutAction, SIGNAL(triggered()), codeEditor, SLOT(cut())); - connect(copyAction, SIGNAL(triggered()), codeEditor, SLOT(copy())); - connect(pasteAction, SIGNAL(triggered()), codeEditor, SLOT(paste())); - connect(deleteAction, SIGNAL(triggered()), codeEditor, SLOT(deleteSelected())); - connect(selectAllAction, SIGNAL(triggered()), codeEditor, SLOT(selectAll())); - connect(putTabAction, SIGNAL(triggered()), codeEditor, SLOT(putTab())); - connect(deleteTabAction, SIGNAL(triggered()), codeEditor, SLOT(deleteTab())); - - connect(codeEditor, SIGNAL(undoAvailable(bool)), undoAction, SLOT(setEnabled(bool))); - connect(codeEditor, SIGNAL(redoAvailable(bool)), redoAction, SLOT(setEnabled(bool))); - connect(codeEditor, SIGNAL(copyAvailable(bool)), cutAction, SLOT(setEnabled(bool))); - connect(codeEditor, SIGNAL(copyAvailable(bool)), copyAction, SLOT(setEnabled(bool))); - connect(codeEditor, SIGNAL(copyAvailable(bool)), commentAction, SLOT(setEnabled(bool))); - connect(codeEditor, SIGNAL(copyAvailable(bool)), uncommentAction, SLOT(setEnabled(bool))); - connect(codeEditor, SIGNAL(copyAvailable(bool)), deleteAction, SLOT(setEnabled(bool))); - } - - prevCodeEditor = codeEditor; -} - -void MainWindow::newFile() -{ - if (tabs->count() > 0) { - settings.setValue("tabgeometry", ((Tab *) tabs->currentWidget())->saveGeometry()); - settings.setValue("tabwindowstate", ((Tab *) tabs->currentWidget())->saveState()); - } - //! Tabs - mainWidget->setCurrentIndex(1); - Tab *tab = new Tab; - tab->code->setPlainText(startText); - tabs->addTab(tab, tr("New")); - tabs->setCurrentWidget(tab); - connect(tab->code, SIGNAL(textChanged()), this, SLOT(setProgramBuildedFlagToFalse())); - connect(tab->code, SIGNAL(modificationChanged(bool)), this, SLOT(changeCurrentSavedState(bool))); - connect(tab->code, SIGNAL(fileOpened(QString)), this, SLOT(openFile(QString))); -} - -void MainWindow::changeCurrentSavedState(bool changed) -{ - if (changed) - tabs->setTabText(tabs->currentIndex(), '*' + tabs->tabText(tabs->currentIndex())); - else { - QString tabText = tabs->tabText(tabs->currentIndex()); - if (tabText[0] == '*') - tabText.remove(0, 1); - tabs->setTabText(tabs->currentIndex(), tabText); - } -} - -void MainWindow::openFile() -{ - QString fileName = QFileDialog::getOpenFileName(this, tr("Open file"), saveOpenDirectory, - tr("Assembler source files (*.asm);;All files (*)")); - if (fileName.isEmpty()) { - return; - } - saveOpenDirectory = QFileInfo(fileName).absoluteDir().absolutePath(); - openFile(fileName); -} - -void MainWindow::openFile(QString path) -{ - if (path.isEmpty()) { - return; - } - - newFile(); - Tab *curTab = (Tab *) tabs->currentWidget(); - curTab->loadCodeFromFile(path); - setTabPath(path); - //connect(curTab, SIGNAL(fileOpened(QString)), this, SLOT(openFile(QString))); -} - -void MainWindow::setTabPath(const QString &filePath, int index) -{ - //! Taking name of file (without path) - int i; - if ((i = filePath.lastIndexOf('/')) == -1) - i = filePath.lastIndexOf('\\'); - QString caption = filePath.mid(i + 1); - if (index == -1) { - tabs->setTabToolTip(tabs->currentIndex(), filePath); - tabs->setTabText(tabs->currentIndex(), caption); - } else { - tabs->setTabToolTip(index, filePath); - tabs->setTabText(index, caption); - } -} - -void MainWindow::closeFile() -{ - deleteTab(tabs->currentIndex()); -} - -bool MainWindow::saveFile(int index, bool openSaveAs) -{ - Tab *tab; - if (index == -1) - tab = (Tab *) tabs->currentWidget(); - else - tab = (Tab *) tabs->widget(index); - QString filePath = tab->getCurrentFilePath(); - if (filePath.isEmpty()) { - if (openSaveAs) { - return saveAsFile(index); - } else { - return false; - } +MainWindow::MainWindow(const QStringList& args, QWidget* parent) + : QMainWindow(parent), settings("SASM Project", "SASM") { + setWindowTitle("SASM"); + setWindowIcon(QIcon(":images/mainIcon.png")); + + //! Set save and open directory + saveOpenDirectory = settings + .value("saveopendirectory", + QString(Common::applicationDataPath() + "/Projects")) + .toString(); + + //! Initial variables + programIsBuilded = false; + prevCodeEditor = 0; + findDialog = 0; + settingsWindow = 0; + closeFromCloseAll = false; + settingsStartTextEditor = 0; + help = 0; + registersWindow = 0; + memoryWindow = 0; + debugger = 0; + programStopped = true; + highlighter = 0; + tabs = 0; + memoryDock = 0; + registersDock = 0; + + //! Initialize assembler + assembler = 0; + recreateAssembler(true); + + //! Set code field start text + startText = settings.value("starttext", QString()).toString(); + if (startText.isEmpty()) { + settings.setValue("starttext", assembler->getStartText()); + startText = assembler->getStartText(); + } + + timer = new QTimer; + timer->setInterval(100); + timer->stop(); + connect(timer, SIGNAL(timeout()), this, SLOT(testStopOfProgram())); + runProcess = new QProcess(); + + initUi(); + createActions(); + createMenus(); + createToolBars(); + refreshEditMenu(); + setAcceptDrops(true); + + //! Restore log splitter state + splitter->restoreState(settings.value("logsplitterstate").toByteArray()); + + //! Open documents from command line + for (int i = 1; i < args.size(); i++) openFile(args[i]); +} + +void MainWindow::enableOrDisableObjectFilenameLabel(int disableCurrentDirCheckboxState) { + bool enabled = (disableCurrentDirCheckboxState == Qt::Unchecked); + settingsUi.objectFileNameEdit->setEnabled(enabled); +} + +void MainWindow::enableOrDisableLinkingEdit(int disableLinkingCheckboxState) { + bool enabled = (disableLinkingCheckboxState == Qt::Unchecked); + settingsUi.linkingOptionsEdit->setEnabled(enabled); + settingsUi.linkerPathEdit->setEnabled(enabled); +} + +void MainWindow::initUi() { + //! Resize + settings.beginGroup("MainWindow"); + resize(settings.value("size", QSize(1024, 650)).toSize()); // default 1024x650 + move(settings.value("pos", QPoint(200, 200)).toPoint()); + //! Set maximized + setWindowState( + windowState() | + (Qt::WindowState) settings.value("maximized", (int) Qt::WindowNoState).toInt()); + settings.endGroup(); + + //! Get Started window + getStartedWidget = new GetStartedWidget; + connect(getStartedWidget->newButton, SIGNAL(clicked()), this, SLOT(newFile())); + connect(getStartedWidget->openButton, SIGNAL(clicked()), this, SLOT(openFile())); + connect(getStartedWidget->prevSessionButton, SIGNAL(clicked()), this, + SLOT(restorePrevSession())); + + //! Create form + splitter = new QSplitter; + splitter->setOrientation(Qt::Vertical); + workLayout = new QVBoxLayout; + workLayout->addWidget(splitter); + workLayout->setMargin(0); + workLayout->setSpacing(0); + workWidget = new QWidget; + workWidget->setLayout(workLayout); + + //! Stacked widget + mainWidget = new QStackedWidget; + mainWidget->addWidget(getStartedWidget); + mainWidget->addWidget(workWidget); + mainWidget->setCurrentIndex(0); // get started + setCentralWidget(mainWidget); + + //! Create highlighter + highlighter = new Highlighter(assembler); + + //! Create tabs + tabs = new QTabWidget; + connect(tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(deleteTab(int))); + connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(changeCurrentTab(int))); + tabs->setTabsClosable(true); + tabs->setMovable(true); + + //! Create compiler field + compilerOut = new RuQTextEdit; + compilerOut->setReadOnly(true); + QFont compilerOutFont; + compilerOutFont.setPointSize(settings.value("fontsize", 12).toInt()); + compilerOut->setFont(compilerOutFont); + compilerOut->setText(tr("Build log:") + '\n'); + + //! Create gdb command widget + debugAnyCommandWidget = new DebugAnyCommandWidget; + + //! Add widgets on splitter + splitter->addWidget(tabs); + splitter->addWidget(compilerOut); + workLayout->addWidget(debugAnyCommandWidget); + int compilerOutSize = 100; + debugAnyCommandWidget->close(); + debugAnyCommandWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + splitter->setSizes(QList() + << splitter->size().height() - compilerOutSize << compilerOutSize); + //! Restore previous session if it in settings + if (settings.value("startwindow", 0).toInt() == 1) restorePrevSession(true); +} + +void MainWindow::createMenus() { + fileMenu = menuBar()->addMenu(tr("File")); + fileMenu->addAction(newAction); + fileMenu->addSeparator(); + fileMenu->addAction(openAction); + fileMenu->addAction(closeAction); + fileMenu->addSeparator(); + fileMenu->addAction(saveAction); + fileMenu->addAction(saveAsAction); + fileMenu->addAction(saveExeAction); + fileMenu->addSeparator(); + fileMenu->addAction(exitAction); + editMenu = menuBar()->addMenu(tr("Edit")); + editMenu->addAction(findAction); + editMenu->addSeparator(); + editMenu->addAction(undoAction); + editMenu->addAction(redoAction); + editMenu->addSeparator(); + editMenu->addAction(cutAction); + editMenu->addAction(copyAction); + editMenu->addAction(pasteAction); + editMenu->addAction(deleteAction); + editMenu->addSeparator(); + editMenu->addAction(selectAllAction); + editMenu->addSeparator(); + editMenu->addAction(commentAction); + editMenu->addAction(uncommentAction); + editMenu->addSeparator(); + editMenu->addAction(putTabAction); + editMenu->addAction(deleteTabAction); + connect(editMenu, SIGNAL(aboutToShow()), this, SLOT(refreshEditMenu())); + connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(refreshEditMenu())); + buildMenu = menuBar()->addMenu(tr("Build")); + buildMenu->addAction(buildAction); + buildMenu->addSeparator(); + buildMenu->addAction(runAction); +#ifdef Q_OS_WIN32 + buildMenu->addAction(runExeAction); +#endif + buildMenu->addSeparator(); + buildMenu->addAction(stopAction); + debugMenu = menuBar()->addMenu(tr("Debug")); + debugMenu->addAction(debugAction); + debugMenu->addSeparator(); + debugMenu->addAction(debugNextNiAction); + debugMenu->addAction(debugNextAction); + debugMenu->addSeparator(); + debugMenu->addAction(debugToggleBreakpointAction); + debugMenu->addAction(debugShowRegistersAction); + debugMenu->addAction(debugShowMemoryAction); + debugMenu->addSeparator(); + debugMenu->addAction(stopAction); + settingsMenu = menuBar()->addMenu(tr("Settings")); + settingsMenu->addAction(settingsAction); + helpMenu = menuBar()->addMenu(tr("Help")); + helpMenu->addAction(helpAction); + helpMenu->addAction(aboutAction); +} + +void MainWindow::createActions() { + QSettings keySettings(Common::applicationDataPath() + "/keys.ini", + QSettings::IniFormat); + + newAction = new QAction(QIcon(":/images/new.png"), tr("New"), this); + QString key = keySettings.value("new", "default").toString(); + QKeySequence stdKey(QKeySequence::New); + if (key == "default") key = stdKey.toString(); + newAction->setShortcut(key); + connect(newAction, SIGNAL(triggered()), this, SLOT(newFile())); + + openAction = new QAction(QIcon(":/images/open.png"), tr("Open"), this); + key = keySettings.value("open", "default").toString(); + stdKey = QKeySequence(QKeySequence::Open); + if (key == "default") key = stdKey.toString(); + openAction->setShortcut(key); + connect(openAction, SIGNAL(triggered()), this, SLOT(openFile())); + + closeAction = new QAction(tr("Close file"), this); + key = keySettings.value("close", "default").toString(); + stdKey = QKeySequence(QKeySequence::Close); + if (key == "default") key = stdKey.toString(); + closeAction->setShortcut(key); + connect(closeAction, SIGNAL(triggered()), this, SLOT(closeFile())); + + saveAction = new QAction(QIcon(":/images/save.png"), tr("Save"), this); + key = keySettings.value("save", "default").toString(); + stdKey = QKeySequence(QKeySequence::Save); + if (key == "default") key = stdKey.toString(); + saveAction->setShortcut(key); + connect(saveAction, SIGNAL(triggered()), this, SLOT(saveFile())); + + saveAsAction = new QAction(tr("Save as"), this); + key = keySettings.value("saveAs", "default").toString(); + stdKey = QKeySequence(QKeySequence::SaveAs); + if (key == "default") key = stdKey.toString(); + saveAsAction->setShortcut(key); + connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAsFile())); + + saveExeAction = new QAction(tr("Save .exe"), this); + key = keySettings.value("save_exe", "default").toString(); + if (key == "default") key = "Ctrl+Shift+E"; + saveExeAction->setShortcut(QKeySequence(key)); + connect(saveExeAction, SIGNAL(triggered()), this, SLOT(saveExe())); + + exitAction = new QAction(tr("Exit"), this); + key = keySettings.value("exit", "default").toString(); + stdKey = QKeySequence(QString("Ctrl+Q")); + if (key == "default") key = stdKey.toString(); + exitAction->setShortcut(key); + connect(exitAction, SIGNAL(triggered()), this, SLOT(closeApp())); + + findAction = new QAction(tr("Find and replace"), this); + key = keySettings.value("find", "default").toString(); + stdKey = QKeySequence(QKeySequence::Find); + if (key == "default") key = stdKey.toString(); + findAction->setShortcut(key); + connect(findAction, SIGNAL(triggered()), this, SLOT(find())); + + undoAction = new QAction(QIcon(":/images/undo.png"), tr("Undo"), this); + key = keySettings.value("undo", "default").toString(); + stdKey = QKeySequence(QKeySequence::Undo); + if (key == "default") key = stdKey.toString(); + undoAction->setShortcut(key); + + redoAction = new QAction(QIcon(":/images/redo.png"), tr("Redo"), this); + key = keySettings.value("redo", "default").toString(); + stdKey = QKeySequence(QKeySequence::Redo); + if (key == "default") key = stdKey.toString(); + redoAction->setShortcut(key); + + cutAction = new QAction(QIcon(":/images/cut.png"), tr("Cut"), this); + key = keySettings.value("cut", "default").toString(); + stdKey = QKeySequence(QKeySequence::Cut); + if (key == "default") key = stdKey.toString(); + cutAction->setShortcut(key); + + copyAction = new QAction(QIcon(":/images/copy.png"), tr("Copy"), this); + key = keySettings.value("copy", "default").toString(); + stdKey = QKeySequence(QKeySequence::Copy); + if (key == "default") key = stdKey.toString(); + copyAction->setShortcut(key); + + pasteAction = new QAction(QIcon(":/images/paste.png"), tr("Paste"), this); + key = keySettings.value("paste", "default").toString(); + stdKey = QKeySequence(QKeySequence::Paste); + if (key == "default") key = stdKey.toString(); + pasteAction->setShortcut(key); + + deleteAction = new QAction(tr("Delete"), this); + key = keySettings.value("delete", "default").toString(); + stdKey = QKeySequence(QKeySequence::Delete); + if (key == "default") key = stdKey.toString(); + deleteAction->setShortcut(key); + + selectAllAction = new QAction(tr("Select all"), this); + key = keySettings.value("selectAll", "default").toString(); + stdKey = QKeySequence(QKeySequence::SelectAll); + if (key == "default") key = stdKey.toString(); + selectAllAction->setShortcut(key); + + commentAction = new QAction(tr("Comment"), this); + key = keySettings.value("comment", "default").toString(); + stdKey = QKeySequence(QString("Shift+Ctrl+A")); + if (key == "default") key = stdKey.toString(); + commentAction->setShortcut(key); + + uncommentAction = new QAction(tr("Remove comment"), this); + key = keySettings.value("uncomment", "default").toString(); + stdKey = QKeySequence(QString("Shift+Ctrl+Q")); + if (key == "default") key = stdKey.toString(); + uncommentAction->setShortcut(key); + + putTabAction = new QAction(tr("Indent"), this); + key = keySettings.value("putTab", "default").toString(); + stdKey = QKeySequence(QString("Tab")); + if (key == "default") key = stdKey.toString(); + putTabAction->setShortcut(key); + + deleteTabAction = new QAction(tr("Remove indent"), this); + key = keySettings.value("deleteTab", "default").toString(); + stdKey = QKeySequence(QString("Shift+Tab")); + if (key == "default") key = stdKey.toString(); + deleteTabAction->setShortcut(key); + //! Action in edit menu connects in refreshEditMenu function! + + buildAction = new QAction(QIcon(":/images/build.png"), tr("Build this"), this); + key = keySettings.value("build", "default").toString(); + stdKey = QKeySequence(QString("Ctrl+F9")); + if (key == "default") key = stdKey.toString(); + buildAction->setShortcut(key); + connect(buildAction, SIGNAL(triggered()), this, SLOT(buildProgram())); + + runAction = new QAction(QIcon(":/images/run.png"), tr("Build and run"), this); + key = keySettings.value("run", "default").toString(); + stdKey = QKeySequence(QString("F9")); + if (key == "default") key = stdKey.toString(); + runAction->setShortcut(key); + connect(runAction, SIGNAL(triggered()), this, SLOT(runProgram())); + + runExeAction = new QAction(tr("Run in new window"), this); + connect(runExeAction, SIGNAL(triggered()), this, SLOT(runExeProgram())); + + stopAction = new QAction(QIcon(":/images/stop.png"), tr("Stop"), this); + connect(stopAction, SIGNAL(triggered()), this, SLOT(stopProgram())); + //! Enable in runProgram(), disable in stop + stopAction->setEnabled(false); + + debugAction = new QAction(QIcon(":/images/debug.png"), tr("Debug"), this); + key = keySettings.value("debug", "default").toString(); + stdKey = QKeySequence(QString("F5")); + if (key == "default") key = stdKey.toString(); + debugAction->setShortcut(key); + debugKey = key; + connect(debugAction, SIGNAL(triggered()), this, SLOT(debug())); + + debugNextNiAction = new QAction(QIcon(":/images/stepover.png"), tr("Step over"), this); + key = keySettings.value("stepOver", "default").toString(); + stdKey = QKeySequence(QString("F10")); + if (key == "default") key = stdKey.toString(); + debugNextNiAction->setShortcut(key); + connect(debugNextNiAction, SIGNAL(triggered()), this, SLOT(debugNextNi())); + + debugNextAction = new QAction(QIcon(":/images/stepinto.png"), tr("Step into"), this); + key = keySettings.value("stepInto", "default").toString(); + stdKey = QKeySequence(QString("F11")); + if (key == "default") key = stdKey.toString(); + debugNextAction->setShortcut(key); + connect(debugNextAction, SIGNAL(triggered()), this, SLOT(debugNext())); + + debugToggleBreakpointAction = new QAction(tr("Toggle breakpoint"), this); + key = keySettings.value("breakpoint", "default").toString(); + stdKey = QKeySequence(QString("F8")); + if (key == "default") key = stdKey.toString(); + debugToggleBreakpointAction->setShortcut(key); + connect(debugToggleBreakpointAction, SIGNAL(triggered()), this, + SLOT(debugToggleBreakpoint())); + + debugShowRegistersAction = new QAction(tr("Show registers"), this); + key = keySettings.value("showRegisters", "default").toString(); + stdKey = QKeySequence(QString("Ctrl+R")); + if (key == "default") key = stdKey.toString(); + debugShowRegistersAction->setShortcut(key); + debugShowRegistersAction->setCheckable(true); + connect(debugShowRegistersAction, SIGNAL(toggled(bool)), this, + SLOT(debugShowRegisters()), Qt::QueuedConnection); + + debugShowMemoryAction = new QAction(tr("Show memory"), this); + key = keySettings.value("showMemory", "default").toString(); + stdKey = QKeySequence(QString("Ctrl+M")); + if (key == "default") key = stdKey.toString(); + debugShowMemoryAction->setShortcut(key); + debugShowMemoryAction->setCheckable(true); + connect(debugShowMemoryAction, SIGNAL(toggled(bool)), this, SLOT(debugShowMemory()), + Qt::QueuedConnection); + + disableDebugActions(true); + + settingsAction = new QAction(tr("Settings"), this); + connect(settingsAction, SIGNAL(triggered()), this, SLOT(openSettings())); + + connect(mainWidget, SIGNAL(currentChanged(int)), this, SLOT(changeActionsState(int))); + //! Disable some actions if get started widget opened + changeActionsState(mainWidget->currentIndex()); + + helpAction = new QAction(tr("Help"), this); + key = keySettings.value("help", "default").toString(); + stdKey = QKeySequence(QKeySequence::HelpContents); + if (key == "default") key = stdKey.toString(); + helpAction->setShortcut(key); + connect(helpAction, SIGNAL(triggered()), this, SLOT(openHelp())); + + aboutAction = new QAction(tr("About"), this); + connect(aboutAction, SIGNAL(triggered()), this, SLOT(openAbout())); +} + +void MainWindow::createToolBars() { + fileToolBar = addToolBar(tr("File")); + fileToolBar->addAction(newAction); + fileToolBar->addAction(openAction); + fileToolBar->addAction(saveAction); + fileToolBar->setObjectName("File"); + + editToolBar = addToolBar(tr("Edit")); + editToolBar->addAction(undoAction); + editToolBar->addAction(redoAction); + editToolBar->addAction(cutAction); + editToolBar->addAction(copyAction); + editToolBar->addAction(pasteAction); + editToolBar->setObjectName("Edit"); + + buildToolBar = addToolBar(tr("Build")); + buildToolBar->addAction(buildAction); + buildToolBar->addAction(runAction); + buildToolBar->addAction(stopAction); + buildToolBar->setObjectName("Build"); + + debugToolBar = addToolBar(tr("Debug")); + debugToolBar->addAction(debugAction); + debugToolBar->addAction(debugNextNiAction); + debugToolBar->addAction(debugNextAction); + debugToolBar->addAction(stopAction); + debugToolBar->setObjectName("Debug"); + + restoreState(settings.value("windowstate").toByteArray()); +} + +void MainWindow::refreshEditMenu() { + CodeEditor* codeEditor = 0; + + //! Disconnect from previous + if (prevCodeEditor) { + disconnect(commentAction, SIGNAL(triggered()), prevCodeEditor, + SLOT(commentSelectedCode())); + disconnect(uncommentAction, SIGNAL(triggered()), prevCodeEditor, + SLOT(uncommentSelectedCode())); + disconnect(undoAction, SIGNAL(triggered()), prevCodeEditor, SLOT(undo())); + disconnect(redoAction, SIGNAL(triggered()), prevCodeEditor, SLOT(redo())); + disconnect(cutAction, SIGNAL(triggered()), prevCodeEditor, SLOT(cut())); + disconnect(copyAction, SIGNAL(triggered()), prevCodeEditor, SLOT(copy())); + disconnect(pasteAction, SIGNAL(triggered()), prevCodeEditor, SLOT(paste())); + disconnect(deleteAction, SIGNAL(triggered()), prevCodeEditor, SLOT(deleteSelected())); + disconnect(selectAllAction, SIGNAL(triggered()), prevCodeEditor, SLOT(selectAll())); + disconnect(putTabAction, SIGNAL(triggered()), prevCodeEditor, SLOT(putTab())); + disconnect(deleteTabAction, SIGNAL(triggered()), prevCodeEditor, SLOT(deleteTab())); + + disconnect(prevCodeEditor, SIGNAL(undoAvailable(bool)), undoAction, + SLOT(setEnabled(bool))); + disconnect(prevCodeEditor, SIGNAL(redoAvailable(bool)), redoAction, + SLOT(setEnabled(bool))); + } + + //! Connect to current + if (tabs->currentIndex() != -1) { + codeEditor = ((Tab*) tabs->currentWidget())->code; + connect(commentAction, SIGNAL(triggered()), codeEditor, SLOT(commentSelectedCode())); + connect(uncommentAction, SIGNAL(triggered()), codeEditor, + SLOT(uncommentSelectedCode())); + connect(undoAction, SIGNAL(triggered()), codeEditor, SLOT(undo())); + connect(redoAction, SIGNAL(triggered()), codeEditor, SLOT(redo())); + connect(cutAction, SIGNAL(triggered()), codeEditor, SLOT(cut())); + connect(copyAction, SIGNAL(triggered()), codeEditor, SLOT(copy())); + connect(pasteAction, SIGNAL(triggered()), codeEditor, SLOT(paste())); + connect(deleteAction, SIGNAL(triggered()), codeEditor, SLOT(deleteSelected())); + connect(selectAllAction, SIGNAL(triggered()), codeEditor, SLOT(selectAll())); + connect(putTabAction, SIGNAL(triggered()), codeEditor, SLOT(putTab())); + connect(deleteTabAction, SIGNAL(triggered()), codeEditor, SLOT(deleteTab())); + + connect(codeEditor, SIGNAL(undoAvailable(bool)), undoAction, SLOT(setEnabled(bool))); + connect(codeEditor, SIGNAL(redoAvailable(bool)), redoAction, SLOT(setEnabled(bool))); + connect(codeEditor, SIGNAL(copyAvailable(bool)), cutAction, SLOT(setEnabled(bool))); + connect(codeEditor, SIGNAL(copyAvailable(bool)), copyAction, SLOT(setEnabled(bool))); + connect(codeEditor, SIGNAL(copyAvailable(bool)), commentAction, + SLOT(setEnabled(bool))); + connect(codeEditor, SIGNAL(copyAvailable(bool)), uncommentAction, + SLOT(setEnabled(bool))); + connect(codeEditor, SIGNAL(copyAvailable(bool)), deleteAction, + SLOT(setEnabled(bool))); + } + + prevCodeEditor = codeEditor; +} + +void MainWindow::newFile() { + if (tabs->count() > 0) { + settings.setValue("tabgeometry", ((Tab*) tabs->currentWidget())->saveGeometry()); + settings.setValue("tabwindowstate", ((Tab*) tabs->currentWidget())->saveState()); + } + //! Tabs + mainWidget->setCurrentIndex(1); + Tab* tab = new Tab; + tab->code->setPlainText(startText); + tabs->addTab(tab, tr("New")); + tabs->setCurrentWidget(tab); + connect(tab->code, SIGNAL(textChanged()), this, SLOT(setProgramBuildedFlagToFalse())); + connect(tab->code, SIGNAL(modificationChanged(bool)), this, + SLOT(changeCurrentSavedState(bool))); + connect(tab->code, SIGNAL(fileOpened(QString)), this, SLOT(openFile(QString))); +} + +void MainWindow::changeCurrentSavedState(bool changed) { + if (changed) + tabs->setTabText(tabs->currentIndex(), '*' + tabs->tabText(tabs->currentIndex())); + else { + QString tabText = tabs->tabText(tabs->currentIndex()); + if (tabText[0] == '*') tabText.remove(0, 1); + tabs->setTabText(tabs->currentIndex(), tabText); + } +} + +void MainWindow::openFile() { + QString fileName = + QFileDialog::getOpenFileName(this, tr("Open file"), saveOpenDirectory, + tr("Assembler source files (*.asm);;All files (*)")); + if (fileName.isEmpty()) { + return; + } + saveOpenDirectory = QFileInfo(fileName).absoluteDir().absolutePath(); + openFile(fileName); +} + +void MainWindow::openFile(QString path) { + if (path.isEmpty()) { + return; + } + + newFile(); + Tab* curTab = (Tab*) tabs->currentWidget(); + curTab->loadCodeFromFile(path); + setTabPath(path); + // connect(curTab, SIGNAL(fileOpened(QString)), this, SLOT(openFile(QString))); +} + +void MainWindow::setTabPath(const QString& filePath, int index) { + //! Taking name of file (without path) + int i; + if ((i = filePath.lastIndexOf('/')) == -1) i = filePath.lastIndexOf('\\'); + QString caption = filePath.mid(i + 1); + if (index == -1) { + tabs->setTabToolTip(tabs->currentIndex(), filePath); + tabs->setTabText(tabs->currentIndex(), caption); + } else { + tabs->setTabToolTip(index, filePath); + tabs->setTabText(index, caption); + } +} + +void MainWindow::closeFile() { deleteTab(tabs->currentIndex()); } + +bool MainWindow::saveFile(int index, bool openSaveAs) { + Tab* tab; + if (index == -1) tab = (Tab*) tabs->currentWidget(); + else + tab = (Tab*) tabs->widget(index); + QString filePath = tab->getCurrentFilePath(); + if (filePath.isEmpty()) { + if (openSaveAs) { + return saveAsFile(index); } else { - tab->saveCodeToFile(filePath, assembler); - return true; + return false; } -} - -bool MainWindow::saveAsFile(int index) -{ - QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"), saveOpenDirectory, - tr("Assembler source files (*.asm);;All files (*)")); - if (fileName.isEmpty()) { - return false; - } - saveOpenDirectory = QFileInfo(fileName).absoluteDir().absolutePath(); - Tab *tab; - if (index == -1) - tab = (Tab *) tabs->currentWidget(); - else - tab = (Tab *) tabs->widget(index); - tab->saveCodeToFile(fileName, assembler); - setTabPath(fileName, index); - return true; -} - -void MainWindow::saveExe() -{ - if (!programIsBuilded) { - buildProgram(); - } - if (!programIsBuilded) { - return; - } - QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save .exe file"), saveOpenDirectory, - tr("Execution files (*.exe);;All files (*.*)")); - if (saveFileName.isEmpty()) - return; - saveOpenDirectory = QFileInfo(saveFileName).absoluteDir().absolutePath(); - QFile exeFile(Common::pathInTemp("SASMprog.exe")); - QFile::remove(saveFileName); - exeFile.copy(saveFileName); -} - -bool MainWindow::closeApp() -{ - int tabsCount = tabs->count(); - if (tabsCount > 0) { - //! Consider all tabs - tabs->setCurrentIndex(0); - for (int i = 0; i < tabsCount; i++) { - //! Left only saved tabs - if (!deleteTab(tabs->currentIndex(), true)) - return false; - } - } - writeSettings(); - closeFromCloseAll = true; - close(); + } else { + tab->saveCodeToFile(filePath, assembler); return true; + } } -void MainWindow::closeEvent(QCloseEvent *e) -{ - - if (!closeFromCloseAll) - if (closeApp()) { - closeAllChildWindows(); - e->accept(); - } else - e->ignore(); - else - e->accept(); -} - -void MainWindow::closeAllChildWindows() -{ - if (findDialog) { - findDialog->close(); - delete findDialog; - } - if (settingsWindow) { - settingsWindow->close(); - delete settingsWindow; - } - if (help) { - help->close(); - delete help; - } - if (registersWindow) { - registersWindow->close(); - delete registersWindow; - registersWindow = 0; - } - if (memoryWindow) { - memoryWindow->close(); - delete memoryWindow; - memoryWindow = 0; - } -} - -bool MainWindow::deleteTab(int index, bool saveFileName) -{ - settings.setValue("tabgeometry", ((Tab *) tabs->widget(index))->saveGeometry()); - settings.setValue("tabwindowstate", ((Tab *) tabs->widget(index))->saveState()); - if (okToContinue(index)) { - if (debugger && index == tabs->currentIndex()) - debugExit(); - if (tabs->count() == 1) - //! Get started - mainWidget->setCurrentIndex(0); - Tab *tabForDeleting = (Tab *) tabs->widget(index); - if (!saveFileName || tabForDeleting->getCurrentFilePath().isEmpty()) { - tabs->removeTab(index); - delete tabForDeleting; - } else { - //! If tab did not delete - tabs->setCurrentIndex(tabs->currentIndex() + 1); - } - if (tabForDeleting->code == prevCodeEditor) - prevCodeEditor = 0; - return true; - } +bool MainWindow::saveAsFile(int index) { + QString fileName = + QFileDialog::getSaveFileName(this, tr("Save file"), saveOpenDirectory, + tr("Assembler source files (*.asm);;All files (*)")); + if (fileName.isEmpty()) { return false; + } + saveOpenDirectory = QFileInfo(fileName).absoluteDir().absolutePath(); + Tab* tab; + if (index == -1) tab = (Tab*) tabs->currentWidget(); + else + tab = (Tab*) tabs->widget(index); + tab->saveCodeToFile(fileName, assembler); + setTabPath(fileName, index); + return true; +} + +void MainWindow::saveExe() { + if (!programIsBuilded) { + buildProgram(); + } + if (!programIsBuilded) { + return; + } + QString saveFileName = + QFileDialog::getSaveFileName(this, tr("Save .exe file"), saveOpenDirectory, + tr("Execution files (*.exe);;All files (*.*)")); + if (saveFileName.isEmpty()) return; + saveOpenDirectory = QFileInfo(saveFileName).absoluteDir().absolutePath(); + QFile exeFile(replacePROGRAM); + QFile::remove(saveFileName); + exeFile.copy(saveFileName); +} + +bool MainWindow::closeApp() { + int tabsCount = tabs->count(); + if (tabsCount > 0) { + //! Consider all tabs + tabs->setCurrentIndex(0); + for (int i = 0; i < tabsCount; i++) { + //! Left only saved tabs + if (!deleteTab(tabs->currentIndex(), true)) return false; + } + } + writeSettings(); + closeFromCloseAll = true; + close(); + return true; +} + +void MainWindow::closeEvent(QCloseEvent* e) { + if (!closeFromCloseAll) + if (closeApp()) { + closeAllChildWindows(); + e->accept(); + } else + e->ignore(); + else + e->accept(); } -bool MainWindow::okToContinue(int index) -{ - Tab *deletingTab; - if (index == -1) - deletingTab = (Tab *) tabs->currentWidget(); - else - deletingTab = (Tab *) tabs->widget(index); - if (deletingTab->code->document()->isModified()) { - QMessageBox msgBox(this); - QPushButton *yesButton = msgBox.addButton(tr("Yes"), QMessageBox::YesRole); - msgBox.addButton(tr("No"), QMessageBox::NoRole); - QPushButton *cancelButton = msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole); - msgBox.setWindowTitle(tr("Save changes?")); - msgBox.setText(tr("Save changes?")); - msgBox.exec(); - - if (msgBox.clickedButton() == yesButton) { - return saveFile(index); - } else if (msgBox.clickedButton() == cancelButton) { - return false; - } - } - return true; -} - -void MainWindow::changeCurrentTab(int index) -{ - //! Set highlighter - if (tabs->count() == 0) - return; - Tab *currentTab = (Tab *) tabs->widget(index); - highlighter->setDocument(currentTab->getCodeDocument()); -} - -void MainWindow::buildProgram(bool debugMode) -{ - saveFile(-1, false); //save file before building if program already was saved - - programIsBuilded = false; - - using Common::applicationDataPath; - printLogWithTime(tr("Build started...") + '\n', Qt::black); - QCoreApplication::processEvents(); - - if (! QFile::exists(applicationDataPath())) { - printLogWithTime(tr("Error! Program directory does not exist. Please reinstall the program.") + '\n', Qt::red); - QMessageBox::critical(0, tr("Error!"), tr("Directory NASM does not exist. Please reinstall the program.")); - return; - } - - QString tempPath = Common::pathInTemp(QString()); - removeDirRecuresively(tempPath); - QString path = Common::pathInTemp("program.asm"); - - Tab *currentTab = (Tab *) tabs->currentWidget(); - currentTab->saveCodeToFile(path, assembler, false, debugMode && settings.value("insertdebugstring", true).toBool()); - - if (debugMode) { - //! Save input to file - QString inputPath = Common::pathInTemp("input.txt"); - Tab *currentTab = (Tab *) tabs->currentWidget(); - currentTab->saveInputToFile(inputPath); - } - - while (! QFile::exists(path)) { - } - - QString stdioMacros = Common::pathInTemp("macro.o"); - - //! Assembler - QString assemblerPath = assembler->getAssemblerPath(); - if (settings.contains("assemblerpath")) - assemblerPath = settings.value("assemblerpath").toString(); - #ifdef Q_OS_WIN32 - QString assemblerOptions = "-f win32 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; - #else - QString assemblerOptions = "-f elf32 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; - #endif - if (settings.contains("assemblyoptions")) - assemblerOptions = settings.value("assemblyoptions").toString(); - QStringList assemblerArguments = assemblerOptions.split(QChar(' ')); - assemblerArguments.replaceInStrings("$SOURCE$", Common::pathInTemp("program.asm")); - assemblerArguments.replaceInStrings("$LSTOUTPUT$", Common::pathInTemp("program.lst")); - assemblerArguments.replaceInStrings("$PROGRAM.OBJ$", - Common::pathInTemp(settings.value("objectfilename", "program.o").toString())); - assemblerArguments.replaceInStrings("$PROGRAM$", Common::pathInTemp("SASMprog.exe")); - assemblerArguments.replaceInStrings("$MACRO.OBJ$", stdioMacros); - QProcess assemblerProcess; - QString assemblerOutput = Common::pathInTemp("compilererror.txt"); - assemblerProcess.setStandardOutputFile(assemblerOutput); - assemblerProcess.setStandardErrorFile(assemblerOutput, QIODevice::Append); - bool currentDir = settings.value("currentdir", false).toBool(); - if (currentDir) { - QString path = currentTab->getCurrentFilePath(); - if (!path.isEmpty()) { - QString dirPath = QFileInfo(path).absoluteDir().absolutePath(); - assemblerProcess.setWorkingDirectory(dirPath); - } else { - assemblerProcess.setWorkingDirectory(applicationDataPath() + "/include"); - } +void MainWindow::closeAllChildWindows() { + if (findDialog) { + findDialog->close(); + delete findDialog; + } + if (settingsWindow) { + settingsWindow->close(); + delete settingsWindow; + } + if (help) { + help->close(); + delete help; + } + if (registersWindow) { + registersWindow->close(); + delete registersWindow; + registersWindow = 0; + } + if (memoryWindow) { + memoryWindow->close(); + delete memoryWindow; + memoryWindow = 0; + } +} + +bool MainWindow::deleteTab(int index, bool saveFileName) { + settings.setValue("tabgeometry", ((Tab*) tabs->widget(index))->saveGeometry()); + settings.setValue("tabwindowstate", ((Tab*) tabs->widget(index))->saveState()); + if (okToContinue(index)) { + if (debugger && index == tabs->currentIndex()) debugExit(); + if (tabs->count() == 1) + //! Get started + mainWidget->setCurrentIndex(0); + Tab* tabForDeleting = (Tab*) tabs->widget(index); + if (!saveFileName || tabForDeleting->getCurrentFilePath().isEmpty()) { + tabs->removeTab(index); + delete tabForDeleting; } else { - assemblerProcess.setWorkingDirectory(applicationDataPath() + "/include"); - } - assemblerProcess.start(assemblerPath, assemblerArguments); - assemblerProcess.waitForFinished(); - - if (assemblerProcess.error() != QProcess::UnknownError) { - printLogWithTime(tr("Unable to start assembler. Check your settings.") + '\n', Qt::red); - return; + //! If tab did not delete + tabs->setCurrentIndex(tabs->currentIndex() + 1); } + if (tabForDeleting->code == prevCodeEditor) prevCodeEditor = 0; + return true; + } + return false; +} + +bool MainWindow::okToContinue(int index) { + Tab* deletingTab; + if (index == -1) deletingTab = (Tab*) tabs->currentWidget(); + else + deletingTab = (Tab*) tabs->widget(index); + if (deletingTab->code->document()->isModified()) { + QMessageBox msgBox(this); + QPushButton* yesButton = msgBox.addButton(tr("Yes"), QMessageBox::YesRole); + msgBox.addButton(tr("No"), QMessageBox::NoRole); + QPushButton* cancelButton = msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole); + msgBox.setWindowTitle(tr("Save changes?")); + msgBox.setText(tr("Save changes?")); + msgBox.exec(); - //! GCC - QString linkerOptions = "$PROGRAM.OBJ$ $MACRO.OBJ$ -g -o $PROGRAM$ -m32"; - if (settings.contains("linkingoptions")) - linkerOptions = settings.value("linkingoptions").toString(); - //! macro.c compilation/copying - QFile macro; - #ifdef Q_OS_WIN32 - QString linker = settings.value("linkerpath", applicationDataPath() + "/MinGW/bin/gcc.exe").toString(); - if (settings.value("mode", QString("x86")).toString() == "x86") { - macro.setFileName(applicationDataPath() + "/NASM/macro.o"); - } else { - macro.setFileName(applicationDataPath() + "/NASM/macro64.o"); - } - macro.copy(stdioMacros); - #else - QString gcc = "gcc"; - QString linker = settings.value("linkerpath", "gcc").toString(); - macro.setFileName(applicationDataPath() + "/NASM/macro.c"); - macro.copy(Common::pathInTemp("macro.c")); - - //! macro.c compilation - QStringList gccMArguments; - gccMArguments << "-x" << "c" << Common::pathInTemp("macro.c") << "-c" << "-g" << "-o" << stdioMacros; - if (settings.value("mode", QString("x86")).toString() == "x86") - gccMArguments << "-m32"; - else - gccMArguments << "-m64"; - QProcess gccMProcess; - gccMProcess.start(gcc, gccMArguments); - gccMProcess.waitForFinished(); - #endif - - //! Final linking - bool disableLinking = settings.value("disablelinking", false).toBool(); - QString linkerOutput; + if (msgBox.clickedButton() == yesButton) { + return saveFile(index); + } else if (msgBox.clickedButton() == cancelButton) { + return false; + } + } + return true; +} + +void MainWindow::changeCurrentTab(int index) { + //! Set highlighter + if (tabs->count() == 0) return; + Tab* currentTab = (Tab*) tabs->widget(index); + highlighter->setDocument(currentTab->getCodeDocument()); +} + +void MainWindow::buildProgram(bool debugMode) { + saveFile(-1, false); // save file before building if program already was saved + + programIsBuilded = false; + + using Common::applicationDataPath; + printLogWithTime(tr("Build started...") + '\n', Qt::white); + QCoreApplication::processEvents(); + + if (!QFile::exists(applicationDataPath())) { + printLogWithTime( + tr("Error! Program directory does not exist. Please reinstall the program.") + + '\n', + Qt::red); + QMessageBox::critical( + 0, tr("Error!"), + tr("Directory NASM does not exist. Please reinstall the program.")); + return; + } + + removeDirRecuresively(Common::pathInTemp(QString())); + + Tab* currentTab = (Tab*) tabs->currentWidget(); + + replaceSOURCE = currentTab->getCurrentFilePath(); + QFileInfo sourceFileInfo = QFileInfo(replaceSOURCE); + replaceWORKSPACE_ROOT = sourceFileInfo.absoluteDir().absolutePath(); + + bool currentDir = settings.value("currentdir", false).toBool(); + if (currentDir) { + QString buildDirPath = replaceWORKSPACE_ROOT + "/build"; + outputCOMPILER_ERROR = buildDirPath + "/compilererror.txt"; + outputLINKER_ERROR = buildDirPath + "/linkererror.txt"; + replaceLSTOUTPUT = buildDirPath + '/' + sourceFileInfo.baseName() + ".lst"; + replacePROGRAM = buildDirPath + '/' + sourceFileInfo.baseName() + ".exe"; + replacePROGRAM_OBJ = buildDirPath + '/' + sourceFileInfo.baseName() + ".obj"; + + // Create build directory if necessary + QDir buildDir = QDir(buildDirPath); + if (!buildDir.exists()) buildDir.mkdir(buildDirPath); + } else { + replaceSOURCE = Common::pathInTemp("program.asm"); + outputCOMPILER_ERROR = Common::pathInTemp("compilererror.txt"); + outputLINKER_ERROR = Common::pathInTemp("linkererror.txt"); + replaceLSTOUTPUT = Common::pathInTemp("program.lst"); + replacePROGRAM = Common::pathInTemp("SASMprog.exe"); + replacePROGRAM_OBJ = + Common::pathInTemp(settings.value("objectfilename", "program.obj").toString()); + } + + currentTab->saveCodeToFile( + replaceSOURCE, assembler, false, + debugMode && settings.value("insertdebugstring", true).toBool()); + + if (debugMode) { + //! Save input to file + QString inputPath = Common::pathInTemp("input.txt"); + Tab* currentTab = (Tab*) tabs->currentWidget(); + currentTab->saveInputToFile(inputPath); + } + + while (!QFile::exists(replaceSOURCE)) { + } + + QString stdioMacros = Common::pathInTemp("macro.o"); + + //! Assembler + QString assemblerPath = assembler->getAssemblerPath(); + if (settings.contains("assemblerpath")) + assemblerPath = settings.value("assemblerpath").toString(); +#ifdef Q_OS_WIN32 + QString assemblerOptions = "-f win32 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; +#else + QString assemblerOptions = "-f elf32 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; +#endif + if (settings.contains("assemblyoptions")) + assemblerOptions = settings.value("assemblyoptions").toString(); + + QProcess assemblerProcess; + QStringList assemblerArguments = assemblerOptions.split(QChar(' ')); + QString assemblerOutput; + + if (currentDir) { + assemblerProcess.setWorkingDirectory(replaceWORKSPACE_ROOT); + } else { + assemblerProcess.setWorkingDirectory(applicationDataPath() + "/include"); + } + + assemblerOutput = outputCOMPILER_ERROR; + assemblerArguments.replaceInStrings("$SOURCE$", replaceSOURCE); + assemblerArguments.replaceInStrings("$LSTOUTPUT$", replaceLSTOUTPUT); + assemblerArguments.replaceInStrings("$PROGRAM$", replacePROGRAM); + assemblerArguments.replaceInStrings("$PROGRAM.OBJ$", replacePROGRAM_OBJ); + assemblerArguments.replaceInStrings("$WORKSPACE_ROOT$", replaceWORKSPACE_ROOT); + assemblerArguments.replaceInStrings("$MACRO.OBJ$", stdioMacros); + + assemblerProcess.setStandardOutputFile(assemblerOutput); + assemblerProcess.setStandardErrorFile(assemblerOutput, QIODevice::Append); + + assemblerProcess.start(assemblerPath, assemblerArguments); + assemblerProcess.waitForFinished(); + + if (assemblerProcess.error() != QProcess::UnknownError) { + printLogWithTime(tr("Unable to start assembler. Check your settings.") + '\n', + Qt::red); + return; + } + + //! GCC + QString linkerOptions = "$PROGRAM.OBJ$ $MACRO.OBJ$ -g -o $PROGRAM$ -m32"; + if (settings.contains("linkingoptions")) + linkerOptions = settings.value("linkingoptions").toString(); + //! macro.c compilation/copying + QFile macro; +#ifdef Q_OS_WIN32 + QString linker = + settings.value("linkerpath", applicationDataPath() + "/MinGW/bin/gcc.exe") + .toString(); + if (settings.value("mode", QString("x86")).toString() == "x86") { + macro.setFileName(applicationDataPath() + "/NASM/macro.o"); + } else { + macro.setFileName(applicationDataPath() + "/NASM/macro64.o"); + } + macro.copy(stdioMacros); +#else + QString gcc = "gcc"; + QString linker = settings.value("linkerpath", "gcc").toString(); + macro.setFileName(applicationDataPath() + "/NASM/macro.c"); + macro.copy(Common::pathInTemp("macro.c")); + + //! macro.c compilation + QStringList gccMArguments; + gccMArguments << "-x" + << "c" << Common::pathInTemp("macro.c") << "-c" + << "-g" + << "-o" << stdioMacros; + if (settings.value("mode", QString("x86")).toString() == "x86") gccMArguments << "-m32"; + else + gccMArguments << "-m64"; + QProcess gccMProcess; + gccMProcess.start(gcc, gccMArguments); + gccMProcess.waitForFinished(); +#endif + + //! Final linking + bool disableLinking = settings.value("disablelinking", false).toBool(); + if (!disableLinking) { + QStringList linkerArguments = linkerOptions.split(QChar(' ')); + linkerArguments.replaceInStrings("$MACRO.OBJ$", stdioMacros); + linkerArguments.replaceInStrings("$PROGRAM.OBJ$", replacePROGRAM_OBJ); + linkerArguments.replaceInStrings("$PROGRAM$", replacePROGRAM); + linkerArguments.replaceInStrings("$SOURCE$", replaceSOURCE); + linkerArguments.replaceInStrings("$LSTOUTPUT$", replaceLSTOUTPUT); + linkerArguments.replaceInStrings("$WORKSPACE_ROOT$", replaceWORKSPACE_ROOT); + + QProcess linkerProcess; + linkerProcess.setStandardOutputFile(outputLINKER_ERROR); + linkerProcess.setStandardErrorFile(outputLINKER_ERROR, QIODevice::Append); + linkerProcess.start(linker, linkerArguments); + linkerProcess.waitForFinished(); + + if (linkerProcess.error() != QProcess::UnknownError) { + printLogWithTime(tr("Unable to start linker. Check your settings.") + '\n', + Qt::red); + return; + } + } + + QFile logFile; + logFile.setFileName(assemblerOutput); + logFile.open(QIODevice::ReadOnly); + QTextStream log(&logFile); + QString logText = log.readAll(); + if (settings.value("assembler", QString("NASM")).toString() == "FASM" && + logText.count(QChar('\n')) == 2 && logText.contains(QRegExp(" bytes\\."))) + logText.clear(); + if (settings.value("assembler", QString("NASM")).toString() == "MASM") { + if (logText.count(QChar('\n')) == 1 && logText.startsWith(" Assembling:")) + logText.clear(); + if (logText.count(QChar('\n')) == 6 && logText.contains("ASCII build")) + logText.clear(); + } + logFile.close(); + + bool builded; + if (QFile::exists(replacePROGRAM)) builded = true; + else + builded = false; + if (!builded) { + printLogWithTime(tr("Warning! Errors have occurred in the build:") + '\n', Qt::red); + + //! Print errors + printLog(logText, Qt::red); if (!disableLinking) { - QStringList linkerArguments = linkerOptions.split(QChar(' ')); - linkerArguments.replaceInStrings("$PROGRAM.OBJ$", - Common::pathInTemp(settings.value("objectfilename", "program.o").toString())); - linkerArguments.replaceInStrings("$MACRO.OBJ$", stdioMacros); - linkerArguments.replaceInStrings("$PROGRAM$", Common::pathInTemp("SASMprog.exe")); - linkerArguments.replaceInStrings("$SOURCE$", Common::pathInTemp("program.asm")); - linkerArguments.replaceInStrings("$LSTOUTPUT$", Common::pathInTemp("program.lst")); - QProcess linkerProcess; - linkerOutput = Common::pathInTemp("linkererror.txt"); - linkerProcess.setStandardOutputFile(linkerOutput); - linkerProcess.setStandardErrorFile(linkerOutput, QIODevice::Append); - linkerProcess.start(linker, linkerArguments); - linkerProcess.waitForFinished(); - - if (linkerProcess.error() != QProcess::UnknownError) { - printLogWithTime(tr("Unable to start linker. Check your settings.") + '\n', Qt::red); - return; - } - } - - QFile logFile; - logFile.setFileName(assemblerOutput); - logFile.open(QIODevice::ReadOnly); - QTextStream log(&logFile); - QString logText = log.readAll(); - if (settings.value("assembler", QString("NASM")).toString() == "FASM" && logText.count(QChar('\n')) == 2 - && logText.contains(QRegExp(" bytes\\."))) - logText.clear(); - if (settings.value("assembler", QString("NASM")).toString() == "MASM") { - if (logText.count(QChar('\n')) == 1 && logText.startsWith(" Assembling:")) - logText.clear(); - if (logText.count(QChar('\n')) == 6 && logText.contains("ASCII build")) - logText.clear(); - } - logFile.close(); - - bool builded; - if (QFile::exists(Common::pathInTemp("SASMprog.exe"))) - builded = true; - else - builded = false; - if (!builded) { - printLogWithTime(tr("Warning! Errors have occurred in the build:") + '\n', Qt::red); - - //! Print errors - printLog(logText, Qt::red); - if (!disableLinking) { - logFile.setFileName(linkerOutput); - logFile.open(QIODevice::ReadOnly); - QTextStream logLinker(&logFile); - logText = logLinker.readAll(); - logFile.close(); - printLog(logText, Qt::red); - } - - //! QMessageBox::critical(0, tr("Warning!"), tr("Errors have occurred in the build!")); - } else { - printLogWithTime(tr("Built successfully.") + '\n', Qt::darkGreen); - //! print warnings - printLog(logText, Qt::red); - if (!disableLinking) { - logFile.setFileName(linkerOutput); - logFile.open(QIODevice::ReadOnly); - QTextStream logLinker(&logFile); - logText = logLinker.readAll(); - logFile.close(); - printLog(logText, Qt::red); - } - programIsBuilded = true; - } -} - -void MainWindow::runProgram() -{ + logFile.setFileName(outputLINKER_ERROR); + logFile.open(QIODevice::ReadOnly); + QTextStream logLinker(&logFile); + logText = logLinker.readAll(); + logFile.close(); + printLog(logText, Qt::red); + } + + //! QMessageBox::critical(0, tr("Warning!"), tr("Errors have occurred in the + //! build!")); + } else { + printLogWithTime(tr("Built successfully.") + '\n', Qt::darkGreen); + //! print warnings + printLog(logText, Qt::red); + if (!disableLinking) { + logFile.setFileName(outputLINKER_ERROR); + logFile.open(QIODevice::ReadOnly); + QTextStream logLinker(&logFile); + logText = logLinker.readAll(); + logFile.close(); + printLog(logText, Qt::red); + } + programIsBuilded = true; + } +} + +void MainWindow::runProgram() { + if (!programStopped) { + QMessageBox::information(0, QString("SASM"), tr("The program is already running.")); + return; + } + outputIndex = tabs->currentIndex(); + if (!programIsBuilded) { + buildProgram(); + } + if (!programIsBuilded) { + return; + } + + stopAction->setEnabled(true); + debugAction->setEnabled(false); + buildAction->setEnabled(false); + + ((Tab*) tabs->currentWidget())->clearOutput(); + + printLogWithTime(tr("The program is executing...") + '\n', Qt::green); + QCoreApplication::processEvents(); + + QString input = Common::pathInTemp("input.txt"); + Tab* currentTab = (Tab*) tabs->currentWidget(); + currentTab->saveInputToFile(input); + + //! Read input.txt + QStringList args; + QFile inputFile(input); + if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&inputFile); + args = in.readAll().split(' '); + } + + //! Run program in code directory + runProcess->setWorkingDirectory(replaceWORKSPACE_ROOT); + + connect(runProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(getOutput())); + programStopped = false; + connect(runProcess, SIGNAL(started()), this, SLOT(startCountProgramTime())); + connect(runProcess, SIGNAL(finished(int)), this, SLOT(testStopOfProgram())); + runProcess->start(replacePROGRAM, args); + + timer->start(100); + // Previous - connect(timer, SIGNAL(timeout()), this, SLOT(testStopOfProgram())); +} + +void MainWindow::startCountProgramTime() { programExecutionTime.start(); } + +void MainWindow::getOutput() { + QByteArray output = runProcess->readAllStandardOutput(); + QString outputString = QString::fromLocal8Bit(output.constData(), output.size()); + printOutput(outputString, outputIndex); +} + +void MainWindow::testStopOfProgram() { + QCoreApplication::processEvents(); + if (runProcess->state() == QProcess::NotRunning) { + stopAction->setEnabled(false); + debugAction->setEnabled(true); + buildAction->setEnabled(true); if (!programStopped) { - QMessageBox::information(0, QString("SASM"), tr("The program is already running.")); - return; - } - outputIndex = tabs->currentIndex(); - if (!programIsBuilded) { - buildProgram(); - } - if (!programIsBuilded) { - return; - } - - stopAction->setEnabled(true); - debugAction->setEnabled(false); - buildAction->setEnabled(false); - - ((Tab *) tabs->currentWidget())->clearOutput(); - - printLogWithTime(tr("The program is executing...") + '\n', Qt::black); - QCoreApplication::processEvents(); - - QString input = Common::pathInTemp("input.txt"); - Tab *currentTab = (Tab *) tabs->currentWidget(); - currentTab->saveInputToFile(input); - - QString program = Common::pathInTemp("SASMprog.exe"); - runProcess->setStandardInputFile(input); - - //! Run program in code directory if it exists - QString codePath = currentTab->getCurrentFilePath(); - if (!codePath.isEmpty()) { - QString codeDirPath = QFileInfo(codePath).absoluteDir().absolutePath(); - runProcess->setWorkingDirectory(codeDirPath); - } - - connect(runProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(getOutput())); - programStopped = false; - connect(runProcess, SIGNAL(started()), this, SLOT(startCountProgramTime())); - connect(runProcess, SIGNAL(finished(int)), this, SLOT(testStopOfProgram())); - runProcess->start(program, QStringList()); - - timer->start(100); - //Previous - connect(timer, SIGNAL(timeout()), this, SLOT(testStopOfProgram())); -} - -void MainWindow::startCountProgramTime() -{ - programExecutionTime.start(); -} - -void MainWindow::getOutput() -{ - QByteArray output = runProcess->readAllStandardOutput(); - QString outputString = QString::fromLocal8Bit(output.constData(), output.size()); - printOutput(outputString, outputIndex); -} - -void MainWindow::testStopOfProgram() -{ - QCoreApplication::processEvents(); - if (runProcess->state() == QProcess::NotRunning) { - stopAction->setEnabled(false); - debugAction->setEnabled(true); - buildAction->setEnabled(true); - if (!programStopped) { - if (runProcess->exitStatus() == QProcess::NormalExit) - printLogWithTime(tr("The program finished normally. Execution time: %1 s") - .arg(programExecutionTime.elapsed() / 1000.0) - + '\n', Qt::darkGreen); - else - printLogWithTime(tr("The program crashed! Execution time: %1 s"). - arg(programExecutionTime.elapsed() / 1000.0) - + '\n', Qt::red); - programStopped = true; - } - timer->stop(); + if (runProcess->exitStatus() == QProcess::NormalExit) + printLogWithTime(tr("The program finished normally. Execution time: %1 s") + .arg(programExecutionTime.elapsed() / 1000.0) + + '\n', + Qt::darkGreen); + else + printLogWithTime(tr("The program crashed! Execution time: %1 s") + .arg(programExecutionTime.elapsed() / 1000.0) + + '\n', + Qt::red); + programStopped = true; } + timer->stop(); + } } -void MainWindow::runExeProgram() -{ - if (!programIsBuilded) { - buildProgram(); - } - if (!programIsBuilded) { - return; - } +void MainWindow::runExeProgram() { + if (!programIsBuilded) { + buildProgram(); + } + if (!programIsBuilded) { + return; + } - QString program = Common::pathInTemp("SASMprog.exe"); - runProcess->startDetached(program, QStringList()); + QString program = replacePROGRAM; + runProcess->startDetached(program, QStringList()); } -void MainWindow::stopProgram() -{ - if (timer->isActive()) { - programStopped = true; - timer->stop(); +void MainWindow::stopProgram() { + if (timer->isActive()) { + programStopped = true; + timer->stop(); - stopAction->setEnabled(false); + stopAction->setEnabled(false); - runProcess->kill(); + runProcess->kill(); - printLogWithTime(tr("The program stopped.") + '\n', Qt::darkGreen); - } else { - QMessageBox::information(0, QString("SASM"), tr("The program is not running.")); - } + printLogWithTime(tr("The program stopped.") + '\n', Qt::darkGreen); + } else { + QMessageBox::information(0, QString("SASM"), tr("The program is not running.")); + } } -void MainWindow::printLogWithTime(const QString &message, const QColor &color) -{ - QTime curTime = QTime::currentTime(); - QString timeString = curTime.toString("[HH:mm:ss] "); - printLog(timeString + message, color); +void MainWindow::printLogWithTime(const QString& message, const QColor& color) { + QTime curTime = QTime::currentTime(); + QString timeString = curTime.toString("[HH:mm:ss] "); + printLog(timeString + message, color); } -void MainWindow::printLog(const QString &message, const QColor &color) -{ - QTextCursor cursor = QTextCursor(compilerOut->document()); - cursor.movePosition(QTextCursor::End); - compilerOut->setTextCursor(cursor); - compilerOut->setTextColor(color); - compilerOut->insertPlainText(message); - cursor.movePosition(QTextCursor::End); - compilerOut->setTextCursor(cursor); +void MainWindow::printLog(const QString& message, const QColor& color) { + QTextCursor cursor = QTextCursor(compilerOut->document()); + cursor.movePosition(QTextCursor::End); + compilerOut->setTextCursor(cursor); + compilerOut->setTextColor(color); + compilerOut->insertPlainText(message); + cursor.movePosition(QTextCursor::End); + compilerOut->setTextCursor(cursor); } -void MainWindow::setProgramBuildedFlagToFalse() -{ - programIsBuilded = false; -} +void MainWindow::setProgramBuildedFlagToFalse() { programIsBuilded = false; } -void MainWindow::printOutput(QString msg, int index) -{ - Tab *tab = 0; - if (index != -1) { - tab = (Tab *) tabs->widget(index); - } else - tab = (Tab *) tabs->currentWidget(); - tab->appendOutput(msg); -} - -void MainWindow::debug() -{ - //! Start debugger if true - if (!debugger) { - debuggerWasStarted = false; - buildProgram(true); - if (!programIsBuilded) { - printLogWithTime(tr("Before debugging you need to build the program.") + '\n', Qt::red); - return; - } - ((Tab *) tabs->currentWidget())->clearOutput(); - printLogWithTime(tr("Debugging started...") + '\n', Qt::darkGreen); - Tab *currentTab = (Tab *) tabs->currentWidget(); - CodeEditor *code = currentTab->code; - - //! Determine executable path - QString exePath = Common::pathInTemp("SASMprog.exe"); - - //! Determine working directory path - QString workingDirectoryPath; - QString codePath = currentTab->getCurrentFilePath(); - if (!codePath.isEmpty()) { - workingDirectoryPath = QFileInfo(codePath).absoluteDir().absolutePath(); - } else { - workingDirectoryPath = Common::pathInTemp(""); - } - workingDirectoryPath.replace("\\", "/"); - - //! Determine input path - QString inputPath = Common::pathInTemp("input.txt"); - inputPath.replace("\\", "/"); - - debugger = new Debugger(compilerOut, exePath, workingDirectoryPath, inputPath, assembler); - connect(debugger, SIGNAL(highlightLine(int)), code, SLOT(updateDebugLine(int))); - connect(debugger, SIGNAL(finished()), this, SLOT(debugExit()), Qt::QueuedConnection); - connect(debugger, SIGNAL(started()), this, SLOT(enableDebugActions())); - connect(debugger, SIGNAL(started()), this, SLOT(showAnyCommandWidget())); - connect(code, SIGNAL(breakpointsChanged(quint64,bool)), debugger, SLOT(changeBreakpoint(quint64,bool))); - connect(code, SIGNAL(addWatchSignal(const RuQPlainTextEdit::Watch &)), - this, SLOT(setShowMemoryToChecked(RuQPlainTextEdit::Watch))); - connect(debugger, SIGNAL(printLog(QString,QColor)), this, SLOT(printLog(QString,QColor))); - connect(debugger, SIGNAL(printOutput(QString)), this, SLOT(printOutput(QString))); - connect(debugger, SIGNAL(inMacro()), this, SLOT(debugNextNi()), Qt::QueuedConnection); - connect(debugger, SIGNAL(wasStopped()), this, SLOT(changeDebugActionToStart())); - connect(debugger, SIGNAL(needToContinue()), this, SLOT(debug())); - code->setDebugEnabled(); - } - //Pause or continue debugger - else { - debugAction->setEnabled(false); - if (debugger->isStopped()) { - debugAction->setText(tr("Pause")); - debugAction->setIcon(QIcon(":/images/debugPause.png")); - debugger->doInput(QString("c\n"), ni); - debugAction->setShortcut(QString()); - } else { - debugAction->setText(tr("Continue")); - debugAction->setIcon(QIcon(":/images/continue.png")); - debugAction->setShortcut(debugKey); - debugger->pause(); - } - debugAction->setEnabled(true); - } +void MainWindow::printOutput(QString msg, int index) { + Tab* tab = 0; + if (index != -1) { + tab = (Tab*) tabs->widget(index); + } else + tab = (Tab*) tabs->currentWidget(); + tab->appendOutput(msg); } -void MainWindow::changeDebugActionToStart() -{ - debugAction->setText(tr("Continue")); - debugAction->setIcon(QIcon(":/images/continue.png")); - debugAction->setShortcut(debugKey); - if (!debuggerWasStarted) - debuggerWasStarted = true; - else { - debugShowRegisters(); - debugShowMemory(); - } -} - -void MainWindow::enableDebugActions() -{ - debugAction->setText(tr("Continue")); - debugAction->setIcon(QIcon(":/images/continue.png")); - - //! Set all user's breakpoints - CodeEditor *code = ((Tab *) tabs->currentWidget())->code; - int lineNumber; - foreach (lineNumber, *(code->getBreakpoints())) { - debugger->changeBreakpoint(lineNumber, true); - } - - //! Enable all actions - debugNextAction->setEnabled(true); - debugNextNiAction->setEnabled(true); - debugShowRegistersAction->setEnabled(true); - debugShowMemoryAction->setEnabled(true); - stopAction->setEnabled(true); - - //! Change stopAction - disconnect(stopAction, SIGNAL(triggered()), this, SLOT(stopProgram())); - connect(stopAction, SIGNAL(triggered()), this, SLOT(debugExit())); - - //! Block run and build - buildAction->setEnabled(false); - runAction->setEnabled(false); - - //! Restore windows - debugShowRegistersAction->setChecked(settings.value("debugregisters", false).toBool()); - debugShowMemoryAction->setChecked(settings.value("debugmemory", false).toBool()); -} - -void MainWindow::disableDebugActions(bool start) -{ - debugAction->setText(tr("Debug")); - debugAction->setIcon(QIcon(":/images/debug.png")); - debugAction->setShortcut(debugKey); - - debugNextAction->setEnabled(false); - debugNextNiAction->setEnabled(false); - debugShowRegistersAction->setEnabled(false); - debugShowMemoryAction->setEnabled(false); - stopAction->setEnabled(false); - - //! Change stopAction - if (!start) { - disconnect(stopAction, SIGNAL(triggered()), this, SLOT(debugExit())); - connect(stopAction, SIGNAL(triggered()), this, SLOT(stopProgram())); - } - - //!Enable run and build - buildAction->setEnabled(true); - runAction->setEnabled(true); -} - -void MainWindow::debugNext() -{ - CodeEditor *code = ((Tab *) tabs->currentWidget())->code; - if (code->isMacroOnCurrentDebugLine()) { - debugNextNi(); +void MainWindow::debug() { + //! Start debugger if true + if (!debugger) { + debuggerWasStarted = false; + buildProgram(true); + if (!programIsBuilded) { + printLogWithTime(tr("Before debugging you need to build the program.") + '\n', + Qt::red); + return; + } + ((Tab*) tabs->currentWidget())->clearOutput(); + printLogWithTime(tr("Debugging started...") + '\n', Qt::darkGreen); + Tab* currentTab = (Tab*) tabs->currentWidget(); + CodeEditor* code = currentTab->code; + + //! Determine input path + QString inputPath = Common::pathInTemp("input.txt"); + inputPath.replace("\\", "/"); + + debugger = new Debugger(compilerOut, replacePROGRAM, replaceLSTOUTPUT, replaceSOURCE, + replaceWORKSPACE_ROOT, inputPath, assembler); + + connect(debugger, SIGNAL(highlightLine(int)), code, SLOT(updateDebugLine(int))); + connect(debugger, SIGNAL(finished()), this, SLOT(debugExit()), Qt::QueuedConnection); + connect(debugger, SIGNAL(started()), this, SLOT(enableDebugActions())); + connect(debugger, SIGNAL(started()), this, SLOT(showAnyCommandWidget())); + connect(code, SIGNAL(breakpointsChanged(quint64, bool)), debugger, + SLOT(changeBreakpoint(quint64, bool))); + connect(code, SIGNAL(addWatchSignal(const RuQPlainTextEdit::Watch&)), this, + SLOT(setShowMemoryToChecked(RuQPlainTextEdit::Watch))); + connect(debugger, SIGNAL(printLog(QString, QColor)), this, + SLOT(printLog(QString, QColor))); + connect(debugger, SIGNAL(printOutput(QString)), this, SLOT(printOutput(QString))); + connect(debugger, SIGNAL(inMacro()), this, SLOT(debugNextNi()), Qt::QueuedConnection); + connect(debugger, SIGNAL(wasStopped()), this, SLOT(changeDebugActionToStart())); + connect(debugger, SIGNAL(needToContinue()), this, SLOT(debug())); + code->setDebugEnabled(); + } + // Pause or continue debugger + else { + debugAction->setEnabled(false); + if (debugger->isStopped()) { + debugAction->setText(tr("Pause")); + debugAction->setIcon(QIcon(":/images/debugPause.png")); + debugger->doInput(QString("c\n"), ni); + debugAction->setShortcut(QString()); } else { - debugNextAction->setEnabled(false); - debugger->doInput(QString("si\n"), si); - debugNextAction->setEnabled(true); - } -} + debugAction->setText(tr("Continue")); + debugAction->setIcon(QIcon(":/images/continue.png")); + debugAction->setShortcut(debugKey); + debugger->pause(); + } + debugAction->setEnabled(true); + } +} + +void MainWindow::changeDebugActionToStart() { + debugAction->setText(tr("Continue")); + debugAction->setIcon(QIcon(":/images/continue.png")); + debugAction->setShortcut(debugKey); + if (!debuggerWasStarted) debuggerWasStarted = true; + else { + debugShowRegisters(); + debugShowMemory(); + } +} + +void MainWindow::enableDebugActions() { + debugAction->setText(tr("Continue")); + debugAction->setIcon(QIcon(":/images/continue.png")); + + //! Set all user's breakpoints + CodeEditor* code = ((Tab*) tabs->currentWidget())->code; + int lineNumber; + foreach (lineNumber, *(code->getBreakpoints())) { + debugger->changeBreakpoint(lineNumber, true); + } + + //! Enable all actions + debugNextAction->setEnabled(true); + debugNextNiAction->setEnabled(true); + debugShowRegistersAction->setEnabled(true); + debugShowMemoryAction->setEnabled(true); + stopAction->setEnabled(true); + + //! Change stopAction + disconnect(stopAction, SIGNAL(triggered()), this, SLOT(stopProgram())); + connect(stopAction, SIGNAL(triggered()), this, SLOT(debugExit())); + + //! Block run and build + buildAction->setEnabled(false); + runAction->setEnabled(false); + + //! Restore windows + debugShowRegistersAction->setChecked(settings.value("debugregisters", false).toBool()); + debugShowMemoryAction->setChecked(settings.value("debugmemory", false).toBool()); +} + +void MainWindow::disableDebugActions(bool start) { + debugAction->setText(tr("Debug")); + debugAction->setIcon(QIcon(":/images/debug.png")); + debugAction->setShortcut(debugKey); + + debugNextAction->setEnabled(false); + debugNextNiAction->setEnabled(false); + debugShowRegistersAction->setEnabled(false); + debugShowMemoryAction->setEnabled(false); + stopAction->setEnabled(false); + + //! Change stopAction + if (!start) { + disconnect(stopAction, SIGNAL(triggered()), this, SLOT(debugExit())); + connect(stopAction, SIGNAL(triggered()), this, SLOT(stopProgram())); + } -void MainWindow::debugToggleBreakpoint() -{ - CodeEditor *code = ((Tab *) tabs->currentWidget())->code; - code->setBreakpointOnCurrentLine(); + //! Enable run and build + buildAction->setEnabled(true); + runAction->setEnabled(true); } -void MainWindow::debugNextNi() -{ - debugNextNiAction->setEnabled(false); - debugger->doInput(QString("ni\n"), ni); - debugNextNiAction->setEnabled(true); -} - -void MainWindow::debugShowMemory() -{ - if (debugShowMemoryAction->isChecked()) { - if (!memoryWindow) { - memoryDock = new QDockWidget(tr("Memory"), this); - memoryDock->setAllowedAreas(Qt::AllDockWidgetAreas); - - //! Create table - memoryWindow = new DebugTableWidget(0, 3, memoryTable, memoryDock); - connect(memoryWindow, SIGNAL(closeSignal()), this, SLOT(setShowMemoryToUnchecked())); - connect(memoryWindow, SIGNAL(debugShowMemory()), this, SLOT(debugShowMemory())); - CodeEditor *code = ((Tab *) tabs->currentWidget())->code; - connect(code, SIGNAL(addWatchSignal(const RuQPlainTextEdit::Watch &)), - memoryWindow, SLOT(addVariable(const RuQPlainTextEdit::Watch &))); - connect(debugger, SIGNAL(printMemory(QList)), - memoryWindow, SLOT(setValuesFromDebugger(QList))); - - memoryDock->setWidget(memoryWindow); - memoryDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); - addDockWidget(Qt::TopDockWidgetArea, memoryDock); - memoryDock->setObjectName("memoryDock"); - - restoreState(settings.value("debugstate").toByteArray()); - if (registersDock) - registersDock->show(); - if (memoryDock) - memoryDock->show(); - - //! Fill table - memoryWindow->initializeMemoryWindow(watches); - } - if (debugger->isStopped()) { - debugger->setWatchesCount(memoryWindow->rowCount() - 1); - for (int i = 0; i < memoryWindow->rowCount() - 1; i++) { - if (memoryWindow->cellWidget(i, 2)) { - WatchSettingsWidget *settings = (WatchSettingsWidget *) memoryWindow->cellWidget(i, 2); - - int arraySize = 0; - - int size = settings->sizeComboBox->currentIndex(); - QStringList sizeFormat; - sizeFormat << "int" << "short" << "char" << "long long"; - - bool ok; - arraySize = settings->arraySizeEdit->text().toInt(&ok); - if (!ok && sizeFormat[size] == "long long") { - arraySize = 1; - ok = true; - } - QString watchAsArray; - if (ok && arraySize > 0) - watchAsArray = "[" + QString::number(arraySize) + "]"; - - int type = settings->typeComboBox->currentIndex(); - QStringList printFormat; - printFormat << "p" << "p/x" << "p/t" << "p/c" << "p/d" << "p/u" << "p/f"; - //! If true, watch as variable - if (! settings->addressCheckbox->isChecked()) { - debugger->doInput(printFormat[type] + " (" + sizeFormat[size] + watchAsArray + ")" + - "(" + memoryWindow->item(i, 0)->text() + ")" + "\n", infoMemory); - } else { - //! Watch as random address - debugger->doInput(printFormat[type] + " (" + sizeFormat[size] + watchAsArray + ")" + - "*((" + sizeFormat[size] + "*) " + "(" + memoryWindow->item(i, 0)->text() + ")" + ")" + - "\n", infoMemory); - } - } - } - static SignalLocker locker; - if (memoryWindow->rowCount() > 1 && locker.tryLock()) { - connect(debugger, SIGNAL(printMemory(QList)), &locker, SLOT(unlock()), Qt::UniqueConnection); - connect(debugger, SIGNAL(finished()), &locker, SLOT(unlock()), Qt::UniqueConnection); - } - } - } else - if (memoryWindow) { - saveWatches(memoryWindow); - memoryWindow->close(); - memoryWindow->clear(); - delete memoryWindow; - memoryWindow = 0; - memoryDock->close(); - delete memoryDock; - memoryDock = 0; +void MainWindow::debugNext() { + CodeEditor* code = ((Tab*) tabs->currentWidget())->code; + if (code->isMacroOnCurrentDebugLine()) { + debugNextNi(); + } else { + debugNextAction->setEnabled(false); + debugger->doInput(QString("si\n"), si); + debugNextAction->setEnabled(true); + } +} + +void MainWindow::debugToggleBreakpoint() { + CodeEditor* code = ((Tab*) tabs->currentWidget())->code; + code->setBreakpointOnCurrentLine(); +} + +void MainWindow::debugNextNi() { + debugNextNiAction->setEnabled(false); + debugger->doInput(QString("ni\n"), ni); + debugNextNiAction->setEnabled(true); +} + +void MainWindow::debugShowMemory() { + if (debugShowMemoryAction->isChecked()) { + if (!memoryWindow) { + memoryDock = new QDockWidget(tr("Memory"), this); + memoryDock->setAllowedAreas(Qt::AllDockWidgetAreas); + + //! Create table + memoryWindow = new DebugTableWidget(0, 3, memoryTable, memoryDock); + connect(memoryWindow, SIGNAL(closeSignal()), this, + SLOT(setShowMemoryToUnchecked())); + connect(memoryWindow, SIGNAL(debugShowMemory()), this, SLOT(debugShowMemory())); + CodeEditor* code = ((Tab*) tabs->currentWidget())->code; + connect(code, SIGNAL(addWatchSignal(const RuQPlainTextEdit::Watch&)), memoryWindow, + SLOT(addVariable(const RuQPlainTextEdit::Watch&))); + connect(debugger, SIGNAL(printMemory(QList)), memoryWindow, + SLOT(setValuesFromDebugger(QList))); + + memoryDock->setWidget(memoryWindow); + memoryDock->setFeatures(QDockWidget::DockWidgetFloatable | + QDockWidget::DockWidgetMovable); + addDockWidget(Qt::TopDockWidgetArea, memoryDock); + memoryDock->setObjectName("memoryDock"); + + restoreState(settings.value("debugstate").toByteArray()); + if (registersDock) registersDock->show(); + if (memoryDock) memoryDock->show(); + + //! Fill table + memoryWindow->initializeMemoryWindow(watches); + } + if (debugger->isStopped()) { + debugger->setWatchesCount(memoryWindow->rowCount() - 1); + for (int i = 0; i < memoryWindow->rowCount() - 1; i++) { + if (memoryWindow->cellWidget(i, 2)) { + WatchSettingsWidget* settings = + (WatchSettingsWidget*) memoryWindow->cellWidget(i, 2); + + int arraySize = 0; + + int size = settings->sizeComboBox->currentIndex(); + QStringList sizeFormat; + sizeFormat << "int" + << "short" + << "char" + << "long long"; + + bool ok; + arraySize = settings->arraySizeEdit->text().toInt(&ok); + if (!ok && sizeFormat[size] == "long long") { + arraySize = 1; + ok = true; + } + QString watchAsArray; + if (ok && arraySize > 0) watchAsArray = "[" + QString::number(arraySize) + "]"; + + int type = settings->typeComboBox->currentIndex(); + QStringList printFormat; + printFormat << "p" + << "p/x" + << "p/t" + << "p/c" + << "p/d" + << "p/u" + << "p/f"; + //! If true, watch as variable + if (!settings->addressCheckbox->isChecked()) { + debugger->doInput(printFormat[type] + " (" + sizeFormat[size] + watchAsArray + + ")" + "(" + memoryWindow->item(i, 0)->text() + ")" + + "\n", + infoMemory); + } else { + //! Watch as random address + debugger->doInput(printFormat[type] + " (" + sizeFormat[size] + watchAsArray + + ")" + "*((" + sizeFormat[size] + "*) " + "(" + + memoryWindow->item(i, 0)->text() + ")" + ")" + "\n", + infoMemory); + } } -} - -void MainWindow::saveWatches(DebugTableWidget *table) -{ - watches.clear(); - for (int i = 0; i < table->rowCount() - 1; i++) { - RuQPlainTextEdit::Watch watch; - watch.name = table->item(i, 0)->text(); - WatchSettingsWidget *settings = (WatchSettingsWidget *) table->cellWidget(i, 2); - watch.type = settings->typeComboBox->currentIndex(); - watch.size = settings->sizeComboBox->currentIndex(); - watch.address = settings->addressCheckbox->isChecked(); - bool ok; - watch.arraySize = settings->arraySizeEdit->text().toInt(&ok); - if (!ok) - watch.arraySize = 0; - watches.append(watch); - } -} - -void MainWindow::setShowMemoryToUnchecked() -{ - debugShowMemoryAction->setChecked(false); -} - -void MainWindow::setShowMemoryToChecked(const RuQPlainTextEdit::Watch &variable) -{ - if (!debugShowMemoryAction->isChecked()) { - watches.append(variable); - debugShowMemoryAction->setChecked(true); + } + static SignalLocker locker; + if (memoryWindow->rowCount() > 1 && locker.tryLock()) { + connect(debugger, SIGNAL(printMemory(QList)), &locker, + SLOT(unlock()), Qt::UniqueConnection); + connect(debugger, SIGNAL(finished()), &locker, SLOT(unlock()), + Qt::UniqueConnection); + } + } + } else if (memoryWindow) { + saveWatches(memoryWindow); + memoryWindow->close(); + memoryWindow->clear(); + delete memoryWindow; + memoryWindow = 0; + memoryDock->close(); + delete memoryDock; + memoryDock = 0; + } +} + +void MainWindow::saveWatches(DebugTableWidget* table) { + watches.clear(); + for (int i = 0; i < table->rowCount() - 1; i++) { + RuQPlainTextEdit::Watch watch; + watch.name = table->item(i, 0)->text(); + WatchSettingsWidget* settings = (WatchSettingsWidget*) table->cellWidget(i, 2); + watch.type = settings->typeComboBox->currentIndex(); + watch.size = settings->sizeComboBox->currentIndex(); + watch.address = settings->addressCheckbox->isChecked(); + bool ok; + watch.arraySize = settings->arraySizeEdit->text().toInt(&ok); + if (!ok) watch.arraySize = 0; + watches.append(watch); + } +} + +void MainWindow::setShowMemoryToUnchecked() { debugShowMemoryAction->setChecked(false); } + +void MainWindow::setShowMemoryToChecked(const RuQPlainTextEdit::Watch& variable) { + if (!debugShowMemoryAction->isChecked()) { + watches.append(variable); + debugShowMemoryAction->setChecked(true); + } +} + +void MainWindow::debugShowRegisters() { + if (debugShowRegistersAction->isChecked()) { + if (!registersWindow) { + registersDock = new QDockWidget(tr("Registers"), this); + registersDock->setAllowedAreas(Qt::AllDockWidgetAreas); + + int regCount; + if (settings.value("mode", QString("x86")).toString() == "x86") { + regCount = 16; + } else { + regCount = 24; + } + if (settings.value("allregisters", false).toBool()) { + regCount += 33; + } + registersWindow = new DebugTableWidget(regCount, 3, registersTable, registersDock); + connect(registersWindow, SIGNAL(closeSignal()), this, + SLOT(setShowRegistersToUnchecked())); + connect(debugger, SIGNAL(printRegisters(QList)), + registersWindow, + SLOT(setValuesFromDebugger(QList))); + + registersDock->setWidget(registersWindow); + registersDock->setFeatures(QDockWidget::DockWidgetFloatable | + QDockWidget::DockWidgetMovable); + addDockWidget(Qt::RightDockWidgetArea, registersDock); + registersDock->setObjectName("registersDock"); + + restoreState(settings.value("debugstate").toByteArray()); + if (registersDock) registersDock->show(); + if (memoryDock) memoryDock->show(); } -} - -void MainWindow::debugShowRegisters() -{ - if (debugShowRegistersAction->isChecked()) { - if (!registersWindow) { - registersDock = new QDockWidget(tr("Registers"), this); - registersDock->setAllowedAreas(Qt::AllDockWidgetAreas); - - int regCount; - if (settings.value("mode", QString("x86")).toString() == "x86") { - regCount = 16; - } else { - regCount = 24; - } - if (settings.value("allregisters", false).toBool()) { - regCount += 33; - } - registersWindow = new DebugTableWidget(regCount, 3, registersTable, registersDock); - connect(registersWindow, SIGNAL(closeSignal()), this, SLOT(setShowRegistersToUnchecked())); - connect(debugger, SIGNAL(printRegisters(QList)), - registersWindow, SLOT(setValuesFromDebugger(QList))); - - registersDock->setWidget(registersWindow); - registersDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); - addDockWidget(Qt::RightDockWidgetArea, registersDock); - registersDock->setObjectName("registersDock"); - - restoreState(settings.value("debugstate").toByteArray()); - if (registersDock) - registersDock->show(); - if (memoryDock) - memoryDock->show(); - } - static SignalLocker locker; - if (debugger->isStopped() && locker.tryLock()) { - connect(debugger, SIGNAL(printRegisters(QList)), &locker, SLOT(unlock()), Qt::UniqueConnection); - connect(debugger, SIGNAL(finished()), &locker, SLOT(unlock()), Qt::UniqueConnection); - if (settings.value("allregisters", false).toBool()) - debugger->doInput(QString("info all-registers\n"), infoRegisters); - else - debugger->doInput(QString("info registers\n"), infoRegisters); - } - } else - if (registersWindow) { - registersWindow->close(); - registersWindow->clear(); - delete registersWindow; - registersWindow = 0; - registersDock->close(); - delete registersDock; - registersDock = 0; - } -} - -void MainWindow::setShowRegistersToUnchecked() -{ - debugShowRegistersAction->setChecked(false); -} - -void MainWindow::debugExit() -{ - settings.setValue("debugregisters", debugShowRegistersAction->isChecked()); - settings.setValue("debugmemory", debugShowMemoryAction->isChecked()); - settings.setValue("debugstate", saveState()); - CodeEditor *code = ((Tab *) tabs->currentWidget())->code; - disconnect(code, SIGNAL(addWatchSignal(const RuQPlainTextEdit::Watch &)), - this, SLOT(setShowMemoryToChecked(RuQPlainTextEdit::Watch))); - disconnect(debugger, SIGNAL(printLog(QString,QColor)), this, SLOT(printLog(QString,QColor))); - disconnect(debugger, SIGNAL(printOutput(QString)), this, SLOT(printOutput(QString))); - code->setDebugDisabled(); - //! Many actions performed here - deleting of highlighting too - delete debugger; - debugger = 0; - closeAnyCommandWidget(); - debugShowRegistersAction->setChecked(false); - debugShowMemoryAction->setChecked(false); - printLogWithTime(tr("Debugging finished.") + '\n', Qt::darkGreen); - disableDebugActions(); -} - -void MainWindow::showAnyCommandWidget() -{ - debugAnyCommandWidget->show(); - debugAnyCommandWidget->setFocusOnLineEdit(); - connect(debugAnyCommandWidget, SIGNAL(performCommand(QString,bool)), - this, SLOT(debugRunCommand(QString,bool))); -} - -void MainWindow::closeAnyCommandWidget() -{ - disconnect(debugAnyCommandWidget, SIGNAL(performCommand(QString,bool)), - this, SLOT(debugRunCommand(QString,bool))); - debugAnyCommandWidget->close(); -} - -void MainWindow::debugRunCommand(QString command, bool print) -{ static SignalLocker locker; if (debugger->isStopped() && locker.tryLock()) { - connect(debugger, SIGNAL(printLog(QString,QColor)), &locker, SLOT(unlock()), Qt::UniqueConnection); - connect(debugger, SIGNAL(finished()), &locker, SLOT(unlock()), Qt::UniqueConnection); - printLog("> " + command + "\n", QColor(32, 71, 247)); - if (print) - debugger->doInput("p " + command + "\n", anyAction); - else - debugger->doInput(command + "\n", anyAction); - } -} - -void MainWindow::find() -{ - if (!findDialog) { - findDialog = new FindDialog(this); - connect(findDialog, SIGNAL(findNext(QString,Qt::CaseSensitivity,bool,bool,QString)), - this, SLOT(findNext(QString,Qt::CaseSensitivity,bool,bool,QString))); - } - CodeEditor *code = ((Tab *) tabs->currentWidget())->code; - QString selectedText = code->textCursor().selectedText(); - if (!selectedText.isEmpty()) { - findDialog->setSearchText(selectedText); - } - findDialog->show(); - findDialog->activateWindow(); -} - -void MainWindow::findNext(const QString &pattern, Qt::CaseSensitivity cs, bool all, - bool replace, const QString &replaceText) -{ - //! Clear all highlights and disable highlighting of current line - for (int i = 0; i < tabs->count(); i++) { - CodeEditor *code = ((Tab *) tabs->widget(i))->code; - disconnect(code, SIGNAL(cursorPositionChanged()), code, SLOT(highlightCurrentLine())); - code->setExtraSelections(QList()); - } - //! Restore highlight - if (pattern.isEmpty()) { - - for (int i = 0; i < tabs->count(); i++) { - CodeEditor *code = ((Tab *) tabs->widget(i))->code; - connect(code, SIGNAL(cursorPositionChanged()), code, SLOT(highlightCurrentLine())); - code->highlightCurrentLine(); - if (code->debugMode) - code->highlightDebugLine(code->currentDebugLine); - } - } else { - //If true, find all - if (all) { - for (int i = 0; i < tabs->count(); i++) { - QTextEdit::ExtraSelection selection; - QList extraSelections; - selection.format.setBackground(QBrush(Qt::green)); - QTextDocument *document = ((Tab *) tabs->widget(i))->getCodeDocument(); - QTextCursor newCursor = QTextCursor(document); - CodeEditor *code = ((Tab *) tabs->widget(i))->code; - - while (!newCursor.isNull() && !newCursor.atEnd()) { - if (cs == Qt::CaseSensitive) - newCursor = document->find(pattern, newCursor, QTextDocument::FindCaseSensitively); - else - newCursor = document->find(pattern, newCursor, 0); - //! Replace mode - if (replace && i == tabs->currentIndex()) { - newCursor.removeSelectedText(); - newCursor.insertText(replaceText); - } - if (!newCursor.isNull()) { - selection.cursor = newCursor; - extraSelections.append(selection); - } - } - - //! Highlight all - code->setExtraSelections(extraSelections); - } - } - //!Find next only - else { - QTextEdit::ExtraSelection selection; - QList extraSelections; - selection.format.setBackground(QBrush(Qt::green)); - QTextDocument *document = ((Tab *) tabs->currentWidget())->getCodeDocument(); - CodeEditor *code = ((Tab *) tabs->currentWidget())->code; - static QTextCursor newCursor(document); - //! if documents differ, cursor is ignored in QTextDocument::find() - if (replace) { - newCursor.removeSelectedText(); - newCursor.insertText(replaceText); - } - if (cs == Qt::CaseSensitive) - newCursor = document->find(pattern, newCursor, QTextDocument::FindCaseSensitively); - else - newCursor = document->find(pattern, newCursor, 0); - //! Continue from start - if (newCursor.isNull()) { - if (cs == Qt::CaseSensitive) - newCursor = document->find(pattern, newCursor, QTextDocument::FindCaseSensitively); - else - newCursor = document->find(pattern, newCursor, 0); - } - if (!newCursor.isNull()) { - selection.cursor = newCursor; - extraSelections.append(selection); - QTextCursor cursor = newCursor; - cursor.clearSelection(); - code->setTextCursor(cursor); - } - - code->setExtraSelections(extraSelections); - } - } -} - -void MainWindow::restorePrevSession(bool notNotify) -{ - int count = settings.value("tabscount", 0).toInt(); - if (count == 0 && !notNotify) { - QMessageBox::information(0, QString("SASM"), - tr("In the previous session was not open any of the saved tabs!")); - return; - } - settings.beginGroup("Tabs"); - for (int i = 0; i < count; i++) { - QString fileName = settings.value(QString::number(i)).toString(); - newFile(); - Tab *curTab = (Tab *) tabs->currentWidget(); - curTab->loadCodeFromFile(fileName); - setTabPath(fileName); - } - settings.endGroup(); -} - -void MainWindow::writeSettings() -{ - //! GUI - settings.beginGroup("MainWindow"); - settings.setValue("size", size()); - settings.setValue("pos", pos()); - unsigned int maxFlag = windowState() & Qt::WindowMaximized; - settings.setValue("maximized", maxFlag); - settings.endGroup(); - settings.setValue("windowstate", saveState()); - - //! Opened tabs - int prevTabsCount = settings.value("tabscount", 0).toInt(); - //! Remove previous - for (int i = 0; i < prevTabsCount; i++) - { - settings.remove(QString("Tabs/") + QString::number(i)); - } - //! Create current - settings.setValue("tabscount", tabs->count()); - settings.beginGroup("Tabs"); + connect(debugger, SIGNAL(printRegisters(QList)), &locker, + SLOT(unlock()), Qt::UniqueConnection); + connect(debugger, SIGNAL(finished()), &locker, SLOT(unlock()), + Qt::UniqueConnection); + if (settings.value("allregisters", false).toBool()) + debugger->doInput(QString("info all-registers\n"), infoRegisters); + else + debugger->doInput(QString("info registers\n"), infoRegisters); + } + } else if (registersWindow) { + registersWindow->close(); + registersWindow->clear(); + delete registersWindow; + registersWindow = 0; + registersDock->close(); + delete registersDock; + registersDock = 0; + } +} + +void MainWindow::setShowRegistersToUnchecked() { + debugShowRegistersAction->setChecked(false); +} + +void MainWindow::debugExit() { + settings.setValue("debugregisters", debugShowRegistersAction->isChecked()); + settings.setValue("debugmemory", debugShowMemoryAction->isChecked()); + settings.setValue("debugstate", saveState()); + CodeEditor* code = ((Tab*) tabs->currentWidget())->code; + disconnect(code, SIGNAL(addWatchSignal(const RuQPlainTextEdit::Watch&)), this, + SLOT(setShowMemoryToChecked(RuQPlainTextEdit::Watch))); + disconnect(debugger, SIGNAL(printLog(QString, QColor)), this, + SLOT(printLog(QString, QColor))); + disconnect(debugger, SIGNAL(printOutput(QString)), this, SLOT(printOutput(QString))); + code->setDebugDisabled(); + //! Many actions performed here - deleting of highlighting too + delete debugger; + debugger = 0; + closeAnyCommandWidget(); + debugShowRegistersAction->setChecked(false); + debugShowMemoryAction->setChecked(false); + printLogWithTime(tr("Debugging finished.") + '\n', Qt::darkGreen); + disableDebugActions(); +} + +void MainWindow::showAnyCommandWidget() { + debugAnyCommandWidget->show(); + debugAnyCommandWidget->setFocusOnLineEdit(); + connect(debugAnyCommandWidget, SIGNAL(performCommand(QString, bool)), this, + SLOT(debugRunCommand(QString, bool))); +} + +void MainWindow::closeAnyCommandWidget() { + disconnect(debugAnyCommandWidget, SIGNAL(performCommand(QString, bool)), this, + SLOT(debugRunCommand(QString, bool))); + debugAnyCommandWidget->close(); +} + +void MainWindow::debugRunCommand(QString command, bool print) { + static SignalLocker locker; + if (debugger->isStopped() && locker.tryLock()) { + connect(debugger, SIGNAL(printLog(QString, QColor)), &locker, SLOT(unlock()), + Qt::UniqueConnection); + connect(debugger, SIGNAL(finished()), &locker, SLOT(unlock()), Qt::UniqueConnection); + printLog("> " + command + "\n", QColor(32, 71, 247)); + if (print) debugger->doInput("p " + command + "\n", anyAction); + else + debugger->doInput(command + "\n", anyAction); + } +} + +void MainWindow::find() { + if (!findDialog) { + findDialog = new FindDialog(this); + connect(findDialog, + SIGNAL(findNext(QString, Qt::CaseSensitivity, bool, bool, QString)), this, + SLOT(findNext(QString, Qt::CaseSensitivity, bool, bool, QString))); + } + CodeEditor* code = ((Tab*) tabs->currentWidget())->code; + QString selectedText = code->textCursor().selectedText(); + if (!selectedText.isEmpty()) { + findDialog->setSearchText(selectedText); + } + findDialog->show(); + findDialog->activateWindow(); +} + +void MainWindow::findNext(const QString& pattern, Qt::CaseSensitivity cs, bool all, + bool replace, const QString& replaceText) { + //! Clear all highlights and disable highlighting of current line + for (int i = 0; i < tabs->count(); i++) { + CodeEditor* code = ((Tab*) tabs->widget(i))->code; + disconnect(code, SIGNAL(cursorPositionChanged()), code, SLOT(highlightCurrentLine())); + code->setExtraSelections(QList()); + } + //! Restore highlight + if (pattern.isEmpty()) { for (int i = 0; i < tabs->count(); i++) { - settings.setValue(QString::number(i), ((Tab *) tabs->widget(i))->getCurrentFilePath()); - } - settings.endGroup(); - - //! Save and open directory - settings.setValue("saveopendirectory", saveOpenDirectory); - - //! Splitters state - settings.setValue("logsplitterstate", splitter->saveState()); -} - -void MainWindow::openSettings() -{ - //! Initialize - if (!settingsWindow) { - settingsWindow = new QWidget(this, Qt::Window); - settingsWindow->setWindowModality(Qt::WindowModal); - settingsUi.setupUi(settingsWindow); - connect(settingsUi.buttonBox->button(QDialogButtonBox::Ok), - SIGNAL(clicked()), this, SLOT(exitSettings())); - connect(settingsUi.buttonBox->button(QDialogButtonBox::Apply), - SIGNAL(clicked()), this, SLOT(saveSettings())); - connect(settingsUi.buttonBox->button(QDialogButtonBox::Cancel), - SIGNAL(clicked()), this, SLOT(restoreSettingsAndExit())); - connect(settingsUi.resetAllButton, SIGNAL(clicked()), this, SLOT(resetAllSettings())); - connect(settingsUi.disableLinkingCheckbox, SIGNAL(stateChanged(int)), - this, SLOT(enableOrDisableLinkingEdit(int))); - - //! Colors - colorSignalMapper = new QSignalMapper(this); - colorButtons << - //! Foreground - settingsUi.keywordsColorButton << settingsUi.registersColorButton << - settingsUi.numbersColorButton << settingsUi.memoryColorButton << - settingsUi.labelsColorButton << settingsUi.commentsColorButton << - settingsUi.systemColorButton << settingsUi.iomacroColorButton << - settingsUi.quotationColorButton << - //! Background - settingsUi.keywordsColorButton_2 << settingsUi.registersColorButton_2 << - settingsUi.numbersColorButton_2 << settingsUi.memoryColorButton_2 << - settingsUi.labelsColorButton_2 << settingsUi.commentsColorButton_2 << - settingsUi.systemColorButton_2 << settingsUi.iomacroColorButton_2 << - settingsUi.quotationColorButton_2 << - //! Common - settingsUi.backgroundColorButton << settingsUi.lineNumberPanelColorButton << - settingsUi.fontColorButton << - settingsUi.currentLineColorButton << settingsUi.debugLineColorButton << - settingsUi.lineNumberFontColorButton; - - defaultColors << - //! According to colorButtons - QColor(Qt::blue) << QColor(153, 0, 204) << - QColor(255, 122, 0) << QColor(0, 128, 255) << - QColor(128, 0, 0) << QColor(Qt::darkGreen) << - QColor(Qt::darkCyan) << QColor(Qt::blue) << - QColor(128, 128, 128) << - QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) << - QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) << - QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) << - QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) << - QPalette().color(QPalette::Base) << - QPalette().color(QPalette::Base) << QPalette().color(QPalette::Window) << - QPalette().color(QPalette::WindowText) << - QColor(232, 232, 255) << QColor(235, 200, 40) << - QColor(QPalette::WindowText); - //! Add color to associative array - for (int i = 0; i < colorButtons.size(); i++) { - - QString name = colorButtons[i]->objectName(); - name.remove("Button"); - name.replace("_2", "bg"); - name = name.toLower(); - colorsMap.insert(name, defaultColors[i]); - - connect(colorButtons[i], SIGNAL(clicked()), colorSignalMapper, SLOT(map())); - colorSignalMapper->setMapping(colorButtons[i], colorButtons[i]); - } - connect(colorSignalMapper, SIGNAL(mapped(QWidget*)), this, SLOT(pickColor(QWidget*))); - - //! Fonts - fontsSignalMapper = new QSignalMapper(this); - fontCheckBoxes << - //! Bold - settingsUi.keywordsBoldCheckBox << settingsUi.registersBoldCheckBox << - settingsUi.numbersBoldCheckBox << settingsUi.memoryBoldCheckBox << - settingsUi.labelsBoldCheckBox << settingsUi.commentsBoldCheckBox << - settingsUi.systemBoldCheckBox << settingsUi.iomacroBoldCheckBox << - settingsUi.quotationBoldCheckBox << - //! Italic - settingsUi.keywordsItalicCheckBox << settingsUi.registersItalicCheckBox << - settingsUi.numbersItalicCheckBox << settingsUi.memoryItalicCheckBox << - settingsUi.labelsItalicCheckBox << settingsUi.commentsItalicCheckBox << - settingsUi.systemItalicCheckBox << settingsUi.iomacroItalicCheckBox << - settingsUi.quotationItalicCheckBox; - //! Add font to associative array - for (int i = 0; i < fontCheckBoxes.size(); i++) { - - QString name = fontCheckBoxes[i]->objectName(); - name.remove("CheckBox"); - name = name.toLower(); - - connect(fontCheckBoxes[i], SIGNAL(clicked()), fontsSignalMapper, SLOT(map())); - fontsSignalMapper->setMapping(fontCheckBoxes[i], fontCheckBoxes[i]); + CodeEditor* code = ((Tab*) tabs->widget(i))->code; + connect(code, SIGNAL(cursorPositionChanged()), code, SLOT(highlightCurrentLine())); + code->highlightCurrentLine(); + if (code->debugMode) code->highlightDebugLine(code->currentDebugLine); + } + } else { + // If true, find all + if (all) { + for (int i = 0; i < tabs->count(); i++) { + QTextEdit::ExtraSelection selection; + QList extraSelections; + selection.format.setBackground(QBrush(Qt::green)); + QTextDocument* document = ((Tab*) tabs->widget(i))->getCodeDocument(); + QTextCursor newCursor = QTextCursor(document); + CodeEditor* code = ((Tab*) tabs->widget(i))->code; + + while (!newCursor.isNull() && !newCursor.atEnd()) { + if (cs == Qt::CaseSensitive) + newCursor = + document->find(pattern, newCursor, QTextDocument::FindCaseSensitively); + else + newCursor = document->find(pattern, newCursor, 0); + //! Replace mode + if (replace && i == tabs->currentIndex()) { + newCursor.removeSelectedText(); + newCursor.insertText(replaceText); + } + if (!newCursor.isNull()) { + selection.cursor = newCursor; + extraSelections.append(selection); + } } - connect(fontsSignalMapper, SIGNAL(mapped(QWidget*)), this, SLOT(changeHighlightingFont(QWidget*))); - connect(settingsUi.currentLineCheckBox, SIGNAL(clicked(bool)), this, SLOT(changeHighlightingLineMode(bool))); - - backupSettings(); - initAssemblerSettings(true); - } else { - initAssemblerSettings(false); + //! Highlight all + code->setExtraSelections(extraSelections); + } } - - //! Set settings - //! Common - settingsUi.startWindow->setCurrentIndex(settings.value("startwindow", 0).toInt()); - settingsUi.language->setCurrentIndex(settings.value("language", 0).toInt()); - settingsUi.fontComboBox->setCurrentFont(QFont(settings.value("fontfamily", - QString("Courier New")).value())); - settingsUi.fontSizeSpinBox->setValue(settings.value("fontsize", 12).toInt()); - if (settings.value("allregisters", false).toBool()) - settingsUi.registersYesRadioButton->setChecked(true); - else - settingsUi.registersNoRadioButton->setChecked(true); - settingsUi.insertDebugStringCheckBox->setChecked(settings.value("insertdebugstring", true).toBool()); + //! Find next only + else { + QTextEdit::ExtraSelection selection; + QList extraSelections; + selection.format.setBackground(QBrush(Qt::green)); + QTextDocument* document = ((Tab*) tabs->currentWidget())->getCodeDocument(); + CodeEditor* code = ((Tab*) tabs->currentWidget())->code; + static QTextCursor newCursor(document); + //! if documents differ, cursor is ignored in QTextDocument::find() + if (replace) { + newCursor.removeSelectedText(); + newCursor.insertText(replaceText); + } + if (cs == Qt::CaseSensitive) + newCursor = + document->find(pattern, newCursor, QTextDocument::FindCaseSensitively); + else + newCursor = document->find(pattern, newCursor, 0); + //! Continue from start + if (newCursor.isNull()) { + if (cs == Qt::CaseSensitive) + newCursor = + document->find(pattern, newCursor, QTextDocument::FindCaseSensitively); + else + newCursor = document->find(pattern, newCursor, 0); + } + if (!newCursor.isNull()) { + selection.cursor = newCursor; + extraSelections.append(selection); + QTextCursor cursor = newCursor; + cursor.clearSelection(); + code->setTextCursor(cursor); + } + + code->setExtraSelections(extraSelections); + } + } +} + +void MainWindow::restorePrevSession(bool notNotify) { + int count = settings.value("tabscount", 0).toInt(); + if (count == 0 && !notNotify) { + QMessageBox::information( + 0, QString("SASM"), + tr("In the previous session was not open any of the saved tabs!")); + return; + } + settings.beginGroup("Tabs"); + for (int i = 0; i < count; i++) { + QString fileName = settings.value(QString::number(i)).toString(); + newFile(); + Tab* curTab = (Tab*) tabs->currentWidget(); + curTab->loadCodeFromFile(fileName); + setTabPath(fileName); + } + settings.endGroup(); +} + +void MainWindow::writeSettings() { + //! GUI + settings.beginGroup("MainWindow"); + settings.setValue("size", size()); + settings.setValue("pos", pos()); + unsigned int maxFlag = windowState() & Qt::WindowMaximized; + settings.setValue("maximized", maxFlag); + settings.endGroup(); + settings.setValue("windowstate", saveState()); + + //! Opened tabs + int prevTabsCount = settings.value("tabscount", 0).toInt(); + //! Remove previous + for (int i = 0; i < prevTabsCount; i++) { + settings.remove(QString("Tabs/") + QString::number(i)); + } + //! Create current + settings.setValue("tabscount", tabs->count()); + settings.beginGroup("Tabs"); + for (int i = 0; i < tabs->count(); i++) { + settings.setValue(QString::number(i), ((Tab*) tabs->widget(i))->getCurrentFilePath()); + } + settings.endGroup(); + + //! Save and open directory + settings.setValue("saveopendirectory", saveOpenDirectory); + + //! Splitters state + settings.setValue("logsplitterstate", splitter->saveState()); +} + +void MainWindow::openSettings() { + //! Initialize + if (!settingsWindow) { + settingsWindow = new QWidget(this, Qt::Window); + settingsWindow->setWindowModality(Qt::WindowModal); + settingsUi.setupUi(settingsWindow); + connect(settingsUi.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, + SLOT(exitSettings())); + connect(settingsUi.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), + this, SLOT(saveSettings())); + connect(settingsUi.buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), + this, SLOT(restoreSettingsAndExit())); + connect(settingsUi.resetAllButton, SIGNAL(clicked()), this, SLOT(resetAllSettings())); + connect(settingsUi.disableLinkingCheckbox, SIGNAL(stateChanged(int)), this, + SLOT(enableOrDisableLinkingEdit(int))); + connect(settingsUi.runInCurrentDirectoryCheckbox, SIGNAL(stateChanged(int)), this, + SLOT(enableOrDisableObjectFilenameLabel(int))); //! Colors + colorSignalMapper = new QSignalMapper(this); + colorButtons << + //! Foreground + settingsUi.keywordsColorButton << settingsUi.registersColorButton + << settingsUi.numbersColorButton << settingsUi.memoryColorButton + << settingsUi.labelsColorButton << settingsUi.commentsColorButton + << settingsUi.systemColorButton << settingsUi.iomacroColorButton + << settingsUi.quotationColorButton << + //! Background + settingsUi.keywordsColorButton_2 << settingsUi.registersColorButton_2 + << settingsUi.numbersColorButton_2 << settingsUi.memoryColorButton_2 + << settingsUi.labelsColorButton_2 << settingsUi.commentsColorButton_2 + << settingsUi.systemColorButton_2 << settingsUi.iomacroColorButton_2 + << settingsUi.quotationColorButton_2 << + //! Common + settingsUi.backgroundColorButton << settingsUi.lineNumberPanelColorButton + << settingsUi.fontColorButton << settingsUi.currentLineColorButton + << settingsUi.debugLineColorButton + << settingsUi.lineNumberFontColorButton; + + defaultColors << + //! According to colorButtons + QColor(Qt::blue) << QColor(153, 0, 204) << QColor(255, 122, 0) + << QColor(0, 128, 255) << QColor(128, 0, 0) << QColor(Qt::darkGreen) + << QColor(Qt::darkCyan) << QColor(Qt::blue) << QColor(128, 128, 128) + << QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) + << QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) + << QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) + << QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) + << QPalette().color(QPalette::Base) << QPalette().color(QPalette::Base) + << QPalette().color(QPalette::Window) + << QPalette().color(QPalette::WindowText) << QColor(232, 232, 255) + << QColor(235, 200, 40) << QColor(QPalette::WindowText); + //! Add color to associative array for (int i = 0; i < colorButtons.size(); i++) { - pickColor((QWidget *) colorButtons[i], true); + QString name = colorButtons[i]->objectName(); + name.remove("Button"); + name.replace("_2", "bg"); + name = name.toLower(); + colorsMap.insert(name, defaultColors[i]); + + connect(colorButtons[i], SIGNAL(clicked()), colorSignalMapper, SLOT(map())); + colorSignalMapper->setMapping(colorButtons[i], colorButtons[i]); } + connect(colorSignalMapper, SIGNAL(mapped(QWidget*)), this, SLOT(pickColor(QWidget*))); + //! Fonts + fontsSignalMapper = new QSignalMapper(this); + fontCheckBoxes << + //! Bold + settingsUi.keywordsBoldCheckBox << settingsUi.registersBoldCheckBox + << settingsUi.numbersBoldCheckBox << settingsUi.memoryBoldCheckBox + << settingsUi.labelsBoldCheckBox << settingsUi.commentsBoldCheckBox + << settingsUi.systemBoldCheckBox << settingsUi.iomacroBoldCheckBox + << settingsUi.quotationBoldCheckBox << + //! Italic + settingsUi.keywordsItalicCheckBox << settingsUi.registersItalicCheckBox + << settingsUi.numbersItalicCheckBox << settingsUi.memoryItalicCheckBox + << settingsUi.labelsItalicCheckBox << settingsUi.commentsItalicCheckBox + << settingsUi.systemItalicCheckBox << settingsUi.iomacroItalicCheckBox + << settingsUi.quotationItalicCheckBox; + //! Add font to associative array for (int i = 0; i < fontCheckBoxes.size(); i++) { - changeHighlightingFont((QWidget *) fontCheckBoxes[i], true); - } + QString name = fontCheckBoxes[i]->objectName(); + name.remove("CheckBox"); + name = name.toLower(); - settingsUi.currentLineCheckBox->setChecked(settings.value("currentlinemode", true).toBool()); - settingsWindow->show(); -} - -void MainWindow::initAssemblerSettings(bool firstOpening) -{ - if (firstOpening) { - /*! - * - * Assembler Dependent Options Begin - * - */ - connect(settingsUi.nasmRadioButton, SIGNAL(clicked()), this, SLOT(changeAssembler())); - connect(settingsUi.gasRadioButton, SIGNAL(clicked()), this, SLOT(changeAssembler())); - connect(settingsUi.fasmRadioButton, SIGNAL(clicked()), this, SLOT(changeAssembler())); - #ifdef Q_OS_WIN32 - connect(settingsUi.masmRadioButton, SIGNAL(clicked()), this, SLOT(changeAssembler())); - connect(settingsUi.masmRadioButton, SIGNAL(clicked()), this, SLOT(printMasmInfo())); - //! Else it is Linux - #else - settingsUi.masmRadioButton->setEnabled(false); - #endif - - /*! - * - * Assembler Dependent Options End - * - */ - - connect(settingsUi.x86RadioButton, SIGNAL(toggled(bool)), this, SLOT(changeMode(bool))); - - //! Start text editor - settingsStartTextEditor = new CodeEditor(0, false); - settingsHighlighter = new Highlighter(assembler); - settingsHighlighter->setDocument(settingsStartTextEditor->document()); - QVBoxLayout *startTextLayout = new QVBoxLayout; - startTextLayout->addWidget(settingsStartTextEditor); - settingsStartTextEditor->setFixedHeight(120); - settingsUi.startTextWidget->setLayout(startTextLayout); + connect(fontCheckBoxes[i], SIGNAL(clicked()), fontsSignalMapper, SLOT(map())); + fontsSignalMapper->setMapping(fontCheckBoxes[i], fontCheckBoxes[i]); } + connect(fontsSignalMapper, SIGNAL(mapped(QWidget*)), this, + SLOT(changeHighlightingFont(QWidget*))); - settingsStartTextEditor->setPlainText(settings.value("starttext").toString()); - - //! Build options - QString options = assembler->getAssemblerOptions(); - settingsUi.assemblyOptionsEdit->setText(settings.value("assemblyoptions", options).toString()); - - QString linkerOptions = assembler->getLinkerOptions(); - settingsUi.linkingOptionsEdit->setText(settings.value("linkingoptions", linkerOptions).toString()); - - settingsUi.objectFileNameEdit->setText(settings.value("objectfilename", "program.o").toString()); - - settingsUi.disableLinkingCheckbox->setChecked(settings.value("disablelinking", false).toBool()); - - settingsUi.runInCurrentDirectoryCheckbox->setChecked(settings.value("currentdir", false).toBool()); - - QString assemblerPath = assembler->getAssemblerPath(); - settingsUi.assemblerPathEdit->setText(settings.value("assemblerpath", assemblerPath).toString()); - - #ifdef Q_OS_WIN32 - settingsUi.linkerPathEdit->setText(settings.value("linkerpath", Common::applicationDataPath() + "/MinGW/bin/gcc.exe").toString()); - #else - settingsUi.linkerPathEdit->setText(settings.value("linkerpath", "gcc").toString()); - #endif - - disconnect(settingsUi.x86RadioButton, SIGNAL(toggled(bool)), this, SLOT(changeMode(bool))); - //! Mode - if (assembler->isx86()) - settingsUi.x86RadioButton->setChecked(true); - else - settingsUi.x64RadioButton->setChecked(true); - connect(settingsUi.x86RadioButton, SIGNAL(toggled(bool)), this, SLOT(changeMode(bool))); + connect(settingsUi.currentLineCheckBox, SIGNAL(clicked(bool)), this, + SLOT(changeHighlightingLineMode(bool))); + backupSettings(); + initAssemblerSettings(true); + } else { + initAssemblerSettings(false); + } + + //! Set settings + //! Common + settingsUi.startWindow->setCurrentIndex(settings.value("startwindow", 0).toInt()); + settingsUi.language->setCurrentIndex(settings.value("language", 0).toInt()); + settingsUi.fontComboBox->setCurrentFont( + QFont(settings.value("fontfamily", QString("Courier New")).value())); + settingsUi.fontSizeSpinBox->setValue(settings.value("fontsize", 12).toInt()); + if (settings.value("allregisters", false).toBool()) + settingsUi.registersYesRadioButton->setChecked(true); + else + settingsUi.registersNoRadioButton->setChecked(true); + settingsUi.insertDebugStringCheckBox->setChecked( + settings.value("insertdebugstring", true).toBool()); + + //! Colors + for (int i = 0; i < colorButtons.size(); i++) { + pickColor((QWidget*) colorButtons[i], true); + } + //! Fonts + for (int i = 0; i < fontCheckBoxes.size(); i++) { + changeHighlightingFont((QWidget*) fontCheckBoxes[i], true); + } + + settingsUi.currentLineCheckBox->setChecked( + settings.value("currentlinemode", true).toBool()); + settingsWindow->show(); +} + +void MainWindow::initAssemblerSettings(bool firstOpening) { + if (firstOpening) { /*! * * Assembler Dependent Options Begin * */ + connect(settingsUi.nasmRadioButton, SIGNAL(clicked()), this, SLOT(changeAssembler())); + connect(settingsUi.gasRadioButton, SIGNAL(clicked()), this, SLOT(changeAssembler())); + connect(settingsUi.fasmRadioButton, SIGNAL(clicked()), this, SLOT(changeAssembler())); +#ifdef Q_OS_WIN32 + connect(settingsUi.masmRadioButton, SIGNAL(clicked()), this, SLOT(changeAssembler())); + connect(settingsUi.masmRadioButton, SIGNAL(clicked()), this, SLOT(printMasmInfo())); +//! Else it is Linux +#else + settingsUi.masmRadioButton->setEnabled(false); +#endif - QString assemblerName = settings.value("assembler", QString("NASM")).toString(); - if (assemblerName == "MASM") { - settingsUi.x64RadioButton->setEnabled(false); - printMasmInfo(); - } - if (assemblerName == "NASM") { - settingsUi.nasmRadioButton->setChecked(true); - } else if (assemblerName == "GAS") { - settingsUi.gasRadioButton->setChecked(true); - } else if (assemblerName == "FASM") { - settingsUi.fasmRadioButton->setChecked(true); - } else if (assemblerName == "MASM") { - settingsUi.masmRadioButton->setChecked(true); - } + /*! + * + * Assembler Dependent Options End + * + */ + + connect(settingsUi.x86RadioButton, SIGNAL(toggled(bool)), this, + SLOT(changeMode(bool))); + + //! Start text editor + settingsStartTextEditor = new CodeEditor(0, false); + settingsHighlighter = new Highlighter(assembler); + settingsHighlighter->setDocument(settingsStartTextEditor->document()); + QVBoxLayout* startTextLayout = new QVBoxLayout; + startTextLayout->addWidget(settingsStartTextEditor); + settingsStartTextEditor->setFixedHeight(120); + settingsUi.startTextWidget->setLayout(startTextLayout); + } + + settingsStartTextEditor->setPlainText(settings.value("starttext").toString()); + + //! Build options + QString options = assembler->getAssemblerOptions(); + settingsUi.assemblyOptionsEdit->setText( + settings.value("assemblyoptions", options).toString()); + + QString linkerOptions = assembler->getLinkerOptions(); + settingsUi.linkingOptionsEdit->setText( + settings.value("linkingoptions", linkerOptions).toString()); + + settingsUi.objectFileNameEdit->setText( + settings.value("objectfilename", "program.o").toString()); + + settingsUi.disableLinkingCheckbox->setChecked( + settings.value("disablelinking", false).toBool()); + + settingsUi.runInCurrentDirectoryCheckbox->setChecked( + settings.value("currentdir", false).toBool()); + + QString assemblerPath = assembler->getAssemblerPath(); + settingsUi.assemblerPathEdit->setText( + settings.value("assemblerpath", assemblerPath).toString()); + +#ifdef Q_OS_WIN32 + settingsUi.linkerPathEdit->setText( + settings.value("linkerpath", Common::applicationDataPath() + "/MinGW/bin/gcc.exe") + .toString()); +#else + settingsUi.linkerPathEdit->setText(settings.value("linkerpath", "gcc").toString()); +#endif + + disconnect(settingsUi.x86RadioButton, SIGNAL(toggled(bool)), this, + SLOT(changeMode(bool))); + //! Mode + if (assembler->isx86()) settingsUi.x86RadioButton->setChecked(true); + else + settingsUi.x64RadioButton->setChecked(true); + connect(settingsUi.x86RadioButton, SIGNAL(toggled(bool)), this, SLOT(changeMode(bool))); + + /*! + * + * Assembler Dependent Options Begin + * + */ + + QString assemblerName = settings.value("assembler", QString("NASM")).toString(); + if (assemblerName == "MASM") { + settingsUi.x64RadioButton->setEnabled(false); + printMasmInfo(); + } + if (assemblerName == "NASM") { + settingsUi.nasmRadioButton->setChecked(true); + } else if (assemblerName == "GAS") { + settingsUi.gasRadioButton->setChecked(true); + } else if (assemblerName == "FASM") { + settingsUi.fasmRadioButton->setChecked(true); + } else if (assemblerName == "MASM") { + settingsUi.masmRadioButton->setChecked(true); + } } /*! @@ -1902,28 +1878,28 @@ void MainWindow::initAssemblerSettings(bool firstOpening) * */ -void MainWindow::printMasmInfo() -{ - settingsUi.infoLabel->setText(tr("Please set path to MASM assembler (ml.exe) and linker (link.exe) on your computer ") + - tr("in fields \"Assembler path\" and \"Linker path\" above.")); +void MainWindow::printMasmInfo() { + settingsUi.infoLabel->setText( + tr("Please set path to MASM assembler (ml.exe) and linker (link.exe) on your " + "computer ") + + tr("in fields \"Assembler path\" and \"Linker path\" above.")); } /*! * * Assembler Dependent Options Begin * */ -void MainWindow::changeAssembler() -{ - if (settingsUi.nasmRadioButton->isChecked()) - settings.setValue("assembler", QString("NASM")); - else if (settingsUi.gasRadioButton->isChecked()) { - settings.setValue("assembler", QString("GAS")); - } else if (settingsUi.fasmRadioButton->isChecked()) { - settings.setValue("assembler", QString("FASM")); - } else if (settingsUi.masmRadioButton->isChecked()) { - settings.setValue("assembler", QString("MASM")); - } - recreateAssembler(); +void MainWindow::changeAssembler() { + if (settingsUi.nasmRadioButton->isChecked()) + settings.setValue("assembler", QString("NASM")); + else if (settingsUi.gasRadioButton->isChecked()) { + settings.setValue("assembler", QString("GAS")); + } else if (settingsUi.fasmRadioButton->isChecked()) { + settings.setValue("assembler", QString("FASM")); + } else if (settingsUi.masmRadioButton->isChecked()) { + settings.setValue("assembler", QString("MASM")); + } + recreateAssembler(); } /*! @@ -1932,388 +1908,371 @@ void MainWindow::changeAssembler() * */ -void MainWindow::changeMode(bool x86) -{ - if (x86) - settings.setValue("mode", QString("x86")); - else - settings.setValue("mode", QString("x64")); - recreateAssembler(); -} - -void MainWindow::recreateAssembler(bool start) -{ - if (assembler) { - delete assembler; - assembler = 0; - } - bool x86 = true; - if (settings.value("mode", QString("x86")).toString() != "x86") - x86 = false; - /*! - * - * Assembler Dependent Options Begin - * - */ - - QString assemblerName = settings.value("assembler", QString("NASM")).toString(); - if (!start) { - if (assemblerName == "MASM") { - settingsUi.x64RadioButton->setEnabled(false); - if (settingsUi.x64RadioButton->isChecked()) { - settingsUi.x86RadioButton->setChecked(true); - return; - } - } else { - settingsUi.x64RadioButton->setEnabled(true); - settingsUi.infoLabel->setText(""); - } - } - if (assemblerName == "NASM") { - assembler = new NASM(x86); - } else if (assemblerName == "GAS") { - assembler = new GAS(x86); - } else if (assemblerName == "FASM") { - assembler = new FASM(x86); - } else if (assemblerName == "MASM") { - assembler = new MASM(x86); - } - - /*! - * - * Assembler Dependent Options End - * - */ - - - if (!start) { - settingsUi.assemblyOptionsEdit->setText(assembler->getAssemblerOptions()); - settingsUi.linkingOptionsEdit->setText(assembler->getLinkerOptions()); - settingsUi.objectFileNameEdit->setText("program.o"); - settingsUi.disableLinkingCheckbox->setChecked(false); - settingsUi.runInCurrentDirectoryCheckbox->setChecked(false); - settingsUi.assemblerPathEdit->setText(assembler->getAssemblerPath()); - settingsUi.linkerPathEdit->setText(assembler->getLinkerPath()); - settings.setValue("assemblyoptions", assembler->getAssemblerOptions()); - settings.setValue("linkingoptions", assembler->getLinkerOptions()); - settings.setValue("objectfilename", "program.o"); - settings.setValue("disablelinking", false); - settings.setValue("currentdir", false); - settings.setValue("assemblerpath", assembler->getAssemblerPath()); - settings.setValue("linkerpath", assembler->getLinkerPath()); - changeStartText(); - recreateHighlighter(); - } -} - -void MainWindow::changeStartText() -{ - settingsStartTextEditor->setPlainText(assembler->getStartText()); - settings.setValue("starttext", assembler->getStartText()); -} - -void MainWindow::backupSettings() -{ - backupAssembler = settings.value("assembler", QString("NASM")).toString(); - backupMode = settings.value("mode", QString("x86")).toString(); - backupAssemblerOptions = settings.value("assemblyoptions", assembler->getAssemblerOptions()).toString(); - backupAssemblerPath = settings.value("assemblerpath", assembler->getAssemblerPath()).toString(); - backupLinkerOptions = settings.value("linkingoptions", assembler->getLinkerOptions()).toString(); - backupObjectFileName = settings.value("objectfilename", "program.o").toString(); - backupDisableLinking = settings.value("disablelinking", false).toBool(); - backupCurrentDir = settings.value("currentdir", false).toBool(); - backupStartText = settings.value("starttext", assembler->getStartText()).toString(); - backupLinkerPath = settings.value("linkerpath", assembler->getLinkerPath()).toString(); -} - -void MainWindow::restoreSettingsAndExit() -{ - settings.setValue("assembler", backupAssembler); - settings.setValue("mode", backupMode); - recreateAssembler(); - settings.setValue("assemblyoptions", backupAssemblerOptions); - settings.setValue("assemblerpath", backupAssemblerPath); - settings.setValue("linkingoptions", backupLinkerOptions); - settings.setValue("objectfilename", backupObjectFileName); - settings.setValue("disablelinking", backupDisableLinking); - settings.setValue("currentdir", backupCurrentDir); - settings.setValue("starttext", backupStartText); - settings.setValue("linkerpath", backupLinkerPath); - settingsWindow->close(); -} - -void MainWindow::recreateHighlighter() -{ - if (highlighter) { - delete highlighter; - highlighter = new Highlighter(assembler); - } - if (tabs && tabs->count() > 0) { - Tab *currentTab = (Tab *) tabs->currentWidget(); - highlighter->setDocument(currentTab->getCodeDocument()); - } - delete settingsHighlighter; - settingsHighlighter = new Highlighter(assembler); - settingsHighlighter->setDocument(settingsStartTextEditor->document()); -} - -void MainWindow::saveSettings() -{ - settings.setValue("startwindow", settingsUi.startWindow->currentIndex()); - settings.setValue("language", settingsUi.language->currentIndex()); - startText = settingsStartTextEditor->toPlainText(); - settings.setValue("allregisters", settingsUi.registersYesRadioButton->isChecked()); - settings.setValue("insertdebugstring", settingsUi.insertDebugStringCheckBox->isChecked()); - - //! Change fonts - settings.setValue("fontfamily", settingsUi.fontComboBox->currentFont().family()); - settings.setValue("fontsize", settingsUi.fontSizeSpinBox->value()); - for (int i = 0; i < tabs->count(); i++) { - Tab *tab = (Tab *) tabs->widget(i); - tab->setFonts(); - } - QFont compilerOutFont; - compilerOutFont.setPointSize(settings.value("fontsize", 12).toInt()); - compilerOut->setFont(compilerOutFont); - - settings.setValue("assemblyoptions", settingsUi.assemblyOptionsEdit->text()); - settings.setValue("linkingoptions", settingsUi.linkingOptionsEdit->text()); - settings.setValue("objectfilename", settingsUi.objectFileNameEdit->text()); - settings.setValue("disablelinking", settingsUi.disableLinkingCheckbox->isChecked()); - settings.setValue("currentdir", settingsUi.runInCurrentDirectoryCheckbox->isChecked()); - settings.setValue("assemblerpath", settingsUi.assemblerPathEdit->text()); - settings.setValue("linkerpath", settingsUi.linkerPathEdit->text()); - settings.setValue("starttext", settingsStartTextEditor->document()->toPlainText()); - - backupSettings(); -} - -void MainWindow::pickColor(QWidget *button, bool init) -{ - QPushButton *colorButton = (QPushButton *) button; - QString name = colorButton->objectName(); - name.remove("Button"); - name.replace("_2", "bg"); - name = name.toLower(); - if (!init) { - QColor color = QColorDialog::getColor(settings.value(name, colorsMap[name]).value()); - if (color.isValid()) { - settings.setValue(name, color); - if (name == "backgroundcolor") { - int r, g, b; - color.getRgb(&r, &g, &b); - for (int i = 9; i < 18; i++) { - QString buttonName = colorButtons[i]->objectName(); - buttonName.remove("Button"); - buttonName.replace("_2", "bg"); - buttonName = buttonName.toLower(); - settings.setValue(buttonName, color); - colorButtons[i]->setStyleSheet(QString("background-color: rgb(%1, %2, %3)").arg(r).arg(g).arg(b)); - } - } - recreateHighlighter(); - } - } - int r, g, b; - QColor color = settings.value(name, colorsMap[name]).value(); - color.getRgb(&r, &g, &b); - colorButton->setStyleSheet(QString("background-color: rgb(%1, %2, %3)").arg(r).arg(g).arg(b)); -} - -void MainWindow::changeHighlightingFont(QWidget *box, bool init) -{ - QCheckBox *checkBox = (QCheckBox *) box; - QString name = checkBox->objectName(); - name.remove("CheckBox"); - name = name.toLower(); - if (init) { - bool defaultState = (name == "keywordsbold") ? true : false; - checkBox->setChecked(settings.value(name, defaultState).toBool()); - } else { - settings.setValue(name, checkBox->isChecked()); - recreateHighlighter(); - } -} - -void MainWindow::changeHighlightingLineMode(bool mode) -{ - settings.setValue("currentlinemode", mode); -} - -void MainWindow::exitSettings() -{ - saveSettings(); - settingsWindow->close(); +void MainWindow::changeMode(bool x86) { + if (x86) settings.setValue("mode", QString("x86")); + else + settings.setValue("mode", QString("x64")); + recreateAssembler(); } -void MainWindow::resetAllSettings() -{ - //! Ask before execution - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Warning); - msgBox.addButton(tr("Yes"), QMessageBox::YesRole); - QPushButton *cancelButton = msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole); - msgBox.setWindowTitle(tr("Warning!")); - msgBox.setText(tr("All settings will be deleted and all unsaved data will be lost. Are you sure?")); - msgBox.exec(); - if (msgBox.clickedButton() == cancelButton) { +void MainWindow::recreateAssembler(bool start) { + if (assembler) { + delete assembler; + assembler = 0; + } + bool x86 = true; + if (settings.value("mode", QString("x86")).toString() != "x86") x86 = false; + /*! + * + * Assembler Dependent Options Begin + * + */ + + QString assemblerName = settings.value("assembler", QString("NASM")).toString(); + if (!start) { + if (assemblerName == "MASM") { + settingsUi.x64RadioButton->setEnabled(false); + if (settingsUi.x64RadioButton->isChecked()) { + settingsUi.x86RadioButton->setChecked(true); return; - } - - settings.remove("MainWindow/size"); - settings.remove("MainWindow/pos"); - - int prevTabsCount = settings.value("tabscount", 0).toInt(); - //! Remove previous - for (int i = 0; i < prevTabsCount; i++) - settings.remove(QString("Tabs/") + QString::number(i)); - - settings.clear(); - - closeFromCloseAll = true; - close(); -} - -void MainWindow::changeActionsState(int widgetIndex) -{ - //! Get started window - if (widgetIndex == 0) { - closeAction->setEnabled(false); - saveAction->setEnabled(false); - saveAsAction->setEnabled(false); - saveExeAction->setEnabled(false); - findAction->setEnabled(false); - commentAction->setEnabled(false); - uncommentAction->setEnabled(false); - undoAction->setEnabled(false); - redoAction->setEnabled(false); - cutAction->setEnabled(false); - copyAction->setEnabled(false); - pasteAction->setEnabled(false); - deleteAction->setEnabled(false); - selectAllAction->setEnabled(false); - putTabAction->setEnabled(false); - deleteTabAction->setEnabled(false); - buildAction->setEnabled(false); - runAction->setEnabled(false); - runExeAction->setEnabled(false); - stopAction->setEnabled(false); - debugAction->setEnabled(false); - debugNextAction->setEnabled(false); - debugNextNiAction->setEnabled(false); - debugShowRegistersAction->setEnabled(false); - debugToggleBreakpointAction->setEnabled(false); - debugShowMemoryAction->setEnabled(false); - } else { - closeAction->setEnabled(true); - saveAction->setEnabled(true); - saveAsAction->setEnabled(true); - saveExeAction->setEnabled(true); - findAction->setEnabled(true); - pasteAction->setEnabled(true); - selectAllAction->setEnabled(true); - putTabAction->setEnabled(true); - deleteTabAction->setEnabled(true); - buildAction->setEnabled(true); - runAction->setEnabled(true); - runExeAction->setEnabled(true); - debugAction->setEnabled(true); - debugToggleBreakpointAction->setEnabled(true); - } -} - -void MainWindow::openHelp() -{ - help = new QTextBrowser; - help->setAttribute(Qt::WA_DeleteOnClose); - QFile helpFile; - //! language 0=Russian - if (settings.value("language", 0).toInt() == 0) { - helpFile.setFileName(":help/help.html"); + } } else { - //! English and other languages - helpFile.setFileName(":help/helpENG.html"); - } - - helpFile.open(QFile::ReadOnly); - QTextStream helpText(&helpFile); - helpText.setCodec("utf-8"); - help->setHtml(helpText.readAll()); - helpFile.close(); - help->setWindowState(Qt::WindowMaximized); - help->setOpenExternalLinks(true); - help->setWindowTitle(tr("Help")); - help->setWindowIcon(QIcon(":images/mainIcon.png")); - help->show(); -} - -void MainWindow::openAbout() -{ - QMessageBox::about(this, tr("About SASM"), - tr("SASM (SimpleASM) ") + SASM_VERSION + " - " + - tr("simple Open Source IDE for NASM, MASM, GAS and FASM assembler languages.") + '\n' + - tr("Licensed under the GNU GPL v3.0") + '\n' + - tr("Based on the Qt.") + '\n' + - tr("Copyright (c) 2013 Dmitriy Manushin") + '\n' + - tr("Development and idea - Dmitriy Manushin") + '\n' + - tr("Icon and advices - Alick Gaybullaev") + '\n' + '\n' + - tr("Wishes and error messages are sent to the e-mail: Dman1095@gmail.com") + '\n' + - tr("More information on the site: http://dman95.github.io/SASM/") + '\n' + '\n' + - tr("Donate:") + '\n' + - tr("PayPal - Dman1095@gmail.com") + '\n' + - tr("WMZ - Z282016332582") + '\n' + - tr("WMR - R331674303467") - ); -} - -void MainWindow::onMessageReceived(const QString &message) -{ - raise(); - activateWindow(); - if (message.startsWith("run")) { - openFile(message.mid(3)); - } -} - -void MainWindow::dragEnterEvent(QDragEnterEvent *event) -{ - if (event->mimeData()->hasUrls()) - { - event->acceptProposedAction(); - } -} - -void MainWindow::dropEvent(QDropEvent *event) -{ - foreach (const QUrl &url, event->mimeData()->urls()) - openFile(url.toLocalFile()); -} - -bool MainWindow::removeDirRecuresively(const QString &dirName){ - bool result = true; - QDir dir(dirName); - - if (dir.exists(dirName)) { - Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | - QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) { - if (info.isDir()) { - result = removeDirRecuresively(info.absoluteFilePath()); - } - else { - result = QFile::remove(info.absoluteFilePath()); - } - - if (!result) { - return result; - } + settingsUi.x64RadioButton->setEnabled(true); + settingsUi.infoLabel->setText(""); + } + } + if (assemblerName == "NASM") { + assembler = new NASM(x86); + } else if (assemblerName == "GAS") { + assembler = new GAS(x86); + } else if (assemblerName == "FASM") { + assembler = new FASM(x86); + } else if (assemblerName == "MASM") { + assembler = new MASM(x86); + } + + /*! + * + * Assembler Dependent Options End + * + */ + + if (!start) { + settingsUi.assemblyOptionsEdit->setText(assembler->getAssemblerOptions()); + settingsUi.linkingOptionsEdit->setText(assembler->getLinkerOptions()); + settingsUi.objectFileNameEdit->setText("program.o"); + settingsUi.disableLinkingCheckbox->setChecked(false); + settingsUi.runInCurrentDirectoryCheckbox->setChecked(false); + settingsUi.assemblerPathEdit->setText(assembler->getAssemblerPath()); + settingsUi.linkerPathEdit->setText(assembler->getLinkerPath()); + settings.setValue("assemblyoptions", assembler->getAssemblerOptions()); + settings.setValue("linkingoptions", assembler->getLinkerOptions()); + settings.setValue("objectfilename", "program.o"); + settings.setValue("disablelinking", false); + settings.setValue("currentdir", false); + settings.setValue("assemblerpath", assembler->getAssemblerPath()); + settings.setValue("linkerpath", assembler->getLinkerPath()); + changeStartText(); + recreateHighlighter(); + } +} + +void MainWindow::changeStartText() { + settingsStartTextEditor->setPlainText(assembler->getStartText()); + settings.setValue("starttext", assembler->getStartText()); +} + +void MainWindow::backupSettings() { + backupAssembler = settings.value("assembler", QString("NASM")).toString(); + backupMode = settings.value("mode", QString("x86")).toString(); + backupAssemblerOptions = + settings.value("assemblyoptions", assembler->getAssemblerOptions()).toString(); + backupAssemblerPath = + settings.value("assemblerpath", assembler->getAssemblerPath()).toString(); + backupLinkerOptions = + settings.value("linkingoptions", assembler->getLinkerOptions()).toString(); + backupObjectFileName = settings.value("objectfilename", "program.o").toString(); + backupDisableLinking = settings.value("disablelinking", false).toBool(); + backupCurrentDir = settings.value("currentdir", false).toBool(); + backupStartText = settings.value("starttext", assembler->getStartText()).toString(); + backupLinkerPath = settings.value("linkerpath", assembler->getLinkerPath()).toString(); +} + +void MainWindow::restoreSettingsAndExit() { + settings.setValue("assembler", backupAssembler); + settings.setValue("mode", backupMode); + recreateAssembler(); + settings.setValue("assemblyoptions", backupAssemblerOptions); + settings.setValue("assemblerpath", backupAssemblerPath); + settings.setValue("linkingoptions", backupLinkerOptions); + settings.setValue("objectfilename", backupObjectFileName); + settings.setValue("disablelinking", backupDisableLinking); + settings.setValue("currentdir", backupCurrentDir); + settings.setValue("starttext", backupStartText); + settings.setValue("linkerpath", backupLinkerPath); + settingsWindow->close(); +} + +void MainWindow::recreateHighlighter() { + if (highlighter) { + delete highlighter; + highlighter = new Highlighter(assembler); + } + if (tabs && tabs->count() > 0) { + Tab* currentTab = (Tab*) tabs->currentWidget(); + highlighter->setDocument(currentTab->getCodeDocument()); + } + delete settingsHighlighter; + settingsHighlighter = new Highlighter(assembler); + settingsHighlighter->setDocument(settingsStartTextEditor->document()); +} + +void MainWindow::saveSettings() { + settings.setValue("startwindow", settingsUi.startWindow->currentIndex()); + settings.setValue("language", settingsUi.language->currentIndex()); + startText = settingsStartTextEditor->toPlainText(); + settings.setValue("allregisters", settingsUi.registersYesRadioButton->isChecked()); + settings.setValue("insertdebugstring", + settingsUi.insertDebugStringCheckBox->isChecked()); + + //! Change fonts + settings.setValue("fontfamily", settingsUi.fontComboBox->currentFont().family()); + settings.setValue("fontsize", settingsUi.fontSizeSpinBox->value()); + for (int i = 0; i < tabs->count(); i++) { + Tab* tab = (Tab*) tabs->widget(i); + tab->setFonts(); + } + QFont compilerOutFont; + compilerOutFont.setPointSize(settings.value("fontsize", 12).toInt()); + compilerOut->setFont(compilerOutFont); + + settings.setValue("assemblyoptions", settingsUi.assemblyOptionsEdit->text()); + settings.setValue("linkingoptions", settingsUi.linkingOptionsEdit->text()); + settings.setValue("objectfilename", settingsUi.objectFileNameEdit->text()); + settings.setValue("disablelinking", settingsUi.disableLinkingCheckbox->isChecked()); + settings.setValue("currentdir", settingsUi.runInCurrentDirectoryCheckbox->isChecked()); + settings.setValue("assemblerpath", settingsUi.assemblerPathEdit->text()); + settings.setValue("linkerpath", settingsUi.linkerPathEdit->text()); + settings.setValue("starttext", settingsStartTextEditor->document()->toPlainText()); + + backupSettings(); +} + +void MainWindow::pickColor(QWidget* button, bool init) { + QPushButton* colorButton = (QPushButton*) button; + QString name = colorButton->objectName(); + name.remove("Button"); + name.replace("_2", "bg"); + name = name.toLower(); + if (!init) { + QColor color = + QColorDialog::getColor(settings.value(name, colorsMap[name]).value()); + if (color.isValid()) { + settings.setValue(name, color); + if (name == "backgroundcolor") { + int r, g, b; + color.getRgb(&r, &g, &b); + for (int i = 9; i < 18; i++) { + QString buttonName = colorButtons[i]->objectName(); + buttonName.remove("Button"); + buttonName.replace("_2", "bg"); + buttonName = buttonName.toLower(); + settings.setValue(buttonName, color); + colorButtons[i]->setStyleSheet( + QString("background-color: rgb(%1, %2, %3)").arg(r).arg(g).arg(b)); } - result = dir.rmdir(dirName); - } - return result; -} - -MainWindow::~MainWindow() -{ - //! Delete all temporary files - removeDirRecuresively(Common::pathInTemp(QString())); + } + recreateHighlighter(); + } + } + int r, g, b; + QColor color = settings.value(name, colorsMap[name]).value(); + color.getRgb(&r, &g, &b); + colorButton->setStyleSheet( + QString("background-color: rgb(%1, %2, %3)").arg(r).arg(g).arg(b)); +} + +void MainWindow::changeHighlightingFont(QWidget* box, bool init) { + QCheckBox* checkBox = (QCheckBox*) box; + QString name = checkBox->objectName(); + name.remove("CheckBox"); + name = name.toLower(); + if (init) { + bool defaultState = (name == "keywordsbold") ? true : false; + checkBox->setChecked(settings.value(name, defaultState).toBool()); + } else { + settings.setValue(name, checkBox->isChecked()); + recreateHighlighter(); + } +} + +void MainWindow::changeHighlightingLineMode(bool mode) { + settings.setValue("currentlinemode", mode); +} + +void MainWindow::exitSettings() { + saveSettings(); + settingsWindow->close(); +} + +void MainWindow::resetAllSettings() { + //! Ask before execution + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Warning); + msgBox.addButton(tr("Yes"), QMessageBox::YesRole); + QPushButton* cancelButton = msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole); + msgBox.setWindowTitle(tr("Warning!")); + msgBox.setText(tr( + "All settings will be deleted and all unsaved data will be lost. Are you sure?")); + msgBox.exec(); + if (msgBox.clickedButton() == cancelButton) { + return; + } + + settings.remove("MainWindow/size"); + settings.remove("MainWindow/pos"); + + int prevTabsCount = settings.value("tabscount", 0).toInt(); + //! Remove previous + for (int i = 0; i < prevTabsCount; i++) + settings.remove(QString("Tabs/") + QString::number(i)); + + settings.clear(); + + closeFromCloseAll = true; + close(); +} + +void MainWindow::changeActionsState(int widgetIndex) { + //! Get started window + if (widgetIndex == 0) { + closeAction->setEnabled(false); + saveAction->setEnabled(false); + saveAsAction->setEnabled(false); + saveExeAction->setEnabled(false); + findAction->setEnabled(false); + commentAction->setEnabled(false); + uncommentAction->setEnabled(false); + undoAction->setEnabled(false); + redoAction->setEnabled(false); + cutAction->setEnabled(false); + copyAction->setEnabled(false); + pasteAction->setEnabled(false); + deleteAction->setEnabled(false); + selectAllAction->setEnabled(false); + putTabAction->setEnabled(false); + deleteTabAction->setEnabled(false); + buildAction->setEnabled(false); + runAction->setEnabled(false); + runExeAction->setEnabled(false); + stopAction->setEnabled(false); + debugAction->setEnabled(false); + debugNextAction->setEnabled(false); + debugNextNiAction->setEnabled(false); + debugShowRegistersAction->setEnabled(false); + debugToggleBreakpointAction->setEnabled(false); + debugShowMemoryAction->setEnabled(false); + } else { + closeAction->setEnabled(true); + saveAction->setEnabled(true); + saveAsAction->setEnabled(true); + saveExeAction->setEnabled(true); + findAction->setEnabled(true); + pasteAction->setEnabled(true); + selectAllAction->setEnabled(true); + putTabAction->setEnabled(true); + deleteTabAction->setEnabled(true); + buildAction->setEnabled(true); + runAction->setEnabled(true); + runExeAction->setEnabled(true); + debugAction->setEnabled(true); + debugToggleBreakpointAction->setEnabled(true); + } +} + +void MainWindow::openHelp() { + help = new QTextBrowser; + help->setAttribute(Qt::WA_DeleteOnClose); + QFile helpFile; + //! language 0=Russian + if (settings.value("language", 0).toInt() == 0) { + helpFile.setFileName(":help/help.html"); + } else { + //! English and other languages + helpFile.setFileName(":help/helpENG.html"); + } + + helpFile.open(QFile::ReadOnly); + QTextStream helpText(&helpFile); + helpText.setCodec("utf-8"); + help->setHtml(helpText.readAll()); + helpFile.close(); + help->setWindowState(Qt::WindowMaximized); + help->setOpenExternalLinks(true); + help->setWindowTitle(tr("Help")); + help->setWindowIcon(QIcon(":images/mainIcon.png")); + help->show(); +} + +void MainWindow::openAbout() { + QMessageBox::about( + this, tr("About SASM"), + tr("SASM (SimpleASM) ") + SASM_VERSION + " - " + + tr("simple Open Source IDE for NASM, MASM, GAS and FASM assembler languages.") + + '\n' + tr("Licensed under the GNU GPL v3.0") + '\n' + tr("Based on the Qt.") + + '\n' + tr("Copyright (c) 2013 Dmitriy Manushin") + '\n' + + tr("Development and idea - Dmitriy Manushin") + '\n' + + tr("Icon and advices - Alick Gaybullaev") + '\n' + '\n' + + tr("Wishes and error messages are sent to the e-mail: Dman1095@gmail.com") + + '\n' + tr("More information on the site: http://dman95.github.io/SASM/") + + '\n' + '\n' + tr("Donate:") + '\n' + tr("PayPal - Dman1095@gmail.com") + '\n' + + tr("WMZ - Z282016332582") + '\n' + tr("WMR - R331674303467")); +} + +void MainWindow::onMessageReceived(const QString& message) { + raise(); + activateWindow(); + if (message.startsWith("run")) { + openFile(message.mid(3)); + } +} + +void MainWindow::dragEnterEvent(QDragEnterEvent* event) { + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } +} + +void MainWindow::dropEvent(QDropEvent* event) { + foreach (const QUrl& url, event->mimeData()->urls()) + openFile(url.toLocalFile()); +} + +bool MainWindow::removeDirRecuresively(const QString& dirName) { + bool result = true; + QDir dir(dirName); + + if (dir.exists(dirName)) { + Q_FOREACH (QFileInfo info, + dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | + QDir::AllDirs | QDir::Files, + QDir::DirsFirst)) { + if (info.isDir()) { + result = removeDirRecuresively(info.absoluteFilePath()); + } else { + result = QFile::remove(info.absoluteFilePath()); + } + + if (!result) { + return result; + } + } + result = dir.rmdir(dirName); + } + return result; +} + +MainWindow::~MainWindow() { + //! Delete all temporary files + removeDirRecuresively(Common::pathInTemp(QString())); } diff --git a/mainwindow.h b/mainwindow.h index 28206fcc..234c043f 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -41,39 +41,40 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H +#include +#include +#include #include -#include -#include -#include +#include #include #include -#include -#include +#include +#include #include -#include #include -#include #include +#include +#include +#include +#include #include -#include -#include -#include -#include "tab.h" -#include "highlighter.h" + +#include "assembler.h" +#include "common.h" +#include "debuganycommandwidget.h" #include "debugger.h" +#include "debugtablewidget.h" +#include "fasm.h" #include "finddialog.h" -#include "ruqtextedit.h" +#include "gas.h" #include "getstartedwidget.h" -#include "ui_settings.h" -#include "debugtablewidget.h" -#include "debuganycommandwidget.h" -#include "assembler.h" +#include "highlighter.h" +#include "masm.h" #include "nasm.h" -#include "gas.h" -#include "common.h" -#include "fasm.h" +#include "ruqtextedit.h" #include "signallocker.h" -#include "masm.h" +#include "tab.h" +#include "ui_settings.h" #define SASM_VERSION "3.12.1" @@ -82,230 +83,240 @@ * Defines the main user interface. */ -/*! \brief The MainWindow class defines the actions and behavior of the main user interface. +/*! \brief The MainWindow class defines the actions and behavior of the main user + * interface. * */ -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(const QStringList & args, QWidget *parent = 0); - ~MainWindow(); +class MainWindow : public QMainWindow { + Q_OBJECT + + public: + MainWindow(const QStringList& args, QWidget* parent = 0); + ~MainWindow(); + + void initUi(); + void createMenus(); + void createActions(); + void createButtons(); + void createToolBars(); + void writeSettings(); + void setupEditor(int i); + bool okToContinue(int index = -1); + void setTabPath(const QString& filePath, int index = -1); + bool removeDirRecuresively(const QString& dirName); - void initUi(); - void createMenus(); - void createActions(); - void createButtons(); - void createToolBars(); - void writeSettings(); - void setupEditor(int i); - bool okToContinue(int index = -1); - void setTabPath(const QString &filePath, int index = -1); - bool removeDirRecuresively(const QString &dirName); + private: + // ui + GetStartedWidget* getStartedWidget; + QStackedWidget* mainWidget; + QSplitter* splitter; + QVBoxLayout* workLayout; + QWidget* workWidget; + RuQTextEdit* compilerOut; + QTabWidget* tabs; -private: - //ui - GetStartedWidget *getStartedWidget; - QStackedWidget *mainWidget; - QSplitter *splitter; - QVBoxLayout *workLayout; - QWidget *workWidget; - RuQTextEdit *compilerOut; - QTabWidget *tabs; + //! Menus and Actions + QMenu* fileMenu; + QMenu* editMenu; + QMenu* debugMenu; + QMenu* buildMenu; + QMenu* settingsMenu; + QMenu* helpMenu; + QAction* newAction; + QAction* openAction; + QAction* closeAction; + QAction* saveAction; + QAction* saveAsAction; + QAction* saveExeAction; + QAction* exitAction; + QAction* findAction; + QAction* commentAction; + QAction* uncommentAction; + QAction* undoAction; + QAction* redoAction; + QAction* cutAction; + QAction* copyAction; + QAction* pasteAction; + QAction* deleteAction; + QAction* selectAllAction; + QAction* putTabAction; + QAction* deleteTabAction; + QAction* buildAction; + QAction* runAction; + QAction* runExeAction; + QAction* stopAction; + QAction* debugAction; + QAction* debugNextAction; + QAction* debugNextNiAction; + QAction* debugToggleBreakpointAction; + QAction* debugShowRegistersAction; + QAction* debugShowMemoryAction; + QAction* settingsAction; + QAction* helpAction; + QAction* aboutAction; - //! Menus and Actions - QMenu *fileMenu; - QMenu *editMenu; - QMenu *debugMenu; - QMenu *buildMenu; - QMenu *settingsMenu; - QMenu *helpMenu; - QAction *newAction; - QAction *openAction; - QAction *closeAction; - QAction *saveAction; - QAction *saveAsAction; - QAction *saveExeAction; - QAction *exitAction; - QAction *findAction; - QAction *commentAction; - QAction *uncommentAction; - QAction *undoAction; - QAction *redoAction; - QAction *cutAction; - QAction *copyAction; - QAction *pasteAction; - QAction *deleteAction; - QAction *selectAllAction; - QAction *putTabAction; - QAction *deleteTabAction; - QAction *buildAction; - QAction *runAction; - QAction *runExeAction; - QAction *stopAction; - QAction *debugAction; - QAction *debugNextAction; - QAction *debugNextNiAction; - QAction *debugToggleBreakpointAction; - QAction *debugShowRegistersAction; - QAction *debugShowMemoryAction; - QAction *settingsAction; - QAction *helpAction; - QAction *aboutAction; + //! Toolbars + QToolBar* fileToolBar; + QToolBar* editToolBar; + QToolBar* buildToolBar; + QToolBar* debugToolBar; - //! Toolbars - QToolBar *fileToolBar; - QToolBar *editToolBar; - QToolBar *buildToolBar; - QToolBar *debugToolBar; + //! Builder and debugger and all that concern to them + QProcess* runProcess; + CodeEditor* prevCodeEditor; + QTimer* timer; + QTime programExecutionTime; + Debugger* debugger; + bool programIsBuilded; + QPointer registersWindow; + QDockWidget* registersDock; + QPointer memoryWindow; + QDockWidget* memoryDock; + QList watches; + DebugAnyCommandWidget* debugAnyCommandWidget; + bool programStopped; + int outputIndex; + Assembler* assembler; + bool debuggerWasStarted; + QString debugKey; - //! Builder and debugger and all that concern to them - QProcess *runProcess; - CodeEditor *prevCodeEditor; - QTimer *timer; - QTime programExecutionTime; - Debugger *debugger; - bool programIsBuilded; - QPointer registersWindow; - QDockWidget *registersDock; - QPointer memoryWindow; - QDockWidget *memoryDock; - QList watches; - DebugAnyCommandWidget *debugAnyCommandWidget; - bool programStopped; - int outputIndex; - Assembler *assembler; - bool debuggerWasStarted; - QString debugKey; + //! Highlighters + Highlighter* highlighter; + Highlighter* settingsHighlighter; - //! Highlighters - Highlighter *highlighter; - Highlighter *settingsHighlighter; + //! Search + QPointer findDialog; + Qt::CaseSensitivity prevCs; - //! Search - QPointer findDialog; - Qt::CaseSensitivity prevCs; + //! Settings and Help + QPointer settingsWindow; + Ui::SettingsWindow settingsUi; + QString startText; + CodeEditor* settingsStartTextEditor; + //! save and open + QString saveOpenDirectory; + QPointer help; + QSignalMapper* colorSignalMapper; + QSignalMapper* fontsSignalMapper; + QList colorButtons; + //! According to colorButtons + QList defaultColors; + QMap colorsMap; + QList fontCheckBoxes; + QSettings settings; + QString backupAssembler; + QString backupMode; + QString backupAssemblerOptions; + QString backupLinkerOptions; + QString backupObjectFileName; + bool backupDisableLinking; + bool backupCurrentDir; + QString backupAssemblerPath; + QString backupStartText; + QString backupLinkerPath; - //! Settings and Help - QPointer settingsWindow; - Ui::SettingsWindow settingsUi; - QString startText; - CodeEditor *settingsStartTextEditor; - //!save and open - QString saveOpenDirectory; - QPointer help; - QSignalMapper *colorSignalMapper; - QSignalMapper *fontsSignalMapper; - QList colorButtons; - //! According to colorButtons - QList defaultColors; - QMap colorsMap; - QList fontCheckBoxes; - QSettings settings; - QString backupAssembler; - QString backupMode; - QString backupAssemblerOptions; - QString backupLinkerOptions; - QString backupObjectFileName; - bool backupDisableLinking; - bool backupCurrentDir; - QString backupAssemblerPath; - QString backupStartText; - QString backupLinkerPath; + // Files + QString replaceSOURCE; // $SOURCE$ + QString replaceLSTOUTPUT; // $LSTOUTPUT$ + QString replacePROGRAM; // $PROGRAM$ + QString replacePROGRAM_OBJ; // $PROGRAM.OBJ$ + QString replaceWORKSPACE_ROOT; // $WORKSPACE_ROOT$ + QString outputCOMPILER_ERROR; + QString outputLINKER_ERROR; - //! About close - bool closeFromCloseAll; - void closeEvent(QCloseEvent *e); + //! About close + bool closeFromCloseAll; + void closeEvent(QCloseEvent* e); -public slots: - //! Actions and Menus - void newFile(); - void openFile(); - void closeFile(); - bool saveFile(int index = -1, bool openSaveAs = true); - bool saveAsFile(int index = -1); - void saveExe(); - bool closeApp(); - void refreshEditMenu(); - void changeCurrentSavedState(bool changed); - void openFile(QString path); + public slots: + //! Actions and Menus + void newFile(); + void openFile(); + void closeFile(); + bool saveFile(int index = -1, bool openSaveAs = true); + bool saveAsFile(int index = -1); + void saveExe(); + bool closeApp(); + void refreshEditMenu(); + void changeCurrentSavedState(bool changed); + void openFile(QString path); - //! Build - void buildProgram(bool debugMode = false); - void runProgram(); - void runExeProgram(); - void stopProgram(); - void testStopOfProgram(); - void setProgramBuildedFlagToFalse(); - void changeCurrentTab(int index); - void printLog(const QString & message, const QColor &color); - void printLogWithTime(const QString & message, const QColor &color); - void startCountProgramTime(); + //! Build + void buildProgram(bool debugMode = false); + void runProgram(); + void runExeProgram(); + void stopProgram(); + void testStopOfProgram(); + void setProgramBuildedFlagToFalse(); + void changeCurrentTab(int index); + void printLog(const QString& message, const QColor& color); + void printLogWithTime(const QString& message, const QColor& color); + void startCountProgramTime(); - //! Debug - void debug(); - void enableDebugActions(); - void disableDebugActions(bool start = false); - void debugNext(); - void debugNextNi(); - void debugExit(); - void debugToggleBreakpoint(); - void debugShowRegisters(); - void debugShowMemory(); - void debugRunCommand(QString command, bool print); - void saveWatches(DebugTableWidget *table); - void setShowRegistersToUnchecked(); - void setShowMemoryToUnchecked(); - void setShowMemoryToChecked(const RuQPlainTextEdit::Watch &variable); - void showAnyCommandWidget(); - void closeAnyCommandWidget(); - void printOutput(QString msg, int index = -1); - void getOutput(); - void changeDebugActionToStart(); + //! Debug + void debug(); + void enableDebugActions(); + void disableDebugActions(bool start = false); + void debugNext(); + void debugNextNi(); + void debugExit(); + void debugToggleBreakpoint(); + void debugShowRegisters(); + void debugShowMemory(); + void debugRunCommand(QString command, bool print); + void saveWatches(DebugTableWidget* table); + void setShowRegistersToUnchecked(); + void setShowMemoryToUnchecked(); + void setShowMemoryToChecked(const RuQPlainTextEdit::Watch& variable); + void showAnyCommandWidget(); + void closeAnyCommandWidget(); + void printOutput(QString msg, int index = -1); + void getOutput(); + void changeDebugActionToStart(); - //! Search - void find(); - void findNext(const QString &pattern, Qt::CaseSensitivity cs, bool all, bool replace, - const QString &replaceText = 0); + //! Search + void find(); + void findNext(const QString& pattern, Qt::CaseSensitivity cs, bool all, bool replace, + const QString& replaceText = 0); - //! Settings - void restorePrevSession(bool notNotify = false); - void openSettings(); - void changeMode(bool x86); - void changeAssembler(); - void changeStartText(); - void saveSettings(); - void exitSettings(); - void changeActionsState(int widgetIndex); - void resetAllSettings(); - void pickColor(QWidget *colorButton, bool init = false); - void changeHighlightingFont(QWidget *box, bool init = false); - void changeHighlightingLineMode(bool mode); - void recreateHighlighter(); - void recreateAssembler(bool start = false); - void initAssemblerSettings(bool firstOpening); - void backupSettings(); - void restoreSettingsAndExit(); - void printMasmInfo(); - void enableOrDisableLinkingEdit(int disableLinkingCheckboxState); + //! Settings + void restorePrevSession(bool notNotify = false); + void openSettings(); + void changeMode(bool x86); + void changeAssembler(); + void changeStartText(); + void saveSettings(); + void exitSettings(); + void changeActionsState(int widgetIndex); + void resetAllSettings(); + void pickColor(QWidget* colorButton, bool init = false); + void changeHighlightingFont(QWidget* box, bool init = false); + void changeHighlightingLineMode(bool mode); + void recreateHighlighter(); + void recreateAssembler(bool start = false); + void initAssemblerSettings(bool firstOpening); + void backupSettings(); + void restoreSettingsAndExit(); + void printMasmInfo(); + void enableOrDisableLinkingEdit(int disableLinkingCheckboxState); + void enableOrDisableObjectFilenameLabel(int disableCurrentDirCheckboxState); - //! Closing - bool deleteTab(int index, bool saveFileName = false); - void closeAllChildWindows(); + //! Closing + bool deleteTab(int index, bool saveFileName = false); + void closeAllChildWindows(); - //! Help and About - void openHelp(); - void openAbout(); + //! Help and About + void openHelp(); + void openAbout(); - //! Single Application message - void onMessageReceived(const QString &message); + //! Single Application message + void onMessageReceived(const QString& message); -protected: - void dragEnterEvent(QDragEnterEvent *event); + protected: + void dragEnterEvent(QDragEnterEvent* event); - void dropEvent(QDropEvent *event); + void dropEvent(QDropEvent* event); }; -#endif // MAINWINDOW_H +#endif // MAINWINDOW_H diff --git a/masm.cpp b/masm.cpp index 15ccc982..b7f27e35 100644 --- a/masm.cpp +++ b/masm.cpp @@ -45,500 +45,870 @@ * Implements the MASM Assembler */ - //! Windows only! -MASM::MASM(bool x86, QObject *parent) : - Assembler(x86, parent) -{ - #ifndef Q_OS_WIN32 - QMessageBox::critical(0, tr("Error!"), tr("MASM is available on Windows only.")); - #else - if (!x86) { - QMessageBox::critical(0, tr("Error!"), tr("Only 32-bit version of MASM is available.")); - } - #endif +MASM::MASM(bool x86, QObject* parent) : Assembler(x86, parent) { +#ifndef Q_OS_WIN32 + QMessageBox::critical(0, tr("Error!"), tr("MASM is available on Windows only.")); +#else + if (!x86) { + QMessageBox::critical(0, tr("Error!"), + tr("Only 32-bit version of MASM is available.")); + } +#endif } -QString MASM::getAssemblerPath() -{ - return "C:/masm32/bin/ml.exe"; -} +QString MASM::getAssemblerPath() { return "C:/masm32/bin/ml.exe"; } -QString MASM::getLinkerPath() -{ - return "C:/masm32/bin/link.exe"; -} +QString MASM::getLinkerPath() { return "C:/masm32/bin/link.exe"; } -quint64 MASM::getMainOffset(QFile &lst, QString entryLabel) -{ - QTextStream lstStream(&lst); - QRegExp mainLabel(" [0-9a-fA-F]{8,16}.*" + entryLabel + ":.*"); - QRegExp empty1("\t\t\t C.*"); - QRegExp empty2(" *;.*"); - while (!lstStream.atEnd()) { - QString line = lstStream.readLine(); - if (empty1.exactMatch(line)) - continue; - if (empty2.exactMatch(line)) - continue; - if (!mainLabel.exactMatch(line)) - continue; - QByteArray lineArr = line.toLocal8Bit(); - const char *s = lineArr.constData(); - quint64 a; - if (sscanf(s, "%llx", &a) == 1) { - return a; - } +quint64 MASM::getMainOffset(QFile& lst, QString entryLabel) { + QTextStream lstStream(&lst); + QRegExp mainLabel(" [0-9a-fA-F]{8,16}.*" + entryLabel + ":.*"); + QRegExp empty1("\t\t\t C.*"); + QRegExp empty2(" *;.*"); + while (!lstStream.atEnd()) { + QString line = lstStream.readLine(); + if (empty1.exactMatch(line)) continue; + if (empty2.exactMatch(line)) continue; + if (!mainLabel.exactMatch(line)) continue; + QByteArray lineArr = line.toLocal8Bit(); + const char* s = lineArr.constData(); + quint64 a; + if (sscanf(s, "%llx", &a) == 1) { + return a; } - return -1; + } + return -1; } -void MASM::parseLstFile(QFile &lst, QVector &lines, quint64 offset) -{ - QTextStream lstStream(&lst); - QList > instrList; - bool inTextSection = false; - QRegExp sectionTextRegExp("\\.code"); - sectionTextRegExp.setCaseSensitivity(Qt::CaseInsensitive); - QRegExp sectionDataRegExp("\\.(data|fardata|const)"); - sectionDataRegExp.setCaseSensitivity(Qt::CaseInsensitive); - QRegExp empty1("\t\t\t C.*"); - QRegExp empty2(" *;.*"); - QRegExp stringWithCode(" [0-9a-fA-F]{8,16} +[0-9a-fA-F]{1,16}.*"); - QRegExp stringWithAddress(" [0-9a-fA-F]{8,16}.*"); - QRegExp macroBegin("[\t0-9a-fA-FRE ]+1\t.*"); - QRegExp macro("[\t0-9a-fA-FRE ]+ +[1-9]\t.*"); - QString mayBeMacro, line, macroInstruction; - bool inMacro = false; - while (!lstStream.atEnd()) { - line = lstStream.readLine(); - if (empty1.exactMatch(line)) - continue; - if (empty2.exactMatch(line)) - continue; - if (line.indexOf(sectionTextRegExp) != -1) { - inTextSection = true; - } else if (line.indexOf(sectionDataRegExp) != -1) { - inTextSection = false; - } - if (inTextSection) { - QByteArray lineArr = line.toLocal8Bit(); - const char *s = lineArr.constData(); - quint64 a; - - //! Check if invoke - if (line.contains("invoke", Qt::CaseInsensitive)) { - macroInstruction = line; - if (macro.exactMatch(macroInstruction)) - continue; - int k = 0; - while (k < macroInstruction.length() && macroInstruction[k].isSpace()) - k++; - macroInstruction.remove(0, k); - if (macroInstruction[0] == '=') - continue; - macroInstruction.remove(QRegExp("^[0-9a-fA-F]{8,16}[ \t]+")); //if label - while (!stringWithAddress.exactMatch(line) && !lstStream.atEnd()) - line = lstStream.readLine(); - lineArr = line.toLocal8Bit(); - s = lineArr.constData(); - if (sscanf(s, "%llx", &a) == 1) { - instrList.append(QPair(a + offset, macroInstruction)); - macroInstruction.clear(); - } - continue; - } - - //! Check if return - if (line.contains("return", Qt::CaseInsensitive)) { - macroInstruction = line; - if (macro.exactMatch(macroInstruction)) - continue; - int k = 0; - while (k < macroInstruction.length() && macroInstruction[k].isSpace()) - k++; - macroInstruction.remove(0, k); - macroInstruction.remove(QRegExp("^[0-9a-fA-F]{8,16}[ \t]+")); //if label - while (!stringWithAddress.exactMatch(line) && !lstStream.atEnd()) - line = lstStream.readLine(); - lineArr = line.toLocal8Bit(); - s = lineArr.constData(); - if (sscanf(s, "%llx", &a) == 1) { - instrList.append(QPair(a + offset, macroInstruction)); - macroInstruction.clear(); - } - continue; - } +void MASM::parseLstFile(QFile& lst, QString& programFilePath, + QVector& lines, quint64 offset) { + QTextStream lstStream(&lst); + QList > instrList; + bool inTextSection = false; + QRegExp sectionTextRegExp("\\.code"); + sectionTextRegExp.setCaseSensitivity(Qt::CaseInsensitive); + QRegExp sectionDataRegExp("\\.(data|fardata|const)"); + sectionDataRegExp.setCaseSensitivity(Qt::CaseInsensitive); + QRegExp empty1("\t\t\t C.*"); + QRegExp empty2(" *;.*"); + QRegExp stringWithCode(" [0-9a-fA-F]{8,16} +[0-9a-fA-F]{1,16}.*"); + QRegExp stringWithAddress(" [0-9a-fA-F]{8,16}.*"); + QRegExp macroBegin("[\t0-9a-fA-FRE ]+1\t.*"); + QRegExp macro("[\t0-9a-fA-FRE ]+ +[1-9]\t.*"); + QString mayBeMacro, line, macroInstruction; + bool inMacro = false; + while (!lstStream.atEnd()) { + line = lstStream.readLine(); + if (empty1.exactMatch(line)) continue; + if (empty2.exactMatch(line)) continue; + if (line.indexOf(sectionTextRegExp) != -1) { + inTextSection = true; + } else if (line.indexOf(sectionDataRegExp) != -1) { + inTextSection = false; + } + if (inTextSection) { + QByteArray lineArr = line.toLocal8Bit(); + const char* s = lineArr.constData(); + quint64 a; - //! Check if macro - if (line.startsWith("\t\t\t\t")) { - mayBeMacro = line; - int k = 0; - while (k < mayBeMacro.length() && mayBeMacro[k].isSpace()) - k++; - mayBeMacro.remove(0, k); - continue; - } - //! If previous may be macro - switch to finding macro start address mode - if (!mayBeMacro.isEmpty() && !inMacro) { - if (macroBegin.exactMatch(line)) { - inMacro = true; - } else { - mayBeMacro.clear(); - } - } - //! If in macro, find its start address - if (inMacro && stringWithCode.exactMatch(line) && sscanf(s, "%llx", &a) == 1) { + //! Check if invoke + if (line.contains("invoke", Qt::CaseInsensitive)) { + macroInstruction = line; + if (macro.exactMatch(macroInstruction)) continue; + int k = 0; + while (k < macroInstruction.length() && macroInstruction[k].isSpace()) k++; + macroInstruction.remove(0, k); + if (macroInstruction[0] == '=') continue; + macroInstruction.remove(QRegExp("^[0-9a-fA-F]{8,16}[ \t]+")); // if label + while (!stringWithAddress.exactMatch(line) && !lstStream.atEnd()) + line = lstStream.readLine(); + lineArr = line.toLocal8Bit(); + s = lineArr.constData(); + if (sscanf(s, "%llx", &a) == 1) { + instrList.append(QPair(a + offset, macroInstruction)); + macroInstruction.clear(); + } + continue; + } - instrList.append(QPair(a + offset, mayBeMacro)); - mayBeMacro.clear(); - inMacro = false; - } + //! Check if return + if (line.contains("return", Qt::CaseInsensitive)) { + macroInstruction = line; + if (macro.exactMatch(macroInstruction)) continue; + int k = 0; + while (k < macroInstruction.length() && macroInstruction[k].isSpace()) k++; + macroInstruction.remove(0, k); + macroInstruction.remove(QRegExp("^[0-9a-fA-F]{8,16}[ \t]+")); // if label + while (!stringWithAddress.exactMatch(line) && !lstStream.atEnd()) + line = lstStream.readLine(); + lineArr = line.toLocal8Bit(); + s = lineArr.constData(); + if (sscanf(s, "%llx", &a) == 1) { + instrList.append(QPair(a + offset, macroInstruction)); + macroInstruction.clear(); + } + continue; + } - //! Check if instruction - if (!stringWithCode.exactMatch(line) || macro.exactMatch(line) || sscanf(s, "%llx", &a) != 1) - continue; - int index = line.indexOf(QRegExp("[RE\t]\t")); - if (index == -1) - continue; - line = line.mid(index + 2); - int k = 0; - while (k < line.length() && line[k].isSpace()) - k++; - line.remove(0, k); - if (line[0] == '*') - continue; - instrList.append(QPair(a + offset, line)); + //! Check if macro + if (line.startsWith("\t\t\t\t")) { + mayBeMacro = line; + int k = 0; + while (k < mayBeMacro.length() && mayBeMacro[k].isSpace()) k++; + mayBeMacro.remove(0, k); + continue; + } + //! If previous may be macro - switch to finding macro start address mode + if (!mayBeMacro.isEmpty() && !inMacro) { + if (macroBegin.exactMatch(line)) { + inMacro = true; + } else { + mayBeMacro.clear(); } + } + //! If in macro, find its start address + if (inMacro && stringWithCode.exactMatch(line) && sscanf(s, "%llx", &a) == 1) { + instrList.append(QPair(a + offset, mayBeMacro)); + mayBeMacro.clear(); + inMacro = false; + } + + //! Check if instruction + if (!stringWithCode.exactMatch(line) || macro.exactMatch(line) || + sscanf(s, "%llx", &a) != 1) + continue; + int index = line.indexOf(QRegExp("[RE\t]\t")); + if (index == -1) continue; + line = line.mid(index + 2); + int k = 0; + while (k < line.length() && line[k].isSpace()) k++; + line.remove(0, k); + if (line[0] == '*') continue; + instrList.append(QPair(a + offset, line)); } - lst.close(); + } + lst.close(); - QFile programFile(Common::pathInTemp("program.asm")); - programFile.open(QFile::ReadOnly); - QTextStream programStream(&programFile); - QList > programList; - int numInCode = 0; - while (!programStream.atEnd()) { - QString line = programStream.readLine(); - numInCode++; - int k = 0; - while (k < line.length() && line[k].isSpace()) - k++; - line.remove(0, k); - programList.append(QPair(numInCode, line)); + QFile programFile(programFilePath); + programFile.open(QFile::ReadOnly); + QTextStream programStream(&programFile); + QList > programList; + int numInCode = 0; + while (!programStream.atEnd()) { + QString line = programStream.readLine(); + numInCode++; + int k = 0; + while (k < line.length() && line[k].isSpace()) k++; + line.remove(0, k); + programList.append(QPair(numInCode, line)); + } + //! Offset in instrList + int i = 0; + //! Offset in programList + int j = 0; + int lastSeenInProgramList = 0; + while (i < instrList.size()) { + if (programList[j].second == instrList[i].second) { + LineNum l; + l.numInCode = programList[j].first; + l.numInMem = instrList[i].first; + lines.append(l); + i++; + lastSeenInProgramList = j; } - //! Offset in instrList - int i = 0; - //! Offset in programList - int j = 0; - int lastSeenInProgramList = 0; - while (i < instrList.size()) { - if (programList[j].second == instrList[i].second) { - LineNum l; - l.numInCode = programList[j].first; - l.numInMem = instrList[i].first; - lines.append(l); - i++; - lastSeenInProgramList = j; - } - j++; - //! If true, skip line in instrList and back to first unwatched line in programList - if (j >= programList.size()) { - i++; - j = lastSeenInProgramList + 1; - } + j++; + //! If true, skip line in instrList and back to first unwatched line in programList + if (j >= programList.size()) { + i++; + j = lastSeenInProgramList + 1; } - programFile.close(); + } + programFile.close(); } -QString MASM::getStartText() -{ - return QString(".386\n.model flat, stdcall\noption casemap : none\n.code\nstart:\n") + - QString(" ;write your code here\n xor eax, eax\n ret\n end start\n"); +QString MASM::getStartText() { + return QString(".386\n.model flat, stdcall\noption casemap : none\n.code\nstart:\n") + + QString(" ;write your code here\n xor eax, eax\n ret\n end start\n"); } -void MASM::putDebugString(CodeEditor *) -{ -} +void MASM::putDebugString(CodeEditor*) {} -QString MASM::getAssemblerOptions() -{ - return "/nologo /Sn /Sa /c /coff /Fo$PROGRAM.OBJ$ /Fl$LSTOUTPUT$ $SOURCE$"; +QString MASM::getAssemblerOptions() { + return "/nologo /Sn /Sa /c /coff /Fo$PROGRAM.OBJ$ /Fl$LSTOUTPUT$ $SOURCE$"; } -QString MASM::getLinkerOptions() -{ - return "/SUBSYSTEM:CONSOLE /OPT:NOREF /NOLOGO /OUT:$PROGRAM$ $PROGRAM.OBJ$"; +QString MASM::getLinkerOptions() { + return "/SUBSYSTEM:CONSOLE /OPT:NOREF /NOLOGO /OUT:$PROGRAM$ $PROGRAM.OBJ$"; } -void MASM::fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression) -{ - typedef Assembler::HighlightingRule HighlightingRule; - QTextCharFormat &keywordFormat = *formats[0]; - QTextCharFormat ®isterFormat = *formats[1]; - QTextCharFormat &numberFormat = *formats[2]; - QTextCharFormat &memoryFormat = *formats[3]; - QTextCharFormat &labelFormat = *formats[4]; - QTextCharFormat &commentFormat = *formats[5]; - QTextCharFormat &systemFormat = *formats[6]; - //QTextCharFormat &iomacrosFormat = *formats[7]; - QTextCharFormat "ationFormat = *formats[8]; - QTextCharFormat &labelWithDotFormat = *formats[9]; +void MASM::fillHighligherRules(QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, + QRegExp& commentEndExpression) { + typedef Assembler::HighlightingRule HighlightingRule; + QTextCharFormat& keywordFormat = *formats[0]; + QTextCharFormat& registerFormat = *formats[1]; + QTextCharFormat& numberFormat = *formats[2]; + QTextCharFormat& memoryFormat = *formats[3]; + QTextCharFormat& labelFormat = *formats[4]; + QTextCharFormat& commentFormat = *formats[5]; + QTextCharFormat& systemFormat = *formats[6]; + // QTextCharFormat &iomacrosFormat = *formats[7]; + QTextCharFormat& quotationFormat = *formats[8]; + QTextCharFormat& labelWithDotFormat = *formats[9]; - //! Setting up regular expressions - HighlightingRule rule; - - //! Keywords - QStringList keywordPatterns; - keywordPatterns << "\\bAAA\\b" << "\\bAAD\\b" << "\\bAAM\\b" << "\\bAAS\\b" << - "\\bADC\\b" << "\\bADD\\b" << "\\bAND\\b" << "\\bCALL\\b" << - "\\bCBW\\b" << "\\bCLC\\b" << "\\bCLD\\b" << "\\bCLI\\b" << - "\\bCMC\\b" << "\\bCMP\\b" << "\\bCMPSB\\b" << "\\bCMPSW\\b" << - "\\bCWD\\b" << "\\bDAA\\b" << "\\bDAS\\b" << "\\bDEC\\b" << - "\\bDIV\\b" << "\\bESC\\b" << "\\bHLT\\b" << "\\bIDIV\\b" << - "\\bIMUL\\b" << "\\bIN\\b" << "\\bINC\\b" << "\\bINT\\b" << - "\\bINTO\\b" << "\\bIRET\\b" << "\\bJA\\b" << "\\bJAE\\b" << - "\\bJB\\b" << "\\bJBE\\b" << "\\bJC\\b" << "\\bJCXZ\\b" << - "\\bJE\\b" << "\\bJG\\b" << "\\bJGE\\b" << "\\bJL\\b" << - "\\bJLE\\b" << "\\bJNA\\b" << "\\bJNAE\\b" << "\\bJNB\\b" << - "\\bJNBE\\b" << "\\bJNC\\b" << "\\bJNE\\b" << "\\bJNG\\b" << - "\\bJNGE\\b" << "\\bJNL\\b" << "\\bJNLE\\b" << "\\bJNO\\b" << - "\\bJNP\\b" << "\\bJNS\\b" << "\\bJNZ\\b" << "\\bJO\\b" << - "\\bJP\\b" << "\\bJPE\\b" << "\\bJPO\\b" << "\\bJS\\b" << - "\\bJZ\\b" << "\\bJMP\\b" << "\\bLAHF\\b" << "\\bLDS\\b" << - "\\bLEA\\b" << "\\bLES\\b" << "\\bLOCK\\b" << "\\bLODSB\\b" << - "\\bLODSW\\b" << "\\bLOOP\\b" << "\\bLOOPE\\b" << "\\bLOOPNE\\b" << - "\\bLOOPNZ\\b" << "\\bLOOPZ\\b" << "\\bMOV\\b" << "\\bMOVSB\\b" << - "\\bMOVSW\\b" << "\\bMUL\\b" << "\\bNEG\\b" << "\\bNOP\\b" << - "\\bNOT\\b" << "\\bOR\\b" << "\\bOUT\\b" << "\\bPOP\\b" << - "\\bPOPF\\b" << "\\bPUSH\\b" << "\\bPUSHF\\b" << "\\bRCL\\b" << - "\\bRCR\\b" << "\\bREP\\b" << "\\bREPE\\b" << "\\bREPNE\\b" << - "\\bREPNZ\\b" << "\\bREPZ\\b" << "\\bRET\\b" << "\\bRETN\\b" << - "\\bRETF\\b" << "\\bROL\\b" << "\\bROR\\b" << "\\bSAHF\\b" << - "\\bSAL\\b" << "\\bSAR\\b" << "\\bSBB\\b" << "\\bSCASB\\b" << - "\\bSCASW\\b" << "\\bSHL\\b" << "\\bSHR\\b" << "\\bSTC\\b" << - "\\bSTD\\b" << "\\bSTI\\b" << "\\bSTOSB\\b" << "\\bSTOSW\\b" << - "\\bSUB\\b" << "\\bTEST\\b" << "\\bWAIT\\b" << "\\bXCHG\\b" << - "\\bXLAT\\b" << "\\bXOR\\b" << "\\bBOUND\\b" << "\\bENTER\\b" << - "\\bINS\\b" << "\\bLEAVE\\b" << "\\bOUTS\\b" << "\\bPOPA\\b" << - "\\bPUSHA\\b" << "\\bARPL\\b" << "\\bCLTS\\b" << "\\bLAR\\b" << - "\\bLGDT\\b" << "\\bLIDT\\b" << "\\bLLDT\\b" << "\\bLMSW\\b" << - "\\bLOADALL\\b" << "\\bLSL\\b" << "\\bLTR\\b" << "\\bSGDT\\b" << - "\\bSIDT\\b" << "\\bSLDT\\b" << "\\bSMSW\\b" << "\\bSTR\\b" << - "\\bVERR\\b" << "\\bVERW\\b" << "\\bBSF\\b" << "\\bBSR\\b" << - "\\bBT\\b" << "\\bBTC\\b" << "\\bBTR\\b" << "\\bBTS\\b" << - "\\bCDQ\\b" << "\\bCMPSD\\b" << "\\bCWDE\\b" << "\\bINSD\\b" << - "\\bIRET\\b" << "\\bIRETW\\b" << "\\bIRETD\\b" << "\\bJCXZ\\b" << - "\\bJECXZ\\b" << "\\bLFS\\b" << "\\bLGS\\b" << "\\bLSS\\b" << - "\\bLODSD\\b" << "\\bMOVSD\\b" << "\\bMOVSX\\b" << "\\bMOVZX\\b" << - "\\bOUTSD\\b" << "\\bPOPAD\\b" << "\\bPOPFD\\b" << "\\bPUSHAD\\b" << - "\\bPUSHFD\\b" << "\\bSCASD\\b" << "\\bSETA\\b" << "\\bSETAE\\b" << - "\\bSETB\\b" << "\\bSETBE\\b" << "\\bSETC\\b" << "\\bSETE\\b" << - "\\bSETG\\b" << "\\bSETGE\\b" << "\\bSETL\\b" << "\\bSETLE\\b" << - "\\bSETNA\\b" << "\\bSETNAE\\b" << "\\bSETNB\\b" << "\\bSETNBE\\b" << - "\\bSETNC\\b" << "\\bSETNE\\b" << "\\bSETNG\\b" << "\\bSETNGE\\b" << - "\\bSETNL\\b" << "\\bSETNLE\\b" << "\\bSETNO\\b" << "\\bSETNP\\b" << - "\\bSETNS\\b" << "\\bSETNZ\\b" << "\\bSETO\\b" << "\\bSETP\\b" << - "\\bSETPE\\b" << "\\bSETPO\\b" << "\\bSETS\\b" << "\\bSETZ\\b" << - "\\bSHLD\\b" << "\\bSHRD\\b" << "\\bSTOSD\\b" << - "\\bPOPAD\\b" << "\\bPOPFD\\b" << "\\bPUSHAD\\b" << "\\bPUSHFD\\b" << - "\\bSCASD\\b" << "\\bBSWAP\\b" << "\\bCMPXCHG\\b" << "\\bINVD\\b" << - "\\bINVLPG\\b" << "\\bWBINVD\\b" << "\\bXADD\\b" << "\\bCPUID\\b" << - "\\bCMPXCHG8B\\b" << "\\bRDMSR\\b" << "\\bRDTSC\\b" << "\\bWRMSR\\b" << - "\\bRSM\\b" << "\\bRDPMC\\b" << "\\bCMOVA\\b" << "\\bCMOVAE\\b" << - "\\bCMOVB\\b" << "\\bCMOVBE\\b" << "\\bCMOVC\\b" << "\\bCMOVE\\b" << - "\\bCMOVG\\b" << "\\bCMOVGE\\b" << "\\bCMOVL\\b" << "\\bCMOVLE\\b" << - "\\bCMOVNA\\b" << "\\bCMOVNAE\\b" << "\\bCMOVNB\\b" << "\\bCMOVNBE\\b" << - "\\bCMOVNC\\b" << "\\bCMOVNE\\b" << "\\bCMOVNG\\b" << "\\bCMOVNGE\\b" << - "\\bCMOVNL\\b" << "\\bCMOVNLE\\b" << "\\bCMOVNO\\b" << "\\bCMOVNP\\b" << - "\\bCMOVNS\\b" << "\\bCMOVNZ\\b" << "\\bCMOVO\\b" << "\\bCMOVP\\b" << - "\\bCMOVPE\\b" << "\\bCMOVPO\\b" << "\\bCMOVS\\b" << "\\bCMOVZ\\b" << - "\\bF2XM1\\b" << "\\bFABS\\b" << "\\bFADD\\b" << "\\bFADDP\\b" << - "\\bFBLD\\b" << "\\bFBSTP\\b" << "\\bFCHS\\b" << "\\bFCLEX\\b" << - "\\bFCOM\\b" << "\\bFCOMP\\b" << "\\bFCOMPP\\b" << "\\bFDECSTP\\b" << - "\\bFDISI\\b" << "\\bFDIV\\b" << "\\bFDIVP\\b" << "\\bFDIVR\\b" << - "\\bFDIVRP\\b" << "\\bFENI\\b" << "\\bFFREE\\b" << "\\bFIADD\\b" << - "\\bFICOM\\b" << "\\bFICOMP\\b" << "\\bFIDIV\\b" << "\\bFIDIVR\\b" << - "\\bFILD\\b" << "\\bFIMUL\\b" << "\\bFINCSTP\\b" << "\\bFINIT\\b" << - "\\bFIST\\b" << "\\bFISTP\\b" << "\\bFISUB\\b" << "\\bFISUBR\\b" << - "\\bFLD\\b" << "\\bFLD1\\b" << "\\bFLDCW\\b" << "\\bFLDENV\\b" << - "\\bFLDENVW\\b" << "\\bFLDL2E\\b" << "\\bFLDL2T\\b" << "\\bFLDLG2\\b" << - "\\bFLDLN2\\b" << "\\bFLDPI\\b" << "\\bFLDZ\\b" << "\\bFMUL\\b" << - "\\bFMULP\\b" << "\\bFNCLEX\\b" << "\\bFNDISI\\b" << "\\bFNENI\\b" << - "\\bFNINIT\\b" << "\\bFNOP\\b" << "\\bFNSAVE\\b" << "\\bFNSAVEW\\b" << - "\\bFNSTCW\\b" << "\\bFNSTENV\\b" << "\\bFNSTENVW\\b" << "\\bFNSTSW\\b" << - "\\bFPATAN\\b" << "\\bFPREM\\b" << "\\bFPTAN\\b" << "\\bFRNDINT\\b" << - "\\bFRSTOR\\b" << "\\bFRSTORW\\b" << "\\bFSAVE\\b" << "\\bFSAVEW\\b" << - "\\bFSCALE\\b" << "\\bFSQRT\\b" << "\\bFST\\b" << "\\bFSTCW\\b" << - "\\bFSTENV\\b" << "\\bFSTENVW\\b" << "\\bFSTP\\b" << "\\bFSTSW\\b" << - "\\bFSUB\\b" << "\\bFSUBP\\b" << "\\bFSUBR\\b" << "\\bFSUBRP\\b" << - "\\bFTST\\b" << "\\bFWAIT\\b" << "\\bFXAM\\b" << "\\bFXCH\\b" << - "\\bFXTRACT\\b" << "\\bFYL2X\\b" << "\\bFYL2XP1\\b" << "\\bFSETPM\\b" << - "\\bFCOS\\b" << "\\bFLDENVD\\b" << "\\bFSAVED\\b" << "\\bFSTENVD\\b" << - "\\bFPREM1\\b" << "\\bFRSTORD\\b" << "\\bFSIN\\b" << "\\bFSINCOS\\b" << - "\\bFSTENVD\\b" << "\\bFUCOM\\b" << "\\bFUCOMP\\b" << "\\bFUCOMPP\\b" << - "\\bFCMOVB\\b" << "\\bFCMOVBE\\b" << "\\bFCMOVE\\b" << "\\bFCMOVNB\\b" << - "\\bFCMOVNBE\\b" << "\\bFCMOVNE\\b" << "\\bFCMOVNU\\b" << "\\bFCMOVU\\b" << - "\\bFCOMI\\b" << "\\bFCOMIP\\b" << "\\bFUCOMI\\b" << "\\bFUCOMIP\\b" << - "\\bCDQE\\b" << "\\bCQO\\b" << "\\bMOVMSKPS\\b" << "\\bMOVMSKPD\\b" << - "\\bPOPCNT\\b" << "\\bLZCNT\\b" << "\\bCMPSQ\\b" << "\\bSCASQ\\b" << - "\\bMOVSQ\\b" << "\\bLODSQ\\b" << "\\bSTOSQ\\b" << "\\bJRCXZ\\b" << - "\\bIRETQ\\b" << "\\bPUSHFQ\\b" << "\\bPOPFQ\\b" << "\\bCMPXCHG16B\\b" << - "\\bJRCXZ\\b" << "\\bINSB\\b" << "\\bINSW\\b" << "\\bOUTSB\\b" << - "\\bOUTSW\\b" << "\\bLFENCE\\b" << "\\bSFENCE\\b" << "\\bMFENCE\\b" << - "\\bPREFETCH\\b" << "\\bPREFETCHL\\b" << "\\bPREFETCHW\\b" << "\\bCLFLUSH\\b" << - "\\bSYSENTER\\b" << "\\bSYSEXIT\\b" << "\\bSYSCALL\\b" << "\\bSYSRET\\b"; - foreach (const QString &pattern, keywordPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - rule.format = keywordFormat; - highlightingRules.append(rule); - } + //! Setting up regular expressions + HighlightingRule rule; - //! Memory - rule.format = memoryFormat; - QStringList memoryPatterns; - rule.pattern = QRegExp("\\["); + //! Keywords + QStringList keywordPatterns; + keywordPatterns << "\\bAAA\\b" + << "\\bAAD\\b" + << "\\bAAM\\b" + << "\\bAAS\\b" + << "\\bADC\\b" + << "\\bADD\\b" + << "\\bAND\\b" + << "\\bCALL\\b" + << "\\bCBW\\b" + << "\\bCLC\\b" + << "\\bCLD\\b" + << "\\bCLI\\b" + << "\\bCMC\\b" + << "\\bCMP\\b" + << "\\bCMPSB\\b" + << "\\bCMPSW\\b" + << "\\bCWD\\b" + << "\\bDAA\\b" + << "\\bDAS\\b" + << "\\bDEC\\b" + << "\\bDIV\\b" + << "\\bESC\\b" + << "\\bHLT\\b" + << "\\bIDIV\\b" + << "\\bIMUL\\b" + << "\\bIN\\b" + << "\\bINC\\b" + << "\\bINT\\b" + << "\\bINTO\\b" + << "\\bIRET\\b" + << "\\bJA\\b" + << "\\bJAE\\b" + << "\\bJB\\b" + << "\\bJBE\\b" + << "\\bJC\\b" + << "\\bJCXZ\\b" + << "\\bJE\\b" + << "\\bJG\\b" + << "\\bJGE\\b" + << "\\bJL\\b" + << "\\bJLE\\b" + << "\\bJNA\\b" + << "\\bJNAE\\b" + << "\\bJNB\\b" + << "\\bJNBE\\b" + << "\\bJNC\\b" + << "\\bJNE\\b" + << "\\bJNG\\b" + << "\\bJNGE\\b" + << "\\bJNL\\b" + << "\\bJNLE\\b" + << "\\bJNO\\b" + << "\\bJNP\\b" + << "\\bJNS\\b" + << "\\bJNZ\\b" + << "\\bJO\\b" + << "\\bJP\\b" + << "\\bJPE\\b" + << "\\bJPO\\b" + << "\\bJS\\b" + << "\\bJZ\\b" + << "\\bJMP\\b" + << "\\bLAHF\\b" + << "\\bLDS\\b" + << "\\bLEA\\b" + << "\\bLES\\b" + << "\\bLOCK\\b" + << "\\bLODSB\\b" + << "\\bLODSW\\b" + << "\\bLOOP\\b" + << "\\bLOOPE\\b" + << "\\bLOOPNE\\b" + << "\\bLOOPNZ\\b" + << "\\bLOOPZ\\b" + << "\\bMOV\\b" + << "\\bMOVSB\\b" + << "\\bMOVSW\\b" + << "\\bMUL\\b" + << "\\bNEG\\b" + << "\\bNOP\\b" + << "\\bNOT\\b" + << "\\bOR\\b" + << "\\bOUT\\b" + << "\\bPOP\\b" + << "\\bPOPF\\b" + << "\\bPUSH\\b" + << "\\bPUSHF\\b" + << "\\bRCL\\b" + << "\\bRCR\\b" + << "\\bREP\\b" + << "\\bREPE\\b" + << "\\bREPNE\\b" + << "\\bREPNZ\\b" + << "\\bREPZ\\b" + << "\\bRET\\b" + << "\\bRETN\\b" + << "\\bRETF\\b" + << "\\bROL\\b" + << "\\bROR\\b" + << "\\bSAHF\\b" + << "\\bSAL\\b" + << "\\bSAR\\b" + << "\\bSBB\\b" + << "\\bSCASB\\b" + << "\\bSCASW\\b" + << "\\bSHL\\b" + << "\\bSHR\\b" + << "\\bSTC\\b" + << "\\bSTD\\b" + << "\\bSTI\\b" + << "\\bSTOSB\\b" + << "\\bSTOSW\\b" + << "\\bSUB\\b" + << "\\bTEST\\b" + << "\\bWAIT\\b" + << "\\bXCHG\\b" + << "\\bXLAT\\b" + << "\\bXOR\\b" + << "\\bBOUND\\b" + << "\\bENTER\\b" + << "\\bINS\\b" + << "\\bLEAVE\\b" + << "\\bOUTS\\b" + << "\\bPOPA\\b" + << "\\bPUSHA\\b" + << "\\bARPL\\b" + << "\\bCLTS\\b" + << "\\bLAR\\b" + << "\\bLGDT\\b" + << "\\bLIDT\\b" + << "\\bLLDT\\b" + << "\\bLMSW\\b" + << "\\bLOADALL\\b" + << "\\bLSL\\b" + << "\\bLTR\\b" + << "\\bSGDT\\b" + << "\\bSIDT\\b" + << "\\bSLDT\\b" + << "\\bSMSW\\b" + << "\\bSTR\\b" + << "\\bVERR\\b" + << "\\bVERW\\b" + << "\\bBSF\\b" + << "\\bBSR\\b" + << "\\bBT\\b" + << "\\bBTC\\b" + << "\\bBTR\\b" + << "\\bBTS\\b" + << "\\bCDQ\\b" + << "\\bCMPSD\\b" + << "\\bCWDE\\b" + << "\\bINSD\\b" + << "\\bIRET\\b" + << "\\bIRETW\\b" + << "\\bIRETD\\b" + << "\\bJCXZ\\b" + << "\\bJECXZ\\b" + << "\\bLFS\\b" + << "\\bLGS\\b" + << "\\bLSS\\b" + << "\\bLODSD\\b" + << "\\bMOVSD\\b" + << "\\bMOVSX\\b" + << "\\bMOVZX\\b" + << "\\bOUTSD\\b" + << "\\bPOPAD\\b" + << "\\bPOPFD\\b" + << "\\bPUSHAD\\b" + << "\\bPUSHFD\\b" + << "\\bSCASD\\b" + << "\\bSETA\\b" + << "\\bSETAE\\b" + << "\\bSETB\\b" + << "\\bSETBE\\b" + << "\\bSETC\\b" + << "\\bSETE\\b" + << "\\bSETG\\b" + << "\\bSETGE\\b" + << "\\bSETL\\b" + << "\\bSETLE\\b" + << "\\bSETNA\\b" + << "\\bSETNAE\\b" + << "\\bSETNB\\b" + << "\\bSETNBE\\b" + << "\\bSETNC\\b" + << "\\bSETNE\\b" + << "\\bSETNG\\b" + << "\\bSETNGE\\b" + << "\\bSETNL\\b" + << "\\bSETNLE\\b" + << "\\bSETNO\\b" + << "\\bSETNP\\b" + << "\\bSETNS\\b" + << "\\bSETNZ\\b" + << "\\bSETO\\b" + << "\\bSETP\\b" + << "\\bSETPE\\b" + << "\\bSETPO\\b" + << "\\bSETS\\b" + << "\\bSETZ\\b" + << "\\bSHLD\\b" + << "\\bSHRD\\b" + << "\\bSTOSD\\b" + << "\\bPOPAD\\b" + << "\\bPOPFD\\b" + << "\\bPUSHAD\\b" + << "\\bPUSHFD\\b" + << "\\bSCASD\\b" + << "\\bBSWAP\\b" + << "\\bCMPXCHG\\b" + << "\\bINVD\\b" + << "\\bINVLPG\\b" + << "\\bWBINVD\\b" + << "\\bXADD\\b" + << "\\bCPUID\\b" + << "\\bCMPXCHG8B\\b" + << "\\bRDMSR\\b" + << "\\bRDTSC\\b" + << "\\bWRMSR\\b" + << "\\bRSM\\b" + << "\\bRDPMC\\b" + << "\\bCMOVA\\b" + << "\\bCMOVAE\\b" + << "\\bCMOVB\\b" + << "\\bCMOVBE\\b" + << "\\bCMOVC\\b" + << "\\bCMOVE\\b" + << "\\bCMOVG\\b" + << "\\bCMOVGE\\b" + << "\\bCMOVL\\b" + << "\\bCMOVLE\\b" + << "\\bCMOVNA\\b" + << "\\bCMOVNAE\\b" + << "\\bCMOVNB\\b" + << "\\bCMOVNBE\\b" + << "\\bCMOVNC\\b" + << "\\bCMOVNE\\b" + << "\\bCMOVNG\\b" + << "\\bCMOVNGE\\b" + << "\\bCMOVNL\\b" + << "\\bCMOVNLE\\b" + << "\\bCMOVNO\\b" + << "\\bCMOVNP\\b" + << "\\bCMOVNS\\b" + << "\\bCMOVNZ\\b" + << "\\bCMOVO\\b" + << "\\bCMOVP\\b" + << "\\bCMOVPE\\b" + << "\\bCMOVPO\\b" + << "\\bCMOVS\\b" + << "\\bCMOVZ\\b" + << "\\bF2XM1\\b" + << "\\bFABS\\b" + << "\\bFADD\\b" + << "\\bFADDP\\b" + << "\\bFBLD\\b" + << "\\bFBSTP\\b" + << "\\bFCHS\\b" + << "\\bFCLEX\\b" + << "\\bFCOM\\b" + << "\\bFCOMP\\b" + << "\\bFCOMPP\\b" + << "\\bFDECSTP\\b" + << "\\bFDISI\\b" + << "\\bFDIV\\b" + << "\\bFDIVP\\b" + << "\\bFDIVR\\b" + << "\\bFDIVRP\\b" + << "\\bFENI\\b" + << "\\bFFREE\\b" + << "\\bFIADD\\b" + << "\\bFICOM\\b" + << "\\bFICOMP\\b" + << "\\bFIDIV\\b" + << "\\bFIDIVR\\b" + << "\\bFILD\\b" + << "\\bFIMUL\\b" + << "\\bFINCSTP\\b" + << "\\bFINIT\\b" + << "\\bFIST\\b" + << "\\bFISTP\\b" + << "\\bFISUB\\b" + << "\\bFISUBR\\b" + << "\\bFLD\\b" + << "\\bFLD1\\b" + << "\\bFLDCW\\b" + << "\\bFLDENV\\b" + << "\\bFLDENVW\\b" + << "\\bFLDL2E\\b" + << "\\bFLDL2T\\b" + << "\\bFLDLG2\\b" + << "\\bFLDLN2\\b" + << "\\bFLDPI\\b" + << "\\bFLDZ\\b" + << "\\bFMUL\\b" + << "\\bFMULP\\b" + << "\\bFNCLEX\\b" + << "\\bFNDISI\\b" + << "\\bFNENI\\b" + << "\\bFNINIT\\b" + << "\\bFNOP\\b" + << "\\bFNSAVE\\b" + << "\\bFNSAVEW\\b" + << "\\bFNSTCW\\b" + << "\\bFNSTENV\\b" + << "\\bFNSTENVW\\b" + << "\\bFNSTSW\\b" + << "\\bFPATAN\\b" + << "\\bFPREM\\b" + << "\\bFPTAN\\b" + << "\\bFRNDINT\\b" + << "\\bFRSTOR\\b" + << "\\bFRSTORW\\b" + << "\\bFSAVE\\b" + << "\\bFSAVEW\\b" + << "\\bFSCALE\\b" + << "\\bFSQRT\\b" + << "\\bFST\\b" + << "\\bFSTCW\\b" + << "\\bFSTENV\\b" + << "\\bFSTENVW\\b" + << "\\bFSTP\\b" + << "\\bFSTSW\\b" + << "\\bFSUB\\b" + << "\\bFSUBP\\b" + << "\\bFSUBR\\b" + << "\\bFSUBRP\\b" + << "\\bFTST\\b" + << "\\bFWAIT\\b" + << "\\bFXAM\\b" + << "\\bFXCH\\b" + << "\\bFXTRACT\\b" + << "\\bFYL2X\\b" + << "\\bFYL2XP1\\b" + << "\\bFSETPM\\b" + << "\\bFCOS\\b" + << "\\bFLDENVD\\b" + << "\\bFSAVED\\b" + << "\\bFSTENVD\\b" + << "\\bFPREM1\\b" + << "\\bFRSTORD\\b" + << "\\bFSIN\\b" + << "\\bFSINCOS\\b" + << "\\bFSTENVD\\b" + << "\\bFUCOM\\b" + << "\\bFUCOMP\\b" + << "\\bFUCOMPP\\b" + << "\\bFCMOVB\\b" + << "\\bFCMOVBE\\b" + << "\\bFCMOVE\\b" + << "\\bFCMOVNB\\b" + << "\\bFCMOVNBE\\b" + << "\\bFCMOVNE\\b" + << "\\bFCMOVNU\\b" + << "\\bFCMOVU\\b" + << "\\bFCOMI\\b" + << "\\bFCOMIP\\b" + << "\\bFUCOMI\\b" + << "\\bFUCOMIP\\b" + << "\\bCDQE\\b" + << "\\bCQO\\b" + << "\\bMOVMSKPS\\b" + << "\\bMOVMSKPD\\b" + << "\\bPOPCNT\\b" + << "\\bLZCNT\\b" + << "\\bCMPSQ\\b" + << "\\bSCASQ\\b" + << "\\bMOVSQ\\b" + << "\\bLODSQ\\b" + << "\\bSTOSQ\\b" + << "\\bJRCXZ\\b" + << "\\bIRETQ\\b" + << "\\bPUSHFQ\\b" + << "\\bPOPFQ\\b" + << "\\bCMPXCHG16B\\b" + << "\\bJRCXZ\\b" + << "\\bINSB\\b" + << "\\bINSW\\b" + << "\\bOUTSB\\b" + << "\\bOUTSW\\b" + << "\\bLFENCE\\b" + << "\\bSFENCE\\b" + << "\\bMFENCE\\b" + << "\\bPREFETCH\\b" + << "\\bPREFETCHL\\b" + << "\\bPREFETCHW\\b" + << "\\bCLFLUSH\\b" + << "\\bSYSENTER\\b" + << "\\bSYSEXIT\\b" + << "\\bSYSCALL\\b" + << "\\bSYSRET\\b"; + foreach (const QString& pattern, keywordPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); + rule.format = keywordFormat; highlightingRules.append(rule); - rule.pattern = QRegExp("\\]"); - highlightingRules.append(rule); - memoryPatterns << "\\bddq\\b" << - "\\bdb\\b" << "\\bdw\\b" << "\\bdd\\b" << - "\\bdq\\b" << "\\bdt\\b" << "\\bdo\\b" << - "\\bdy\\b" << "\\bequ\\b" << "\\bdf\\b" << - "\\bptr\\b" << - "\\bbyte\\b" << "\\bword\\b" << - "\\bdword\\b" << "\\bqword\\b" << - "\\btword\\b" << "\\boword\\b" << - "\\byword\\b" << "\\bfword\\b" << - "\\bmmword\\b" << "\\bsdword\\b" << - "\\bsqword\\b" << "\\bsword\\b" << - "\\bxmmword\\b" << "\\bymmword\\b" << - "\\bsbyte\\b" << "\\btbyte\\b" << - "\\bDEFAULT\\b" << - "\\bABS\\b" << "\\bREL\\b"; - foreach (const QString &pattern, memoryPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } + } - //! Labels - rule.pattern = QRegExp("\\S+:"); - rule.format = labelFormat; + //! Memory + rule.format = memoryFormat; + QStringList memoryPatterns; + rule.pattern = QRegExp("\\["); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\]"); + highlightingRules.append(rule); + memoryPatterns << "\\bddq\\b" + << "\\bdb\\b" + << "\\bdw\\b" + << "\\bdd\\b" + << "\\bdq\\b" + << "\\bdt\\b" + << "\\bdo\\b" + << "\\bdy\\b" + << "\\bequ\\b" + << "\\bdf\\b" + << "\\bptr\\b" + << "\\bbyte\\b" + << "\\bword\\b" + << "\\bdword\\b" + << "\\bqword\\b" + << "\\btword\\b" + << "\\boword\\b" + << "\\byword\\b" + << "\\bfword\\b" + << "\\bmmword\\b" + << "\\bsdword\\b" + << "\\bsqword\\b" + << "\\bsword\\b" + << "\\bxmmword\\b" + << "\\bymmword\\b" + << "\\bsbyte\\b" + << "\\btbyte\\b" + << "\\bDEFAULT\\b" + << "\\bABS\\b" + << "\\bREL\\b"; + foreach (const QString& pattern, memoryPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - //! Numbers - rule.format = numberFormat; - rule.pattern = QRegExp("\\b[\\-\\+]?\\d+[bod]?\\b"); - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b0[bo]\\d+\\b"); - highlightingRules.append(rule); - //! Hexadecimal notation - rule.pattern = QRegExp("\\b[0-9A-Fa-f]+h\\b"); - highlightingRules.append(rule); - //! Hexadecimal notation - rule.pattern = QRegExp("\\b0[xh][0-9A-Fa-f]+\\b"); - highlightingRules.append(rule); + //! Labels + rule.pattern = QRegExp("\\S+:"); + rule.format = labelFormat; + highlightingRules.append(rule); - //registers - QStringList registerPatterns; - registerPatterns << "\\beax\\b" << "\\bebx\\b" << "\\becx\\b" << - "\\bedx\\b" << "\\bebp\\b" << "\\besp\\b" << - "\\bedi\\b" << "\\besi\\b" << "\\bax\\b" << - "\\bbx\\b" << "\\bcx\\b" << "\\bdx\\b" << - "\\bbp\\b" << "\\bsp\\b" << "\\bsi\\b" << - "\\bdi\\b" << "\\bal\\b" << "\\bah\\b" << - "\\bbl\\b" << "\\bbh\\b" << "\\bcl\\b" << - "\\bch\\b" << "\\bdl\\b" << "\\bdh\\b" << - "\\brax\\b" << "\\brbx\\b" << "\\brcx\\b" << //x64 - "\\brdx\\b" << "\\brbp\\b" << "\\brsp\\b" << - "\\brdi\\b" << "\\brsi\\b" << "\\bspl\\b" << - "\\bbpl\\b" << "\\bsil\\b" << "\\bdil\\b" << - "\\br8\\b" << "\\br8d\\b" << "\\br8w\\b" << - "\\br8b\\b" << "\\br9\\b" << "\\br9d\\b" << - "\\br9w\\b" << "\\br9b\\b" << "\\br10\\b" << - "\\br10d\\b" << "\\br10w\\b" << "\\br10b\\b" << - "\\br11\\b" << "\\br11d\\b" << "\\br11w\\b" << - "\\br11b\\b" << "\\br12\\b" << "\\br12d\\b" << - "\\br12w\\b" << "\\br12b\\b" << "\\br13\\b" << - "\\br13d\\b" << "\\br13w\\b" << "\\br13b\\b" << - "\\br14\\b" << "\\br14d\\b" << "\\br14w\\b" << - "\\br14b\\b" << "\\br15\\b" << "\\br15d\\b" << - "\\br15w\\b" << "\\br15b\\b"; - foreach (const QString &pattern, registerPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - rule.format = registerFormat; - highlightingRules.append(rule); - } + //! Numbers + rule.format = numberFormat; + rule.pattern = QRegExp("\\b[\\-\\+]?\\d+[bod]?\\b"); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b0[bo]\\d+\\b"); + highlightingRules.append(rule); + //! Hexadecimal notation + rule.pattern = QRegExp("\\b[0-9A-Fa-f]+h\\b"); + highlightingRules.append(rule); + //! Hexadecimal notation + rule.pattern = QRegExp("\\b0[xh][0-9A-Fa-f]+\\b"); + highlightingRules.append(rule); - //! .labels and numbers with point - rule.pattern = QRegExp("\\.[^\\s:]+[^:]"); - rule.format = labelWithDotFormat; - highlightingRules.append(rule); - rule.pattern = QRegExp("\\.[^\\s:]+:"); - rule.format = labelFormat; - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b[\\-\\+]?\\d+\\.\\d+\\b"); - rule.format = numberFormat; + // registers + QStringList registerPatterns; + registerPatterns << "\\beax\\b" + << "\\bebx\\b" + << "\\becx\\b" + << "\\bedx\\b" + << "\\bebp\\b" + << "\\besp\\b" + << "\\bedi\\b" + << "\\besi\\b" + << "\\bax\\b" + << "\\bbx\\b" + << "\\bcx\\b" + << "\\bdx\\b" + << "\\bbp\\b" + << "\\bsp\\b" + << "\\bsi\\b" + << "\\bdi\\b" + << "\\bal\\b" + << "\\bah\\b" + << "\\bbl\\b" + << "\\bbh\\b" + << "\\bcl\\b" + << "\\bch\\b" + << "\\bdl\\b" + << "\\bdh\\b" + << "\\brax\\b" + << "\\brbx\\b" + << "\\brcx\\b" << // x64 + "\\brdx\\b" + << "\\brbp\\b" + << "\\brsp\\b" + << "\\brdi\\b" + << "\\brsi\\b" + << "\\bspl\\b" + << "\\bbpl\\b" + << "\\bsil\\b" + << "\\bdil\\b" + << "\\br8\\b" + << "\\br8d\\b" + << "\\br8w\\b" + << "\\br8b\\b" + << "\\br9\\b" + << "\\br9d\\b" + << "\\br9w\\b" + << "\\br9b\\b" + << "\\br10\\b" + << "\\br10d\\b" + << "\\br10w\\b" + << "\\br10b\\b" + << "\\br11\\b" + << "\\br11d\\b" + << "\\br11w\\b" + << "\\br11b\\b" + << "\\br12\\b" + << "\\br12d\\b" + << "\\br12w\\b" + << "\\br12b\\b" + << "\\br13\\b" + << "\\br13d\\b" + << "\\br13w\\b" + << "\\br13b\\b" + << "\\br14\\b" + << "\\br14d\\b" + << "\\br14w\\b" + << "\\br14b\\b" + << "\\br15\\b" + << "\\br15d\\b" + << "\\br15w\\b" + << "\\br15b\\b"; + foreach (const QString& pattern, registerPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); + rule.format = registerFormat; highlightingRules.append(rule); + } - //! System instructions and preprocessor commands - rule.format = systemFormat; - QStringList systemPatterns; - systemPatterns << "\\s\\.\\w+\\b" << "^\\.\\w+\\b" << "\\bSEGMENT\\b" << "\\bPUBLIC\\b" << - "\\bEXTERN\\b" << "\\bEXTRN\\b" << - "\\bALIAS\\b" << "\\bALIGN\\b" << "\\bASSUME\\b" << - "\\bCATSTR\\b" << "\\bCOMM\\b" << "\\bCOMMENT\\b" << - "\\bDOSSEG\\b" << "\\bECHO\\b" << "\\bELSE\\b" << - "\\bELSEIF\\b" << "\\bELSEIF2\\b" << "\\bEND\\b" << - "\\bENDM\\b" << "\\bENDP\\b" << "\\bENDS\\b" << - "\\bEVEN\\b" << "\\bEXITM\\b" << "\\bEXTERNDEF\\b" << - "\\bFOR\\b" << "\\bFORC\\b" << "\\bGOTO\\b" << - "\\bGROUP\\b" << "\\bIF\\b" << "\\bIF2\\b" << - "\\bIFB\\b" << "\\bIFDEF\\b" << "\\bIFDIF\\b" << - "\\bIFE\\b" << "\\bIFIDN\\b" << "\\bIFNB\\b" << - "\\bIFNDEF\\b" << "\\bINCLUDE\\b" << "\\bINCLUDELIB\\b" << - "\\bINSTR\\b" << "\\bINVOKE\\b" << "\\bIRP\\b" << - "\\bIRPC\\b" << "\\bLABEL\\b" << "\\bLOCAL\\b" << - "\\bMACRO\\b" << "\\bNAME\\b" << "\\bOPTION\\b" << - "\\bORG\\b" << "\\b%OUT\\b" << "\\bPAGE\\b" << - "\\bPOPCONTEXT\\b" << "\\bPROC\\b" << "\\bPROTO\\b" << - "\\bPURGE\\b" << "\\bPUSHCONTEXT\\b" << "\\bREAL10\\b" << - "\\bREAL4\\b" << "\\bREAL8\\b" << "\\bRECORD\\b" << - "\\bREPEAT\\b" << "\\bREPT\\b" << "\\bSIZESTR\\b" << - "\\bSTRUC\\b" << "\\bSTRUCT\\b" << "\\bSUBSTR\\b" << - "\\bSUBTITLE\\b" << "\\bSUBTTL\\b" << "\\bTEXTEQU\\b" << - "\\bTITLE\\b" << "\\bTYPEDEF\\b" << "\\bUNION\\b" << - "\\bWHILE\\b"; - foreach (const QString &pattern, systemPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } + //! .labels and numbers with point + rule.pattern = QRegExp("\\.[^\\s:]+[^:]"); + rule.format = labelWithDotFormat; + highlightingRules.append(rule); + rule.pattern = QRegExp("\\.[^\\s:]+:"); + rule.format = labelFormat; + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b[\\-\\+]?\\d+\\.\\d+\\b"); + rule.format = numberFormat; + highlightingRules.append(rule); - //quotations - rule.pattern = QRegExp("\".*\""); - rule.format = quotationFormat; - rule.pattern.setMinimal(true); + //! System instructions and preprocessor commands + rule.format = systemFormat; + QStringList systemPatterns; + systemPatterns << "\\s\\.\\w+\\b" + << "^\\.\\w+\\b" + << "\\bSEGMENT\\b" + << "\\bPUBLIC\\b" + << "\\bEXTERN\\b" + << "\\bEXTRN\\b" + << "\\bALIAS\\b" + << "\\bALIGN\\b" + << "\\bASSUME\\b" + << "\\bCATSTR\\b" + << "\\bCOMM\\b" + << "\\bCOMMENT\\b" + << "\\bDOSSEG\\b" + << "\\bECHO\\b" + << "\\bELSE\\b" + << "\\bELSEIF\\b" + << "\\bELSEIF2\\b" + << "\\bEND\\b" + << "\\bENDM\\b" + << "\\bENDP\\b" + << "\\bENDS\\b" + << "\\bEVEN\\b" + << "\\bEXITM\\b" + << "\\bEXTERNDEF\\b" + << "\\bFOR\\b" + << "\\bFORC\\b" + << "\\bGOTO\\b" + << "\\bGROUP\\b" + << "\\bIF\\b" + << "\\bIF2\\b" + << "\\bIFB\\b" + << "\\bIFDEF\\b" + << "\\bIFDIF\\b" + << "\\bIFE\\b" + << "\\bIFIDN\\b" + << "\\bIFNB\\b" + << "\\bIFNDEF\\b" + << "\\bINCLUDE\\b" + << "\\bINCLUDELIB\\b" + << "\\bINSTR\\b" + << "\\bINVOKE\\b" + << "\\bIRP\\b" + << "\\bIRPC\\b" + << "\\bLABEL\\b" + << "\\bLOCAL\\b" + << "\\bMACRO\\b" + << "\\bNAME\\b" + << "\\bOPTION\\b" + << "\\bORG\\b" + << "\\b%OUT\\b" + << "\\bPAGE\\b" + << "\\bPOPCONTEXT\\b" + << "\\bPROC\\b" + << "\\bPROTO\\b" + << "\\bPURGE\\b" + << "\\bPUSHCONTEXT\\b" + << "\\bREAL10\\b" + << "\\bREAL4\\b" + << "\\bREAL8\\b" + << "\\bRECORD\\b" + << "\\bREPEAT\\b" + << "\\bREPT\\b" + << "\\bSIZESTR\\b" + << "\\bSTRUC\\b" + << "\\bSTRUCT\\b" + << "\\bSUBSTR\\b" + << "\\bSUBTITLE\\b" + << "\\bSUBTTL\\b" + << "\\bTEXTEQU\\b" + << "\\bTITLE\\b" + << "\\bTYPEDEF\\b" + << "\\bUNION\\b" + << "\\bWHILE\\b"; + foreach (const QString& pattern, systemPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - rule.pattern = QRegExp("'.*'"); - rule.pattern.setMinimal(true); - highlightingRules.append(rule); + // quotations + rule.pattern = QRegExp("\".*\""); + rule.format = quotationFormat; + rule.pattern.setMinimal(true); + highlightingRules.append(rule); - //comments - rule.pattern = QRegExp(";[^\n]*"); - rule.isComment = true; - rule.format = commentFormat; - highlightingRules.append(rule); - multiLineComments = false; - commentStartExpression = QRegExp(); - commentEndExpression = QRegExp(); + rule.pattern = QRegExp("'.*'"); + rule.pattern.setMinimal(true); + highlightingRules.append(rule); + + // comments + rule.pattern = QRegExp(";[^\n]*"); + rule.isComment = true; + rule.format = commentFormat; + highlightingRules.append(rule); + multiLineComments = false; + commentStartExpression = QRegExp(); + commentEndExpression = QRegExp(); } diff --git a/masm.h b/masm.h index ea4c4706..1c9f0e28 100644 --- a/masm.h +++ b/masm.h @@ -42,6 +42,7 @@ #define MASM_H #include + #include "assembler.h" /** @@ -53,24 +54,23 @@ * */ -class MASM : public Assembler -{ - Q_OBJECT -public: - explicit MASM(bool x86, QObject *parent = 0); - QString getAssemblerPath(); - QString getLinkerPath(); - quint64 getMainOffset(QFile &lst, QString entryLabel); - void parseLstFile(QFile &lst, QVector &lines, quint64 offset); - void fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression); - QString getStartText(); - void putDebugString(CodeEditor *); - QString getAssemblerOptions(); - QString getLinkerOptions(); +class MASM : public Assembler { + Q_OBJECT + public: + explicit MASM(bool x86, QObject* parent = 0); + QString getAssemblerPath(); + QString getLinkerPath(); + quint64 getMainOffset(QFile& lst, QString entryLabel); + void parseLstFile(QFile& lst, QString& programFilePath, + QVector& lines, quint64 offset); + void fillHighligherRules(QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, + QRegExp& commentEndExpression); + QString getStartText(); + void putDebugString(CodeEditor*); + QString getAssemblerOptions(); + QString getLinkerOptions(); }; -#endif // MASM_H +#endif // MASM_H diff --git a/nasm.cpp b/nasm.cpp index e3e85d01..0a6bc38d 100644 --- a/nasm.cpp +++ b/nasm.cpp @@ -45,459 +45,871 @@ * Implements the NASM Assembler */ -NASM::NASM(bool x86, QObject *parent) : - GccBasedAssembler(x86, parent) -{ -} +NASM::NASM(bool x86, QObject* parent) : GccBasedAssembler(x86, parent) {} -QString NASM::getAssemblerPath() -{ - #ifdef Q_OS_WIN32 - return Common::applicationDataPath() + "/NASM/nasm.exe"; - #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) - return "/usr/local/bin/nasm"; - #else - return "nasm"; - #endif +QString NASM::getAssemblerPath() { +#ifdef Q_OS_WIN32 + return Common::applicationDataPath() + "/NASM/nasm.exe"; +#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__DragonFly__) + return "/usr/local/bin/nasm"; +#else + return "nasm"; +#endif } - -quint64 NASM::getMainOffset(QFile &lst, QString entryLabel) -{ - QTextStream lstStream(&lst); - QRegExp mainLabel(entryLabel + ":"); - mainLabel.setCaseSensitivity(Qt::CaseInsensitive); - bool flag = false; - while (!lstStream.atEnd()) { - QString line = lstStream.readLine(); - if (flag) { - //! Omit strings with data only - //! if in list : line number, address, data and it is all (without instruction) - - //! omit this string - if (line.length() <= 37) { - continue; - } - QByteArray lineArr = line.toLocal8Bit(); - const char *s = lineArr.constData(); - quint64 a, b, c; - if (sscanf(s, "%llu %llx %llx", &a, &b, &c) == 3) { - //! Exclude 0 0 - if (!(b == 0 && c == 0)) { - return b; - } - } - } else { - if (line.indexOf(mainLabel) != -1) - flag = true; +quint64 NASM::getMainOffset(QFile& lst, QString entryLabel) { + QTextStream lstStream(&lst); + QRegExp mainLabel(entryLabel + ":"); + mainLabel.setCaseSensitivity(Qt::CaseInsensitive); + bool flag = false; + while (!lstStream.atEnd()) { + QString line = lstStream.readLine(); + if (flag) { + //! Omit strings with data only + //! if in list : line number, address, data and it is all (without instruction) - + //! omit this string + if (line.length() <= 37) { + continue; + } + QByteArray lineArr = line.toLocal8Bit(); + const char* s = lineArr.constData(); + quint64 a, b, c; + if (sscanf(s, "%llu %llx %llx", &a, &b, &c) == 3) { + //! Exclude 0 0 + if (!(b == 0 && c == 0)) { + return b; } + } + } else { + if (line.indexOf(mainLabel) != -1) flag = true; } - return -1; + } + return -1; } -void NASM::parseLstFile(QFile &lst, QVector &lines, quint64 offset) -{ - bool inTextSection = false; - QRegExp sectionTextRegExp("SECTION\\s+\\.?(text|code)"); - sectionTextRegExp.setCaseSensitivity(Qt::CaseInsensitive); - QRegExp sectionRegExp("SECTION"); - sectionRegExp.setCaseSensitivity(Qt::CaseInsensitive); +void NASM::parseLstFile(QFile& lst, QString& programFilePath, + QVector& lines, quint64 offset) { + bool inTextSection = false; + QRegExp sectionTextRegExp("SECTION\\s+\\.?(text|code)"); + sectionTextRegExp.setCaseSensitivity(Qt::CaseInsensitive); + QRegExp sectionRegExp("SECTION"); + sectionRegExp.setCaseSensitivity(Qt::CaseInsensitive); - QList > instrList; - QTextStream lstStream(&lst); - lstStream.seek(0); - while (!lstStream.atEnd()) { - QString line = lstStream.readLine(); - if (line.indexOf(QRegExp("^ +[0-9]+ +<[0-9]+>")) != -1) { //macro - continue; - } - if (line.indexOf(sectionTextRegExp) != -1) { - inTextSection = true; - } else if (line.indexOf(sectionRegExp) != -1) { - inTextSection = false; - } - //! omit strings with data only - //! if in list : line number, address, data and it is all (without instruction) - - //! omit this string and subtract 1 from offset - if (line.indexOf(QRegExp("^(\\s+[^\\s]+){4}")) == -1) { - continue; - } - if (inTextSection) { - QRegExp lineRegExp("^\\s+[0-9]+\\s+([0-9a-fA-F]+)\\s+\\S+\\s+(.*)"); - lineRegExp.setMinimal(false); - if (lineRegExp.indexIn(line) == 0) { - quint64 address = lineRegExp.cap(1).toULongLong(0, 16); - QString instruction = lineRegExp.cap(2).trimmed(); - instrList.append(QPair(address + offset, instruction)); - } - } + QList > instrList; + QTextStream lstStream(&lst); + lstStream.seek(0); + while (!lstStream.atEnd()) { + QString line = lstStream.readLine(); + if (line.indexOf(QRegExp("^ +[0-9]+ +<[0-9]+>")) != -1) { // macro + continue; + } + if (line.indexOf(sectionTextRegExp) != -1) { + inTextSection = true; + } else if (line.indexOf(sectionRegExp) != -1) { + inTextSection = false; + } + //! omit strings with data only + //! if in list : line number, address, data and it is all (without instruction) - + //! omit this string and subtract 1 from offset + if (line.indexOf(QRegExp("^(\\s+[^\\s]+){4}")) == -1) { + continue; + } + if (inTextSection) { + QRegExp lineRegExp("^\\s+[0-9]+\\s+([0-9a-fA-F]+)\\s+\\S+\\s+(.*)"); + lineRegExp.setMinimal(false); + if (lineRegExp.indexIn(line) == 0) { + quint64 address = lineRegExp.cap(1).toULongLong(0, 16); + QString instruction = lineRegExp.cap(2).trimmed(); + instrList.append(QPair(address + offset, instruction)); + } } + } - QFile programFile(Common::pathInTemp("program.asm")); - programFile.open(QFile::ReadOnly); - QTextStream programStream(&programFile); - //! Offset in list - int i = 0; - int numInCode = 0; - while (!programStream.atEnd()) { - if (i >= instrList.size()) { - break; - } - QString line = programStream.readLine(); - numInCode++; - line = line.trimmed(); - if (line == instrList[i].second) { - LineNum l; - l.numInCode = numInCode; - l.numInMem = instrList[i].first; - lines.append(l); - i++; - } + QFile programFile(programFilePath); + programFile.open(QFile::ReadOnly); + QTextStream programStream(&programFile); + //! Offset in list + int i = 0; + int numInCode = 0; + while (!programStream.atEnd()) { + if (i >= instrList.size()) { + break; + } + QString line = programStream.readLine(); + numInCode++; + line = line.trimmed(); + if (line == instrList[i].second) { + LineNum l; + l.numInCode = numInCode; + l.numInMem = instrList[i].first; + lines.append(l); + i++; } - programFile.close(); + } + programFile.close(); } -QString NASM::getStartText() -{ - if (isx86()) { - return QString("%include \"io.inc\"\n\nsection .text\nglobal CMAIN\n") + - QString("CMAIN:\n ;write your code here\n xor eax, eax\n ret"); - } else { - return QString("%include \"io64.inc\"\n\nsection .text\nglobal CMAIN\n") + - QString("CMAIN:\n ;write your code here\n xor rax, rax\n ret"); - } +QString NASM::getStartText() { + if (isx86()) { + return QString("%include \"io.inc\"\n\nsection .text\nglobal CMAIN\n") + + QString("CMAIN:\n ;write your code here\n xor eax, eax\n ret"); + } else { + return QString("%include \"io64.inc\"\n\nsection .text\nglobal CMAIN\n") + + QString("CMAIN:\n ;write your code here\n xor rax, rax\n ret"); + } } -void NASM::putDebugString(CodeEditor *code) -{ - //! add : mov ebp, esp for making frame for correct debugging if this code has not been added yet - int index = code->toPlainText().indexOf(QRegExp("CMAIN:|main:")); - if (index != -1) { - index = code->toPlainText().indexOf(QChar(':'), index); - if (isx86()) { - if (code->toPlainText().indexOf( - QRegExp("\\s+[Mm][Oo][Vv] +[Ee][Bb][Pp] *, *[Ee][Ss][Pp]"), index + 1) != index + 1) { - QTextCursor cursor = code->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); - cursor.insertText(QString("\n mov ebp, esp; for correct debugging")); - } - } else { - if (code->toPlainText().indexOf( - QRegExp("\\s+[Mm][Oo][Vv] +[Rr][Bb][Pp] *, *[Rr][Ss][Pp]"), index + 1) != index + 1) { - QTextCursor cursor = code->textCursor(); - cursor.movePosition(QTextCursor::Start); - cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); - cursor.insertText(QString("\n mov rbp, rsp; for correct debugging")); - } - } +void NASM::putDebugString(CodeEditor* code) { + //! add : mov ebp, esp for making frame for correct debugging if this code has not been + //! added yet + int index = code->toPlainText().indexOf(QRegExp("CMAIN:|main:")); + if (index != -1) { + index = code->toPlainText().indexOf(QChar(':'), index); + if (isx86()) { + if (code->toPlainText().indexOf( + QRegExp("\\s+[Mm][Oo][Vv] +[Ee][Bb][Pp] *, *[Ee][Ss][Pp]"), index + 1) != + index + 1) { + QTextCursor cursor = code->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); + cursor.insertText(QString("\n mov ebp, esp; for correct debugging")); + } + } else { + if (code->toPlainText().indexOf( + QRegExp("\\s+[Mm][Oo][Vv] +[Rr][Bb][Pp] *, *[Rr][Ss][Pp]"), index + 1) != + index + 1) { + QTextCursor cursor = code->textCursor(); + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, index + 1); + cursor.insertText(QString("\n mov rbp, rsp; for correct debugging")); + } } + } } -QString NASM::getAssemblerOptions() -{ - QString options; - #ifdef Q_OS_WIN32 - if (isx86()) - options = "-f win32 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; - else - options = "-f win64 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; - #else - if (isx86()) - options = "-f elf32 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; - else - options = "-f elf64 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; - #endif - return options; +QString NASM::getAssemblerOptions() { + QString options; +#ifdef Q_OS_WIN32 + if (isx86()) options = "-f win32 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; + else + options = "-f win64 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; +#else + if (isx86()) options = "-f elf32 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; + else + options = "-f elf64 $SOURCE$ -l $LSTOUTPUT$ -o $PROGRAM.OBJ$"; +#endif + return options; } -void NASM::fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression) -{ - typedef Assembler::HighlightingRule HighlightingRule; - QTextCharFormat &keywordFormat = *formats[0]; - QTextCharFormat ®isterFormat = *formats[1]; - QTextCharFormat &numberFormat = *formats[2]; - QTextCharFormat &memoryFormat = *formats[3]; - QTextCharFormat &labelFormat = *formats[4]; - QTextCharFormat &commentFormat = *formats[5]; - QTextCharFormat &systemFormat = *formats[6]; - QTextCharFormat &iomacrosFormat = *formats[7]; - QTextCharFormat "ationFormat = *formats[8]; - QTextCharFormat &labelWithDotFormat = *formats[9]; +void NASM::fillHighligherRules(QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, + QRegExp& commentEndExpression) { + typedef Assembler::HighlightingRule HighlightingRule; + QTextCharFormat& keywordFormat = *formats[0]; + QTextCharFormat& registerFormat = *formats[1]; + QTextCharFormat& numberFormat = *formats[2]; + QTextCharFormat& memoryFormat = *formats[3]; + QTextCharFormat& labelFormat = *formats[4]; + QTextCharFormat& commentFormat = *formats[5]; + QTextCharFormat& systemFormat = *formats[6]; + QTextCharFormat& iomacrosFormat = *formats[7]; + QTextCharFormat& quotationFormat = *formats[8]; + QTextCharFormat& labelWithDotFormat = *formats[9]; - //! Setting up regular expressions - HighlightingRule rule; + //! Setting up regular expressions + HighlightingRule rule; - //! Keywords - QStringList keywordPatterns; - keywordPatterns << "\\bAAA\\b" << "\\bAAD\\b" << "\\bAAM\\b" << "\\bAAS\\b" << - "\\bADC\\b" << "\\bADD\\b" << "\\bAND\\b" << "\\bCALL\\b" << - "\\bCBW\\b" << "\\bCLC\\b" << "\\bCLD\\b" << "\\bCLI\\b" << - "\\bCMC\\b" << "\\bCMP\\b" << "\\bCMPSB\\b" << "\\bCMPSW\\b" << - "\\bCWD\\b" << "\\bDAA\\b" << "\\bDAS\\b" << "\\bDEC\\b" << - "\\bDIV\\b" << "\\bESC\\b" << "\\bHLT\\b" << "\\bIDIV\\b" << - "\\bIMUL\\b" << "\\bIN\\b" << "\\bINC\\b" << "\\bINT\\b" << - "\\bINTO\\b" << "\\bIRET\\b" << "\\bJA\\b" << "\\bJAE\\b" << - "\\bJB\\b" << "\\bJBE\\b" << "\\bJC\\b" << "\\bJCXZ\\b" << - "\\bJE\\b" << "\\bJG\\b" << "\\bJGE\\b" << "\\bJL\\b" << - "\\bJLE\\b" << "\\bJNA\\b" << "\\bJNAE\\b" << "\\bJNB\\b" << - "\\bJNBE\\b" << "\\bJNC\\b" << "\\bJNE\\b" << "\\bJNG\\b" << - "\\bJNGE\\b" << "\\bJNL\\b" << "\\bJNLE\\b" << "\\bJNO\\b" << - "\\bJNP\\b" << "\\bJNS\\b" << "\\bJNZ\\b" << "\\bJO\\b" << - "\\bJP\\b" << "\\bJPE\\b" << "\\bJPO\\b" << "\\bJS\\b" << - "\\bJZ\\b" << "\\bJMP\\b" << "\\bLAHF\\b" << "\\bLDS\\b" << - "\\bLEA\\b" << "\\bLES\\b" << "\\bLOCK\\b" << "\\bLODSB\\b" << - "\\bLODSW\\b" << "\\bLOOP\\b" << "\\bLOOPE\\b" << "\\bLOOPNE\\b" << - "\\bLOOPNZ\\b" << "\\bLOOPZ\\b" << "\\bMOV\\b" << "\\bMOVSB\\b" << - "\\bMOVSW\\b" << "\\bMUL\\b" << "\\bNEG\\b" << "\\bNOP\\b" << - "\\bNOT\\b" << "\\bOR\\b" << "\\bOUT\\b" << "\\bPOP\\b" << - "\\bPOPF\\b" << "\\bPUSH\\b" << "\\bPUSHF\\b" << "\\bRCL\\b" << - "\\bRCR\\b" << "\\bREP\\b" << "\\bREPE\\b" << "\\bREPNE\\b" << - "\\bREPNZ\\b" << "\\bREPZ\\b" << "\\bRET\\b" << "\\bRETN\\b" << - "\\bRETF\\b" << "\\bROL\\b" << "\\bROR\\b" << "\\bSAHF\\b" << - "\\bSAL\\b" << "\\bSAR\\b" << "\\bSBB\\b" << "\\bSCASB\\b" << - "\\bSCASW\\b" << "\\bSHL\\b" << "\\bSHR\\b" << "\\bSTC\\b" << - "\\bSTD\\b" << "\\bSTI\\b" << "\\bSTOSB\\b" << "\\bSTOSW\\b" << - "\\bSUB\\b" << "\\bTEST\\b" << "\\bWAIT\\b" << "\\bXCHG\\b" << - "\\bXLAT\\b" << "\\bXOR\\b" << "\\bBOUND\\b" << "\\bENTER\\b" << - "\\bINS\\b" << "\\bLEAVE\\b" << "\\bOUTS\\b" << "\\bPOPA\\b" << - "\\bPUSHA\\b" << "\\bARPL\\b" << "\\bCLTS\\b" << "\\bLAR\\b" << - "\\bLGDT\\b" << "\\bLIDT\\b" << "\\bLLDT\\b" << "\\bLMSW\\b" << - "\\bLOADALL\\b" << "\\bLSL\\b" << "\\bLTR\\b" << "\\bSGDT\\b" << - "\\bSIDT\\b" << "\\bSLDT\\b" << "\\bSMSW\\b" << "\\bSTR\\b" << - "\\bVERR\\b" << "\\bVERW\\b" << "\\bBSF\\b" << "\\bBSR\\b" << - "\\bBT\\b" << "\\bBTC\\b" << "\\bBTR\\b" << "\\bBTS\\b" << - "\\bCDQ\\b" << "\\bCMPSD\\b" << "\\bCWDE\\b" << "\\bINSD\\b" << - "\\bIRET\\b" << "\\bIRETW\\b" << "\\bIRETD\\b" << "\\bJCXZ\\b" << - "\\bJECXZ\\b" << "\\bLFS\\b" << "\\bLGS\\b" << "\\bLSS\\b" << - "\\bLODSD\\b" << "\\bMOVSD\\b" << "\\bMOVSX\\b" << "\\bMOVZX\\b" << - "\\bOUTSD\\b" << "\\bPOPAD\\b" << "\\bPOPFD\\b" << "\\bPUSHAD\\b" << - "\\bPUSHFD\\b" << "\\bSCASD\\b" << "\\bSETA\\b" << "\\bSETAE\\b" << - "\\bSETB\\b" << "\\bSETBE\\b" << "\\bSETC\\b" << "\\bSETE\\b" << - "\\bSETG\\b" << "\\bSETGE\\b" << "\\bSETL\\b" << "\\bSETLE\\b" << - "\\bSETNA\\b" << "\\bSETNAE\\b" << "\\bSETNB\\b" << "\\bSETNBE\\b" << - "\\bSETNC\\b" << "\\bSETNE\\b" << "\\bSETNG\\b" << "\\bSETNGE\\b" << - "\\bSETNL\\b" << "\\bSETNLE\\b" << "\\bSETNO\\b" << "\\bSETNP\\b" << - "\\bSETNS\\b" << "\\bSETNZ\\b" << "\\bSETO\\b" << "\\bSETP\\b" << - "\\bSETPE\\b" << "\\bSETPO\\b" << "\\bSETS\\b" << "\\bSETZ\\b" << - "\\bSHLD\\b" << "\\bSHRD\\b" << "\\bSTOSD\\b" << - "\\bPOPAD\\b" << "\\bPOPFD\\b" << "\\bPUSHAD\\b" << "\\bPUSHFD\\b" << - "\\bSCASD\\b" << "\\bBSWAP\\b" << "\\bCMPXCHG\\b" << "\\bINVD\\b" << - "\\bINVLPG\\b" << "\\bWBINVD\\b" << "\\bXADD\\b" << "\\bCPUID\\b" << - "\\bCMPXCHG8B\\b" << "\\bRDMSR\\b" << "\\bRDTSC\\b" << "\\bWRMSR\\b" << - "\\bRSM\\b" << "\\bRDPMC\\b" << "\\bCMOVA\\b" << "\\bCMOVAE\\b" << - "\\bCMOVB\\b" << "\\bCMOVBE\\b" << "\\bCMOVC\\b" << "\\bCMOVE\\b" << - "\\bCMOVG\\b" << "\\bCMOVGE\\b" << "\\bCMOVL\\b" << "\\bCMOVLE\\b" << - "\\bCMOVNA\\b" << "\\bCMOVNAE\\b" << "\\bCMOVNB\\b" << "\\bCMOVNBE\\b" << - "\\bCMOVNC\\b" << "\\bCMOVNE\\b" << "\\bCMOVNG\\b" << "\\bCMOVNGE\\b" << - "\\bCMOVNL\\b" << "\\bCMOVNLE\\b" << "\\bCMOVNO\\b" << "\\bCMOVNP\\b" << - "\\bCMOVNS\\b" << "\\bCMOVNZ\\b" << "\\bCMOVO\\b" << "\\bCMOVP\\b" << - "\\bCMOVPE\\b" << "\\bCMOVPO\\b" << "\\bCMOVS\\b" << "\\bCMOVZ\\b" << - "\\bF2XM1\\b" << "\\bFABS\\b" << "\\bFADD\\b" << "\\bFADDP\\b" << - "\\bFBLD\\b" << "\\bFBSTP\\b" << "\\bFCHS\\b" << "\\bFCLEX\\b" << - "\\bFCOM\\b" << "\\bFCOMP\\b" << "\\bFCOMPP\\b" << "\\bFDECSTP\\b" << - "\\bFDISI\\b" << "\\bFDIV\\b" << "\\bFDIVP\\b" << "\\bFDIVR\\b" << - "\\bFDIVRP\\b" << "\\bFENI\\b" << "\\bFFREE\\b" << "\\bFIADD\\b" << - "\\bFICOM\\b" << "\\bFICOMP\\b" << "\\bFIDIV\\b" << "\\bFIDIVR\\b" << - "\\bFILD\\b" << "\\bFIMUL\\b" << "\\bFINCSTP\\b" << "\\bFINIT\\b" << - "\\bFIST\\b" << "\\bFISTP\\b" << "\\bFISUB\\b" << "\\bFISUBR\\b" << - "\\bFLD\\b" << "\\bFLD1\\b" << "\\bFLDCW\\b" << "\\bFLDENV\\b" << - "\\bFLDENVW\\b" << "\\bFLDL2E\\b" << "\\bFLDL2T\\b" << "\\bFLDLG2\\b" << - "\\bFLDLN2\\b" << "\\bFLDPI\\b" << "\\bFLDZ\\b" << "\\bFMUL\\b" << - "\\bFMULP\\b" << "\\bFNCLEX\\b" << "\\bFNDISI\\b" << "\\bFNENI\\b" << - "\\bFNINIT\\b" << "\\bFNOP\\b" << "\\bFNSAVE\\b" << "\\bFNSAVEW\\b" << - "\\bFNSTCW\\b" << "\\bFNSTENV\\b" << "\\bFNSTENVW\\b" << "\\bFNSTSW\\b" << - "\\bFPATAN\\b" << "\\bFPREM\\b" << "\\bFPTAN\\b" << "\\bFRNDINT\\b" << - "\\bFRSTOR\\b" << "\\bFRSTORW\\b" << "\\bFSAVE\\b" << "\\bFSAVEW\\b" << - "\\bFSCALE\\b" << "\\bFSQRT\\b" << "\\bFST\\b" << "\\bFSTCW\\b" << - "\\bFSTENV\\b" << "\\bFSTENVW\\b" << "\\bFSTP\\b" << "\\bFSTSW\\b" << - "\\bFSUB\\b" << "\\bFSUBP\\b" << "\\bFSUBR\\b" << "\\bFSUBRP\\b" << - "\\bFTST\\b" << "\\bFWAIT\\b" << "\\bFXAM\\b" << "\\bFXCH\\b" << - "\\bFXTRACT\\b" << "\\bFYL2X\\b" << "\\bFYL2XP1\\b" << "\\bFSETPM\\b" << - "\\bFCOS\\b" << "\\bFLDENVD\\b" << "\\bFSAVED\\b" << "\\bFSTENVD\\b" << - "\\bFPREM1\\b" << "\\bFRSTORD\\b" << "\\bFSIN\\b" << "\\bFSINCOS\\b" << - "\\bFSTENVD\\b" << "\\bFUCOM\\b" << "\\bFUCOMP\\b" << "\\bFUCOMPP\\b" << - "\\bFCMOVB\\b" << "\\bFCMOVBE\\b" << "\\bFCMOVE\\b" << "\\bFCMOVNB\\b" << - "\\bFCMOVNBE\\b" << "\\bFCMOVNE\\b" << "\\bFCMOVNU\\b" << "\\bFCMOVU\\b" << - "\\bFCOMI\\b" << "\\bFCOMIP\\b" << "\\bFUCOMI\\b" << "\\bFUCOMIP\\b" << - "\\bCDQE\\b" << "\\bCQO\\b" << "\\bMOVMSKPS\\b" << "\\bMOVMSKPD\\b" << - "\\bPOPCNT\\b" << "\\bLZCNT\\b" << "\\bCMPSQ\\b" << "\\bSCASQ\\b" << - "\\bMOVSQ\\b" << "\\bLODSQ\\b" << "\\bSTOSQ\\b" << "\\bJRCXZ\\b" << - "\\bIRETQ\\b" << "\\bPUSHFQ\\b" << "\\bPOPFQ\\b" << "\\bCMPXCHG16B\\b" << - "\\bJRCXZ\\b" << "\\bINSB\\b" << "\\bINSW\\b" << "\\bOUTSB\\b" << - "\\bOUTSW\\b" << "\\bLFENCE\\b" << "\\bSFENCE\\b" << "\\bMFENCE\\b" << - "\\bPREFETCH\\b" << "\\bPREFETCHL\\b" << "\\bPREFETCHW\\b" << "\\bCLFLUSH\\b" << - "\\bSYSENTER\\b" << "\\bSYSEXIT\\b" << "\\bSYSCALL\\b" << "\\bSYSRET\\b"; - foreach (const QString &pattern, keywordPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - rule.format = keywordFormat; - highlightingRules.append(rule); - } - - //! IO macros - rule.format = iomacrosFormat; - QStringList macrosPatterns; - macrosPatterns << "\\bPRINT_DEC\\b" << "\\bPRINT_HEX\\b" << - "\\bPRINT_CHAR\\b" << "\\bPRINT_STRING\\b" << - "\\bNEWLINE\\b" << "\\bPRINT_UDEC\\b" << - "\\bGET_UDEC\\b" << "\\bGET_DEC\\b" << - "\\bGET_HEX\\b" << "\\bGET_CHAR\\b" << - "\\bGET_STRING\\b" << "\\bCMAIN\\b" << "\\bCEXTERN\\b"; - foreach (const QString &pattern, macrosPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseSensitive); - highlightingRules.append(rule); - } - - //! Memory - rule.format = memoryFormat; - QStringList memoryPatterns; - rule.pattern = QRegExp("\\["); - highlightingRules.append(rule); - rule.pattern = QRegExp("\\]"); + //! Keywords + QStringList keywordPatterns; + keywordPatterns << "\\bAAA\\b" + << "\\bAAD\\b" + << "\\bAAM\\b" + << "\\bAAS\\b" + << "\\bADC\\b" + << "\\bADD\\b" + << "\\bAND\\b" + << "\\bCALL\\b" + << "\\bCBW\\b" + << "\\bCLC\\b" + << "\\bCLD\\b" + << "\\bCLI\\b" + << "\\bCMC\\b" + << "\\bCMP\\b" + << "\\bCMPSB\\b" + << "\\bCMPSW\\b" + << "\\bCWD\\b" + << "\\bDAA\\b" + << "\\bDAS\\b" + << "\\bDEC\\b" + << "\\bDIV\\b" + << "\\bESC\\b" + << "\\bHLT\\b" + << "\\bIDIV\\b" + << "\\bIMUL\\b" + << "\\bIN\\b" + << "\\bINC\\b" + << "\\bINT\\b" + << "\\bINTO\\b" + << "\\bIRET\\b" + << "\\bJA\\b" + << "\\bJAE\\b" + << "\\bJB\\b" + << "\\bJBE\\b" + << "\\bJC\\b" + << "\\bJCXZ\\b" + << "\\bJE\\b" + << "\\bJG\\b" + << "\\bJGE\\b" + << "\\bJL\\b" + << "\\bJLE\\b" + << "\\bJNA\\b" + << "\\bJNAE\\b" + << "\\bJNB\\b" + << "\\bJNBE\\b" + << "\\bJNC\\b" + << "\\bJNE\\b" + << "\\bJNG\\b" + << "\\bJNGE\\b" + << "\\bJNL\\b" + << "\\bJNLE\\b" + << "\\bJNO\\b" + << "\\bJNP\\b" + << "\\bJNS\\b" + << "\\bJNZ\\b" + << "\\bJO\\b" + << "\\bJP\\b" + << "\\bJPE\\b" + << "\\bJPO\\b" + << "\\bJS\\b" + << "\\bJZ\\b" + << "\\bJMP\\b" + << "\\bLAHF\\b" + << "\\bLDS\\b" + << "\\bLEA\\b" + << "\\bLES\\b" + << "\\bLOCK\\b" + << "\\bLODSB\\b" + << "\\bLODSW\\b" + << "\\bLOOP\\b" + << "\\bLOOPE\\b" + << "\\bLOOPNE\\b" + << "\\bLOOPNZ\\b" + << "\\bLOOPZ\\b" + << "\\bMOV\\b" + << "\\bMOVSB\\b" + << "\\bMOVSW\\b" + << "\\bMUL\\b" + << "\\bNEG\\b" + << "\\bNOP\\b" + << "\\bNOT\\b" + << "\\bOR\\b" + << "\\bOUT\\b" + << "\\bPOP\\b" + << "\\bPOPF\\b" + << "\\bPUSH\\b" + << "\\bPUSHF\\b" + << "\\bRCL\\b" + << "\\bRCR\\b" + << "\\bREP\\b" + << "\\bREPE\\b" + << "\\bREPNE\\b" + << "\\bREPNZ\\b" + << "\\bREPZ\\b" + << "\\bRET\\b" + << "\\bRETN\\b" + << "\\bRETF\\b" + << "\\bROL\\b" + << "\\bROR\\b" + << "\\bSAHF\\b" + << "\\bSAL\\b" + << "\\bSAR\\b" + << "\\bSBB\\b" + << "\\bSCASB\\b" + << "\\bSCASW\\b" + << "\\bSHL\\b" + << "\\bSHR\\b" + << "\\bSTC\\b" + << "\\bSTD\\b" + << "\\bSTI\\b" + << "\\bSTOSB\\b" + << "\\bSTOSW\\b" + << "\\bSUB\\b" + << "\\bTEST\\b" + << "\\bWAIT\\b" + << "\\bXCHG\\b" + << "\\bXLAT\\b" + << "\\bXOR\\b" + << "\\bBOUND\\b" + << "\\bENTER\\b" + << "\\bINS\\b" + << "\\bLEAVE\\b" + << "\\bOUTS\\b" + << "\\bPOPA\\b" + << "\\bPUSHA\\b" + << "\\bARPL\\b" + << "\\bCLTS\\b" + << "\\bLAR\\b" + << "\\bLGDT\\b" + << "\\bLIDT\\b" + << "\\bLLDT\\b" + << "\\bLMSW\\b" + << "\\bLOADALL\\b" + << "\\bLSL\\b" + << "\\bLTR\\b" + << "\\bSGDT\\b" + << "\\bSIDT\\b" + << "\\bSLDT\\b" + << "\\bSMSW\\b" + << "\\bSTR\\b" + << "\\bVERR\\b" + << "\\bVERW\\b" + << "\\bBSF\\b" + << "\\bBSR\\b" + << "\\bBT\\b" + << "\\bBTC\\b" + << "\\bBTR\\b" + << "\\bBTS\\b" + << "\\bCDQ\\b" + << "\\bCMPSD\\b" + << "\\bCWDE\\b" + << "\\bINSD\\b" + << "\\bIRET\\b" + << "\\bIRETW\\b" + << "\\bIRETD\\b" + << "\\bJCXZ\\b" + << "\\bJECXZ\\b" + << "\\bLFS\\b" + << "\\bLGS\\b" + << "\\bLSS\\b" + << "\\bLODSD\\b" + << "\\bMOVSD\\b" + << "\\bMOVSX\\b" + << "\\bMOVZX\\b" + << "\\bOUTSD\\b" + << "\\bPOPAD\\b" + << "\\bPOPFD\\b" + << "\\bPUSHAD\\b" + << "\\bPUSHFD\\b" + << "\\bSCASD\\b" + << "\\bSETA\\b" + << "\\bSETAE\\b" + << "\\bSETB\\b" + << "\\bSETBE\\b" + << "\\bSETC\\b" + << "\\bSETE\\b" + << "\\bSETG\\b" + << "\\bSETGE\\b" + << "\\bSETL\\b" + << "\\bSETLE\\b" + << "\\bSETNA\\b" + << "\\bSETNAE\\b" + << "\\bSETNB\\b" + << "\\bSETNBE\\b" + << "\\bSETNC\\b" + << "\\bSETNE\\b" + << "\\bSETNG\\b" + << "\\bSETNGE\\b" + << "\\bSETNL\\b" + << "\\bSETNLE\\b" + << "\\bSETNO\\b" + << "\\bSETNP\\b" + << "\\bSETNS\\b" + << "\\bSETNZ\\b" + << "\\bSETO\\b" + << "\\bSETP\\b" + << "\\bSETPE\\b" + << "\\bSETPO\\b" + << "\\bSETS\\b" + << "\\bSETZ\\b" + << "\\bSHLD\\b" + << "\\bSHRD\\b" + << "\\bSTOSD\\b" + << "\\bPOPAD\\b" + << "\\bPOPFD\\b" + << "\\bPUSHAD\\b" + << "\\bPUSHFD\\b" + << "\\bSCASD\\b" + << "\\bBSWAP\\b" + << "\\bCMPXCHG\\b" + << "\\bINVD\\b" + << "\\bINVLPG\\b" + << "\\bWBINVD\\b" + << "\\bXADD\\b" + << "\\bCPUID\\b" + << "\\bCMPXCHG8B\\b" + << "\\bRDMSR\\b" + << "\\bRDTSC\\b" + << "\\bWRMSR\\b" + << "\\bRSM\\b" + << "\\bRDPMC\\b" + << "\\bCMOVA\\b" + << "\\bCMOVAE\\b" + << "\\bCMOVB\\b" + << "\\bCMOVBE\\b" + << "\\bCMOVC\\b" + << "\\bCMOVE\\b" + << "\\bCMOVG\\b" + << "\\bCMOVGE\\b" + << "\\bCMOVL\\b" + << "\\bCMOVLE\\b" + << "\\bCMOVNA\\b" + << "\\bCMOVNAE\\b" + << "\\bCMOVNB\\b" + << "\\bCMOVNBE\\b" + << "\\bCMOVNC\\b" + << "\\bCMOVNE\\b" + << "\\bCMOVNG\\b" + << "\\bCMOVNGE\\b" + << "\\bCMOVNL\\b" + << "\\bCMOVNLE\\b" + << "\\bCMOVNO\\b" + << "\\bCMOVNP\\b" + << "\\bCMOVNS\\b" + << "\\bCMOVNZ\\b" + << "\\bCMOVO\\b" + << "\\bCMOVP\\b" + << "\\bCMOVPE\\b" + << "\\bCMOVPO\\b" + << "\\bCMOVS\\b" + << "\\bCMOVZ\\b" + << "\\bF2XM1\\b" + << "\\bFABS\\b" + << "\\bFADD\\b" + << "\\bFADDP\\b" + << "\\bFBLD\\b" + << "\\bFBSTP\\b" + << "\\bFCHS\\b" + << "\\bFCLEX\\b" + << "\\bFCOM\\b" + << "\\bFCOMP\\b" + << "\\bFCOMPP\\b" + << "\\bFDECSTP\\b" + << "\\bFDISI\\b" + << "\\bFDIV\\b" + << "\\bFDIVP\\b" + << "\\bFDIVR\\b" + << "\\bFDIVRP\\b" + << "\\bFENI\\b" + << "\\bFFREE\\b" + << "\\bFIADD\\b" + << "\\bFICOM\\b" + << "\\bFICOMP\\b" + << "\\bFIDIV\\b" + << "\\bFIDIVR\\b" + << "\\bFILD\\b" + << "\\bFIMUL\\b" + << "\\bFINCSTP\\b" + << "\\bFINIT\\b" + << "\\bFIST\\b" + << "\\bFISTP\\b" + << "\\bFISUB\\b" + << "\\bFISUBR\\b" + << "\\bFLD\\b" + << "\\bFLD1\\b" + << "\\bFLDCW\\b" + << "\\bFLDENV\\b" + << "\\bFLDENVW\\b" + << "\\bFLDL2E\\b" + << "\\bFLDL2T\\b" + << "\\bFLDLG2\\b" + << "\\bFLDLN2\\b" + << "\\bFLDPI\\b" + << "\\bFLDZ\\b" + << "\\bFMUL\\b" + << "\\bFMULP\\b" + << "\\bFNCLEX\\b" + << "\\bFNDISI\\b" + << "\\bFNENI\\b" + << "\\bFNINIT\\b" + << "\\bFNOP\\b" + << "\\bFNSAVE\\b" + << "\\bFNSAVEW\\b" + << "\\bFNSTCW\\b" + << "\\bFNSTENV\\b" + << "\\bFNSTENVW\\b" + << "\\bFNSTSW\\b" + << "\\bFPATAN\\b" + << "\\bFPREM\\b" + << "\\bFPTAN\\b" + << "\\bFRNDINT\\b" + << "\\bFRSTOR\\b" + << "\\bFRSTORW\\b" + << "\\bFSAVE\\b" + << "\\bFSAVEW\\b" + << "\\bFSCALE\\b" + << "\\bFSQRT\\b" + << "\\bFST\\b" + << "\\bFSTCW\\b" + << "\\bFSTENV\\b" + << "\\bFSTENVW\\b" + << "\\bFSTP\\b" + << "\\bFSTSW\\b" + << "\\bFSUB\\b" + << "\\bFSUBP\\b" + << "\\bFSUBR\\b" + << "\\bFSUBRP\\b" + << "\\bFTST\\b" + << "\\bFWAIT\\b" + << "\\bFXAM\\b" + << "\\bFXCH\\b" + << "\\bFXTRACT\\b" + << "\\bFYL2X\\b" + << "\\bFYL2XP1\\b" + << "\\bFSETPM\\b" + << "\\bFCOS\\b" + << "\\bFLDENVD\\b" + << "\\bFSAVED\\b" + << "\\bFSTENVD\\b" + << "\\bFPREM1\\b" + << "\\bFRSTORD\\b" + << "\\bFSIN\\b" + << "\\bFSINCOS\\b" + << "\\bFSTENVD\\b" + << "\\bFUCOM\\b" + << "\\bFUCOMP\\b" + << "\\bFUCOMPP\\b" + << "\\bFCMOVB\\b" + << "\\bFCMOVBE\\b" + << "\\bFCMOVE\\b" + << "\\bFCMOVNB\\b" + << "\\bFCMOVNBE\\b" + << "\\bFCMOVNE\\b" + << "\\bFCMOVNU\\b" + << "\\bFCMOVU\\b" + << "\\bFCOMI\\b" + << "\\bFCOMIP\\b" + << "\\bFUCOMI\\b" + << "\\bFUCOMIP\\b" + << "\\bCDQE\\b" + << "\\bCQO\\b" + << "\\bMOVMSKPS\\b" + << "\\bMOVMSKPD\\b" + << "\\bPOPCNT\\b" + << "\\bLZCNT\\b" + << "\\bCMPSQ\\b" + << "\\bSCASQ\\b" + << "\\bMOVSQ\\b" + << "\\bLODSQ\\b" + << "\\bSTOSQ\\b" + << "\\bJRCXZ\\b" + << "\\bIRETQ\\b" + << "\\bPUSHFQ\\b" + << "\\bPOPFQ\\b" + << "\\bCMPXCHG16B\\b" + << "\\bJRCXZ\\b" + << "\\bINSB\\b" + << "\\bINSW\\b" + << "\\bOUTSB\\b" + << "\\bOUTSW\\b" + << "\\bLFENCE\\b" + << "\\bSFENCE\\b" + << "\\bMFENCE\\b" + << "\\bPREFETCH\\b" + << "\\bPREFETCHL\\b" + << "\\bPREFETCHW\\b" + << "\\bCLFLUSH\\b" + << "\\bSYSENTER\\b" + << "\\bSYSEXIT\\b" + << "\\bSYSCALL\\b" + << "\\bSYSRET\\b"; + foreach (const QString& pattern, keywordPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); + rule.format = keywordFormat; highlightingRules.append(rule); - memoryPatterns << "\\bresb\\b" << "\\bresw\\b" << "\\bresd\\b" << - "\\bresq\\b" << "\\brest\\b" << "\\breso\\b" << - "\\bresy\\b" << "\\bddq\\b" << "\\bresdq\\b" << - "\\bdb\\b" << "\\bdw\\b" << "\\bdd\\b" << - "\\bdq\\b" << "\\bdt\\b" << "\\bdo\\b" << - "\\bdy\\b" << "\\bequ\\b" << - "\\bbyte[\\s\\[]" << "\\bword[\\s\\[]" << - "\\bdword[\\s\\[]" << "\\bqword[\\s\\[]" << - "\\btword[\\s\\[]" << "\\boword[\\s\\[]" << - "\\byword[\\s\\[]" << "\\bDEFAULT\\b" << - "\\bABS\\b" << "\\bREL\\b"; - foreach (const QString &pattern, memoryPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } + } - //! Labels - rule.pattern = QRegExp("\\S+:"); - rule.format = labelFormat; + //! IO macros + rule.format = iomacrosFormat; + QStringList macrosPatterns; + macrosPatterns << "\\bPRINT_DEC\\b" + << "\\bPRINT_HEX\\b" + << "\\bPRINT_CHAR\\b" + << "\\bPRINT_STRING\\b" + << "\\bNEWLINE\\b" + << "\\bPRINT_UDEC\\b" + << "\\bGET_UDEC\\b" + << "\\bGET_DEC\\b" + << "\\bGET_HEX\\b" + << "\\bGET_CHAR\\b" + << "\\bGET_STRING\\b" + << "\\bCMAIN\\b" + << "\\bCEXTERN\\b"; + foreach (const QString& pattern, macrosPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseSensitive); highlightingRules.append(rule); + } - //! Numbers - rule.format = numberFormat; - rule.pattern = QRegExp("\\b[\\-\\+]?\\d+[bod]?\\b"); - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b0[bo]\\d+\\b"); - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b[0-9A-Fa-f]+h\\b"); //hexadecimal notation - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b0[xh][0-9A-Fa-f]+\\b"); //hexadecimal notation + //! Memory + rule.format = memoryFormat; + QStringList memoryPatterns; + rule.pattern = QRegExp("\\["); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\]"); + highlightingRules.append(rule); + memoryPatterns << "\\bresb\\b" + << "\\bresw\\b" + << "\\bresd\\b" + << "\\bresq\\b" + << "\\brest\\b" + << "\\breso\\b" + << "\\bresy\\b" + << "\\bddq\\b" + << "\\bresdq\\b" + << "\\bdb\\b" + << "\\bdw\\b" + << "\\bdd\\b" + << "\\bdq\\b" + << "\\bdt\\b" + << "\\bdo\\b" + << "\\bdy\\b" + << "\\bequ\\b" + << "\\bbyte[\\s\\[]" + << "\\bword[\\s\\[]" + << "\\bdword[\\s\\[]" + << "\\bqword[\\s\\[]" + << "\\btword[\\s\\[]" + << "\\boword[\\s\\[]" + << "\\byword[\\s\\[]" + << "\\bDEFAULT\\b" + << "\\bABS\\b" + << "\\bREL\\b"; + foreach (const QString& pattern, memoryPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - //! Registers - QStringList registerPatterns; - registerPatterns << "\\beax\\b" << "\\bebx\\b" << "\\becx\\b" << - "\\bedx\\b" << "\\bebp\\b" << "\\besp\\b" << - "\\bedi\\b" << "\\besi\\b" << "\\bax\\b" << - "\\bbx\\b" << "\\bcx\\b" << "\\bdx\\b" << - "\\bbp\\b" << "\\bsp\\b" << "\\bsi\\b" << - "\\bdi\\b" << "\\bal\\b" << "\\bah\\b" << - "\\bbl\\b" << "\\bbh\\b" << "\\bcl\\b" << - "\\bch\\b" << "\\bdl\\b" << "\\bdh\\b" << - "\\brax\\b" << "\\brbx\\b" << "\\brcx\\b" << //x64 - "\\brdx\\b" << "\\brbp\\b" << "\\brsp\\b" << - "\\brdi\\b" << "\\brsi\\b" << "\\bspl\\b" << - "\\bbpl\\b" << "\\bsil\\b" << "\\bdil\\b" << - "\\br8\\b" << "\\br8d\\b" << "\\br8w\\b" << - "\\br8b\\b" << "\\br9\\b" << "\\br9d\\b" << - "\\br9w\\b" << "\\br9b\\b" << "\\br10\\b" << - "\\br10d\\b" << "\\br10w\\b" << "\\br10b\\b" << - "\\br11\\b" << "\\br11d\\b" << "\\br11w\\b" << - "\\br11b\\b" << "\\br12\\b" << "\\br12d\\b" << - "\\br12w\\b" << "\\br12b\\b" << "\\br13\\b" << - "\\br13d\\b" << "\\br13w\\b" << "\\br13b\\b" << - "\\br14\\b" << "\\br14d\\b" << "\\br14w\\b" << - "\\br14b\\b" << "\\br15\\b" << "\\br15d\\b" << - "\\br15w\\b" << "\\br15b\\b"; - foreach (const QString &pattern, registerPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - rule.format = registerFormat; - highlightingRules.append(rule); - } + //! Labels + rule.pattern = QRegExp("\\S+:"); + rule.format = labelFormat; + highlightingRules.append(rule); - //! Labels and numbers with point - rule.pattern = QRegExp("\\.[^\\s:]+[^:]"); - rule.format = labelWithDotFormat; - highlightingRules.append(rule); - rule.pattern = QRegExp("\\.[^\\s:]+:"); - rule.format = labelFormat; - highlightingRules.append(rule); - rule.pattern = QRegExp("\\b[\\-\\+]?\\d+\\.\\d+\\b"); - rule.format = numberFormat; + //! Numbers + rule.format = numberFormat; + rule.pattern = QRegExp("\\b[\\-\\+]?\\d+[bod]?\\b"); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b0[bo]\\d+\\b"); + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b[0-9A-Fa-f]+h\\b"); // hexadecimal notation + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b0[xh][0-9A-Fa-f]+\\b"); // hexadecimal notation + highlightingRules.append(rule); + + //! Registers + QStringList registerPatterns; + registerPatterns << "\\beax\\b" + << "\\bebx\\b" + << "\\becx\\b" + << "\\bedx\\b" + << "\\bebp\\b" + << "\\besp\\b" + << "\\bedi\\b" + << "\\besi\\b" + << "\\bax\\b" + << "\\bbx\\b" + << "\\bcx\\b" + << "\\bdx\\b" + << "\\bbp\\b" + << "\\bsp\\b" + << "\\bsi\\b" + << "\\bdi\\b" + << "\\bal\\b" + << "\\bah\\b" + << "\\bbl\\b" + << "\\bbh\\b" + << "\\bcl\\b" + << "\\bch\\b" + << "\\bdl\\b" + << "\\bdh\\b" + << "\\brax\\b" + << "\\brbx\\b" + << "\\brcx\\b" << // x64 + "\\brdx\\b" + << "\\brbp\\b" + << "\\brsp\\b" + << "\\brdi\\b" + << "\\brsi\\b" + << "\\bspl\\b" + << "\\bbpl\\b" + << "\\bsil\\b" + << "\\bdil\\b" + << "\\br8\\b" + << "\\br8d\\b" + << "\\br8w\\b" + << "\\br8b\\b" + << "\\br9\\b" + << "\\br9d\\b" + << "\\br9w\\b" + << "\\br9b\\b" + << "\\br10\\b" + << "\\br10d\\b" + << "\\br10w\\b" + << "\\br10b\\b" + << "\\br11\\b" + << "\\br11d\\b" + << "\\br11w\\b" + << "\\br11b\\b" + << "\\br12\\b" + << "\\br12d\\b" + << "\\br12w\\b" + << "\\br12b\\b" + << "\\br13\\b" + << "\\br13d\\b" + << "\\br13w\\b" + << "\\br13b\\b" + << "\\br14\\b" + << "\\br14d\\b" + << "\\br14w\\b" + << "\\br14b\\b" + << "\\br15\\b" + << "\\br15d\\b" + << "\\br15w\\b" + << "\\br15b\\b"; + foreach (const QString& pattern, registerPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); + rule.format = registerFormat; highlightingRules.append(rule); + } - //! System instructions and preprocessor commands - rule.format = systemFormat; - QStringList systemPatterns; - systemPatterns << "\\btimes\\b" << "\\bsection\\b" << "\\.bss\\b" << - "\\.text\\b" << "\\.data\\b" << - "\\bglobal\\b" << "\\.rodata\\b" << - "\\bextern\\b" << - "\\%arg\\b" << "\\%assign\\b" << "\\%clear\\b" << //macro - "\\%comment\\b" << "\\%define\\b" << "\\%defstr\\b" << - "\\%deftok\\b" << "\\%depend\\b" << - "\\%line\\b" << "\\%local\\b" << "\\%macro\\b" << - "\\%n\\b" << "\\%pathsearch\\b" << "\\%pop\\b" << - "\\%push\\b" << "\\%rep\\b" << "\\%repl\\b" << - "\\%rotate\\b" << "\\%stacksize\\b" << "\\%strcat\\b" << - "\\%strlen\\b" << "\\%substr\\b" << "\\%undef\\b" << - "\\%unmacro\\b" << "\\%use\\b" << "\\%warning\\b" << - "\\%xdefine\\b" << "\\%endcomment\\b" << "\\%endif\\b" << - "\\%endmacro\\b" << "\\%endrep\\b" << "\\%error\\b" << - "\\%exitrep\\b" << "\\%fatal\\b" << "\\%idefine\\b" << - "\\%else\\b" << "\\%imacro\\b" << "\\%include\\b" << - "\\%if\\b" << "\\%ifctx\\b" << "\\%ifdef\\b" << //ifs - "\\%ifempty\\b" << "\\%ifenv\\b" << "\\%ifidn\\b" << - "\\%ifidni\\b" << "\\%ifmacro\\b" << "\\%ifstr\\b" << - "\\%iftoken\\b" << "\\%ifnum\\b" << "\\%ifid\\b" << - "\\%elif\\b" << "\\%elifctx\\b" << "\\%elifdef\\b" << //elifs - "\\%elifempty\\b" << "\\%elifenv\\b" << "\\%elifidn\\b" << - "\\%elifidni\\b" << "\\%elifmacro\\b" << "\\%elifstr\\b" << - "\\%eliftoken\\b" << "\\%elifnum\\b" << "\\%elifid\\b" << - "\\%ifn\\b" << "\\%ifnctx\\b" << "\\%ifndef\\b" << //ifns - "\\%ifnempty\\b" << "\\%ifnenv\\b" << "\\%ifnidn\\b" << - "\\%ifnidni\\b" << "\\%ifnmacro\\b" << "\\%ifnstr\\b" << - "\\%ifntoken\\b" << "\\%ifnnum\\b" << "\\%ifnid\\b" << - "\\%elifn\\b" << "\\%elifnctx\\b" << "\\%elifndef\\b" << //elifns - "\\%elifnempty\\b" << "\\%elifnenv\\b" << "\\%elifnidn\\b" << - "\\%elifnidni\\b" << "\\%elifnmacro\\b" << "\\%elifnstr\\b" << - "\\%elifntoken\\b" << "\\%elifnnum\\b" << "\\%elifnid\\b"; - foreach (const QString &pattern, systemPatterns) { - rule.pattern = QRegExp(pattern); - rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); - highlightingRules.append(rule); - } + //! Labels and numbers with point + rule.pattern = QRegExp("\\.[^\\s:]+[^:]"); + rule.format = labelWithDotFormat; + highlightingRules.append(rule); + rule.pattern = QRegExp("\\.[^\\s:]+:"); + rule.format = labelFormat; + highlightingRules.append(rule); + rule.pattern = QRegExp("\\b[\\-\\+]?\\d+\\.\\d+\\b"); + rule.format = numberFormat; + highlightingRules.append(rule); - //! Quotations - rule.pattern = QRegExp("\".*\""); - rule.format = quotationFormat; - rule.pattern.setMinimal(true); + //! System instructions and preprocessor commands + rule.format = systemFormat; + QStringList systemPatterns; + systemPatterns << "\\btimes\\b" + << "\\bsection\\b" + << "\\.bss\\b" + << "\\.text\\b" + << "\\.data\\b" + << "\\bglobal\\b" + << "\\.rodata\\b" + << "\\bextern\\b" + << "\\%arg\\b" + << "\\%assign\\b" + << "\\%clear\\b" << // macro + "\\%comment\\b" + << "\\%define\\b" + << "\\%defstr\\b" + << "\\%deftok\\b" + << "\\%depend\\b" + << "\\%line\\b" + << "\\%local\\b" + << "\\%macro\\b" + << "\\%n\\b" + << "\\%pathsearch\\b" + << "\\%pop\\b" + << "\\%push\\b" + << "\\%rep\\b" + << "\\%repl\\b" + << "\\%rotate\\b" + << "\\%stacksize\\b" + << "\\%strcat\\b" + << "\\%strlen\\b" + << "\\%substr\\b" + << "\\%undef\\b" + << "\\%unmacro\\b" + << "\\%use\\b" + << "\\%warning\\b" + << "\\%xdefine\\b" + << "\\%endcomment\\b" + << "\\%endif\\b" + << "\\%endmacro\\b" + << "\\%endrep\\b" + << "\\%error\\b" + << "\\%exitrep\\b" + << "\\%fatal\\b" + << "\\%idefine\\b" + << "\\%else\\b" + << "\\%imacro\\b" + << "\\%include\\b" + << "\\%if\\b" + << "\\%ifctx\\b" + << "\\%ifdef\\b" << // ifs + "\\%ifempty\\b" + << "\\%ifenv\\b" + << "\\%ifidn\\b" + << "\\%ifidni\\b" + << "\\%ifmacro\\b" + << "\\%ifstr\\b" + << "\\%iftoken\\b" + << "\\%ifnum\\b" + << "\\%ifid\\b" + << "\\%elif\\b" + << "\\%elifctx\\b" + << "\\%elifdef\\b" << // elifs + "\\%elifempty\\b" + << "\\%elifenv\\b" + << "\\%elifidn\\b" + << "\\%elifidni\\b" + << "\\%elifmacro\\b" + << "\\%elifstr\\b" + << "\\%eliftoken\\b" + << "\\%elifnum\\b" + << "\\%elifid\\b" + << "\\%ifn\\b" + << "\\%ifnctx\\b" + << "\\%ifndef\\b" << // ifns + "\\%ifnempty\\b" + << "\\%ifnenv\\b" + << "\\%ifnidn\\b" + << "\\%ifnidni\\b" + << "\\%ifnmacro\\b" + << "\\%ifnstr\\b" + << "\\%ifntoken\\b" + << "\\%ifnnum\\b" + << "\\%ifnid\\b" + << "\\%elifn\\b" + << "\\%elifnctx\\b" + << "\\%elifndef\\b" << // elifns + "\\%elifnempty\\b" + << "\\%elifnenv\\b" + << "\\%elifnidn\\b" + << "\\%elifnidni\\b" + << "\\%elifnmacro\\b" + << "\\%elifnstr\\b" + << "\\%elifntoken\\b" + << "\\%elifnnum\\b" + << "\\%elifnid\\b"; + foreach (const QString& pattern, systemPatterns) { + rule.pattern = QRegExp(pattern); + rule.pattern.setCaseSensitivity(Qt::CaseInsensitive); highlightingRules.append(rule); + } - rule.pattern = QRegExp("'.*'"); - rule.pattern.setMinimal(true); - highlightingRules.append(rule); + //! Quotations + rule.pattern = QRegExp("\".*\""); + rule.format = quotationFormat; + rule.pattern.setMinimal(true); + highlightingRules.append(rule); - rule.pattern = QRegExp("`.*`"); - rule.pattern.setMinimal(true); - highlightingRules.append(rule); + rule.pattern = QRegExp("'.*'"); + rule.pattern.setMinimal(true); + highlightingRules.append(rule); - //! Comments - rule.pattern = QRegExp(";[^\n]*"); - rule.format = commentFormat; - rule.isComment = true; - highlightingRules.append(rule); - multiLineComments = false; - commentStartExpression = QRegExp(); - commentEndExpression = QRegExp(); + rule.pattern = QRegExp("`.*`"); + rule.pattern.setMinimal(true); + highlightingRules.append(rule); + + //! Comments + rule.pattern = QRegExp(";[^\n]*"); + rule.format = commentFormat; + rule.isComment = true; + highlightingRules.append(rule); + multiLineComments = false; + commentStartExpression = QRegExp(); + commentEndExpression = QRegExp(); } diff --git a/nasm.h b/nasm.h index fd0db2cd..1cc9ea99 100644 --- a/nasm.h +++ b/nasm.h @@ -52,27 +52,25 @@ * */ -class NASM : public GccBasedAssembler -{ - Q_OBJECT -public: - explicit NASM(bool x86, QObject *parent = 0); - QString getAssemblerPath(); - quint64 getMainOffset(QFile &lst, QString entryLabel); - void parseLstFile(QFile &lst, QVector &lines, quint64 offset); - void fillHighligherRules(QVector &highlightingRules, - QList &formats, - bool &multiLineComments, - QRegExp &commentStartExpression, - QRegExp &commentEndExpression); - QString getStartText(); - void putDebugString(CodeEditor *code); - QString getAssemblerOptions(); +class NASM : public GccBasedAssembler { + Q_OBJECT + public: + explicit NASM(bool x86, QObject* parent = 0); + QString getAssemblerPath(); + quint64 getMainOffset(QFile& lst, QString entryLabel); + void parseLstFile(QFile& lst, QString& programFilePath, + QVector& lines, quint64 offset); + void fillHighligherRules(QVector& highlightingRules, + QList& formats, bool& multiLineComments, + QRegExp& commentStartExpression, + QRegExp& commentEndExpression); + QString getStartText(); + void putDebugString(CodeEditor* code); + QString getAssemblerOptions(); -signals: - -public slots: - + signals: + + public slots: }; -#endif // NASM_H +#endif // NASM_H