aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/qregisters.cpp
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2015-07-14 15:32:48 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2015-07-14 15:32:48 +0200
commit7a851424152a942443190ac34856c08d8dfe7580 (patch)
treece9d234d60934e1cb5fbc20fcc1f6e6b677b492d /src/qregisters.cpp
parent45e2f9a5c6a8ac29ce9fa1bf2e18343098c4a050 (diff)
downloadsciteco-7a851424152a942443190ac34856c08d8dfe7580.tar.gz
fixed error message for Qq if <q> does not exist
* the problem comes from StateExpectQReg resetting the QRegMachine too early. StateExpectQReg(QREG_OPTIONAL) states cannot call machine.fail() in their got_register() callback. In other words, commands with both optional or required registers depending on runtime state cannot be modelled with StateExpectQReg. * instead we derive from State directly - most functionality is encapsulated in QRegSpecMachine anyway. * might also fix crashes on some systems.
Diffstat (limited to 'src/qregisters.cpp')
-rw-r--r--src/qregisters.cpp33
1 files changed, 28 insertions, 5 deletions
diff --git a/src/qregisters.cpp b/src/qregisters.cpp
index e47415b..b7ef0c1 100644
--- a/src/qregisters.cpp
+++ b/src/qregisters.cpp
@@ -900,8 +900,13 @@ StateExpectQReg::custom(gchar chr)
if (!machine.input(chr, reg))
return this;
- machine.reset();
+ /*
+ * NOTE: We must reset the Q-Reg machine
+ * now, since we have commands like <M>
+ * that indirectly call their state recursively.
+ */
+ machine.reset();
return got_register(reg);
}
@@ -1050,10 +1055,22 @@ StateSaveQReg::got_file(const gchar *filename)
* If <q> is undefined, it returns \fIsuccess\fP, else a \fIfailure\fP
* boolean.
*/
+StateQueryQReg::StateQueryQReg() : machine(QREG_OPTIONAL)
+{
+ transitions['\0'] = this;
+}
+
State *
-StateQueryQReg::got_register(QRegister *reg)
+StateQueryQReg::custom(gchar chr)
{
- BEGIN_EXEC(&States::start);
+ QRegister *reg;
+
+ if (!machine.input(chr, reg))
+ return this;
+
+ /* like BEGIN_EXEC(&States::start), but resets machine */
+ if (mode > MODE_NORMAL)
+ goto reset;
expressions.eval();
@@ -1061,7 +1078,7 @@ StateQueryQReg::got_register(QRegister *reg)
/* Query Q-Register's existence or string size */
expressions.push(reg ? reg->get_string_size()
: (tecoInt)-1);
- return &States::start;
+ goto reset;
}
/*
@@ -1069,7 +1086,11 @@ StateQueryQReg::got_register(QRegister *reg)
* without colon and otherwise optional.
* While it may be clearer to model this as two States,
* we cannot currently let parsing depend on the colon-modifier.
- * That's why we have to delegate exception throwing to QRegSpecMachine.
+ * That's why we have to declare the Q-Reg machine as QREG_OPTIONAL
+ * and care about exception throwing on our own.
+ * Since we need the machine's state to throw a reasonable error
+ * we cannot derive from StateExpectQReg since it has to reset the
+ * machine before calling got_register().
*/
if (!reg)
machine.fail();
@@ -1085,6 +1106,8 @@ StateQueryQReg::got_register(QRegister *reg)
expressions.push(reg->get_integer());
}
+reset:
+ machine.reset();
return &States::start;
}