Permalink
Browse files

Improve input syscall handling

Aborting an input prompt (e.g. by pressing Cancel in the GUI) now throws
a syscall error that aborts the program.  This allows the user to escape
out of an infinite loop of input syscalls (the input dialog is modal,
making it impossible to access the stop button in the toolbar). [CS031 #65]

In the GUI, update the output console (i.e. flush output) before
prompting for new input.
  • Loading branch information...
1 parent bc51b0e commit 1bccaa3b02450d79bb075dae66a9fdc84fece324 Andrew Ayer committed Oct 12, 2011
Showing with 25 additions and 6 deletions.
  1. +3 −0 src/gui/IOConsole.H
  2. +12 −3 src/gui/OutputConsole.cpp
  3. +4 −2 src/gui/SPIMSyscalls.cpp
  4. +6 −1 src/gui/TextIOConsole.cpp
View
@@ -52,6 +52,9 @@ public:
// You can call undo_output multiple times to undo the last several outputs
virtual void undo_output () = 0;
virtual bool can_undo_output () const = 0;
+
+ // Exception may be thrown if the user aborts input
+ class InputError { };
};
View
@@ -83,24 +83,33 @@ void OutputConsole::update_output ()
std::string OutputConsole::prompt_for_string (State* state, int status, std::string prompt_message, size_t max_length)
{
m_gui->getOutputConsole()->update();
- QString result = QInputDialog::getText(NULL, "Syscall", prompt_message.c_str());
+ bool okay = false;
+ QString result = QInputDialog::getText(NULL, "Syscall", prompt_message.c_str(), QLineEdit::Normal, "", &okay);
+ if (!okay)
+ throw InputError();
return result.toStdString().substr(0, max_length);
}
int OutputConsole::prompt_for_int (State* state, int status, std::string prompt_message, int min, int max)
{
+ m_gui->getOutputConsole()->update();
bool okay = false;
int result = QInputDialog::getInteger(NULL, "Syscall", prompt_message.c_str(), 0, min, max, 1, &okay);
+ if (!okay)
+ throw InputError();
- return okay ? result : 0;
+ return result;
}
double OutputConsole::prompt_for_double (State* state, int status, std::string prompt_message, double min, double max)
{
+ m_gui->getOutputConsole()->update();
bool okay = false;
double result = QInputDialog::getDouble(NULL, "Syscall", prompt_message.c_str(), 0, min, max, 1, &okay);
+ if (!okay)
+ throw InputError();
- return okay ? result : 0.0;
+ return result;
}
View
@@ -121,7 +121,7 @@ void SPIMSyscalls::output_syscall (State* s, int status, int syscall, int valueO
}
void SPIMSyscalls::input_syscall (State* s, int status, int syscall, int valueOfa0)
-{
+try {
switch (syscall) {
case S_READ_INT:
s->setRegister(v0, io->prompt_for_int(s, status, "Input integer"));
@@ -144,12 +144,14 @@ void SPIMSyscalls::input_syscall (State* s, int status, int syscall, int valueOf
break;
}
+} catch (IOConsole::InputError) {
+ s->syscallError("Input error");
}
void SPIMSyscalls::read_string (State* s, int status, unsigned int buffer_address, size_t max_length)
{
if (max_length == 0) {
- s->breakError("read_string called with a max length ($a1) of 0");
+ s->syscallError("read_string called with a max length ($a1) of 0");
return;
}
@@ -37,7 +37,8 @@ std::string TextIOConsole::prompt_for_string (State* state, int status, std::st
{
std::string input;
prompt_out << prompt_message << ": ";
- std::getline(in, input);
+ if (!std::getline(in, input))
+ throw InputError();
return input.substr(0, max_length);
}
@@ -46,6 +47,8 @@ int TextIOConsole::prompt_for_int (State* state, int status, std::string prompt
int input;
prompt_out << prompt_message << ": ";
in >> input;
+ if (!in)
+ throw InputError();
return input;
}
@@ -54,6 +57,8 @@ double TextIOConsole::prompt_for_double (State* state, int status, std::string
double input;
prompt_out << prompt_message << ": ";
in >> input;
+ if (!in)
+ throw InputError();
return input;
}

0 comments on commit 1bccaa3

Please sign in to comment.