Add SyscallViewer dialog for viewing supported system calls
MODIFY
src/mainwindow.cpp
src/mainwindow.cpp
#include "ripessettings.h"
#include "savedialog.h"
#include "settingsdialog.h"
+#include "syscall/syscallviewer.h"
#include "syscall/systemio.h"
#include "version/version.h"
@@ -94,6 +95,10 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), m_ui(new Ui::Main
connect(ProcessorHandler::get(), &ProcessorHandler::reqProcessorReset, m_processorTab, &ProcessorTab::reset);
connect(ProcessorHandler::get(), &ProcessorHandler::reqReloadProgram, m_editTab, &EditTab::emitProgramChanged);
+ connect(m_ui->actionSystem_calls, &QAction::triggered, [=] {
+ SyscallViewer v;
+ v.exec();
+ });
connect(m_ui->actionOpen_wiki, &QAction::triggered, this, &MainWindow::wiki);
connect(m_ui->actionVersion, &QAction::triggered, this, &MainWindow::version);
connect(m_ui->actionSettings, &QAction::triggered, this, &MainWindow::settingsTriggered);

MODIFY
src/mainwindow.ui
src/mainwindow.ui
<string>Help</string>
</property>
<addaction name="actionOpen_wiki"/>
+ <addaction name="actionSystem_calls"/>
<addaction name="actionVersion"/>
</widget>
<widget class="QMenu" name="menuEdit">
<string>Settings</string>
</property>
</action>
+ <action name="actionSystem_calls">
+ <property name="text">
+ <string>System calls</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>

MODIFY
src/processorhandler.h
src/processorhandler.h
@@ -31,7 +31,7 @@ public:
const ProcessorID& getID() const { return m_currentID; }
std::weak_ptr<const Program> getProgram() const { return m_program; }
const ISAInfoBase* currentISA() const { return m_currentProcessor->implementsISA(); }
-
+ const SyscallManager& getSyscallManager() const { return *m_syscallManager; }
/**
* @brief loadProcessorToWidget
* Loads the current processor to the @param VSRTLWidget. Required given that ProcessorHandler::getProcessor returns

MODIFY
src/syscall/ripes_syscall.h
src/syscall/ripes_syscall.h
@@ -21,6 +21,7 @@ public:
virtual ~Syscall() {}
const QString& name() const { return m_name; }
const QString& description() const { return m_description; }
+ const std::map<unsigned, QString>& argumentDescriptions() const { return m_argumentDescriptions; }
virtual void execute() = 0;
@@ -40,12 +41,16 @@ public:
*/
void execute(int id) {
if (m_syscalls.count(id) == 0) {
- QMessageBox::warning(nullptr, "Error", "Unknown system call: " + QString::number(id));
+ QMessageBox::warning(nullptr, "Error",
+ "Unknown system call: " + QString::number(id) +
+ "\nRefer to \"Help->System calls\" for a list of support system calls.");
} else {
m_syscalls.at(id)->execute();
}
}
+ const std::map<int, std::unique_ptr<Syscall>>& getSyscalls() const { return m_syscalls; }
+
protected:
SyscallManager() {}
std::map<int, std::unique_ptr<Syscall>> m_syscalls;

ADD
src/syscall/syscallviewer.cpp
+#include "syscallviewer.h"
+#include "ui_syscallviewer.h"
+
+#include "processorhandler.h"
+
+#include <QTableWidgetItem>
+
+namespace Ripes {
+
+SyscallViewer::SyscallViewer(QWidget* parent) : QDialog(parent), m_ui(new Ui::SyscallViewer) {
+ m_ui->setupUi(this);
+
+ setWindowTitle("Supported system calls");
+
+ m_ui->splitter->setStretchFactor(0, 0);
+ m_ui->splitter->setStretchFactor(1, 1);
+
+ auto font = m_ui->syscallTitle->font();
+ font.setBold(true);
+ font.setPointSize(static_cast<int>(font.pointSize() * 1.2));
+ m_ui->syscallTitle->setFont(font);
+
+ const auto& syscallManager = ProcessorHandler::get()->getSyscallManager();
+
+ // Setup syscall list
+ m_ui->syscallList->setColumnCount(2);
+ m_ui->syscallList->setSortingEnabled(false);
+ for (const auto& iter : syscallManager.getSyscalls()) {
+ addSyscall(iter.first, iter.second.get());
+ }
+ m_ui->syscallList->setSortingEnabled(true);
+ m_ui->syscallList->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_ui->syscallList->verticalHeader()->hide();
+ m_ui->syscallList->setHorizontalHeaderLabels({"Call number", "Name"});
+ m_ui->syscallList->horizontalHeader()->setStretchLastSection(true);
+ connect(m_ui->syscallList, &QTableWidget::currentItemChanged, this, &SyscallViewer::handleItemChanged);
+
+ // Setup syscall argument styling
+ m_ui->syscallArguments->setColumnCount(2);
+ m_ui->syscallArguments->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_ui->syscallArguments->horizontalHeader()->setStretchLastSection(true);
+ m_ui->syscallArguments->setHorizontalHeaderLabels({"Arg. #", "Description"});
+ m_ui->syscallArguments->verticalHeader()->hide();
+
+ // Select first row to set the initial state
+ m_ui->syscallList->selectRow(0);
+}
+
+void SyscallViewer::handleItemChanged(QTableWidgetItem* current, QTableWidgetItem*) {
+ if (current == nullptr)
+ return;
+
+ setCurrentSyscall(current->data(Qt::UserRole).value<const Syscall*>());
+}
+
+void SyscallViewer::setCurrentSyscall(const Syscall* syscall) {
+ if (syscall == nullptr)
+ return;
+
+ m_ui->syscallArguments->clearContents();
+ m_ui->syscallArguments->setRowCount(0);
+ m_ui->syscallTitle->setText(syscall->name());
+ m_ui->syscallDescription->setText(syscall->description());
+ for (const auto& iter : syscall->argumentDescriptions()) {
+ addArgument(iter.first, iter.second);
+ }
+}
+
+void SyscallViewer::addArgument(unsigned int idx, const QString& description) {
+ m_ui->syscallArguments->setRowCount(m_ui->syscallArguments->rowCount() + 1);
+ QTableWidgetItem* idxItem = new QTableWidgetItem();
+ QTableWidgetItem* textItem = new QTableWidgetItem();
+
+ idxItem->setData(Qt::EditRole, QString::number(idx));
+ textItem->setData(Qt::DisplayRole, description);
+
+ idxItem->setFlags(idxItem->flags() ^ Qt::ItemIsEditable);
+ textItem->setFlags(textItem->flags() ^ Qt::ItemIsEditable);
+
+ const int row = m_ui->syscallArguments->rowCount() - 1;
+ m_ui->syscallArguments->setItem(row, 0, idxItem);
+ m_ui->syscallArguments->setItem(row, 1, textItem);
+}
+
+void SyscallViewer::addSyscall(unsigned id, const Syscall* syscall) {
+ m_ui->syscallList->setRowCount(m_ui->syscallList->rowCount() + 1);
+ QTableWidgetItem* idItem = new QTableWidgetItem();
+ QTableWidgetItem* textItem = new QTableWidgetItem();
+
+ idItem->setData(Qt::EditRole, QString::number(id));
+ textItem->setData(Qt::DisplayRole, syscall->name());
+ idItem->setData(Qt::UserRole, QVariant::fromValue(syscall));
+ textItem->setData(Qt::UserRole, QVariant::fromValue(syscall));
+
+ idItem->setFlags(idItem->flags() ^ Qt::ItemIsEditable);
+ textItem->setFlags(textItem->flags() ^ Qt::ItemIsEditable);
+
+ const int row = m_ui->syscallList->rowCount() - 1;
+ m_ui->syscallList->setItem(row, 0, idItem);
+ m_ui->syscallList->setItem(row, 1, textItem);
+}
+
+SyscallViewer::~SyscallViewer() {
+ delete m_ui;
+}
+
+} // namespace Ripes
+
+Q_DECLARE_METATYPE(const Ripes::Syscall*);

ADD
src/syscall/syscallviewer.h
+#pragma once
+#include <QDialog>
+#include <QTableWidgetItem>
+
+#include "ripes_syscall.h"
+
+namespace Ripes {
+
+namespace Ui {
+class SyscallViewer;
+}
+
+class SyscallViewer : public QDialog {
+ Q_OBJECT
+
+public:
+ explicit SyscallViewer(QWidget* parent = nullptr);
+ ~SyscallViewer();
+
+private:
+ void handleItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
+ void addSyscall(unsigned id, const Syscall* syscall);
+ void addArgument(unsigned idx, const QString& description);
+ void setCurrentSyscall(const Syscall* syscall);
+
+ Ui::SyscallViewer* m_ui;
+};
+} // namespace Ripes

ADD
src/syscall/syscallviewer.ui
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Ripes::SyscallViewer</class>
+ <widget class="QDialog" name="Ripes::SyscallViewer">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>733</width>
+ <height>395</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QTableWidget" name="syscallList">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QWidget" name="layoutWidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="syscallTitle">
+ <property name="text">
+ <string>title</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="syscallDescription">
+ <property name="text">
+ <string>description</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableWidget" name="syscallArguments"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Ripes::SyscallViewer</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Ripes::SyscallViewer</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>

Add SyscallViewer dialog for viewing supported system calls