aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2014-11-20 05:08:19 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2014-11-20 05:08:19 +0100
commite909fb2179724b5619213520ca46cc31b4e6713b (patch)
treeb80edd2db67783d9a44a0dc45ffbe7e0baef20fb /src/parser.cpp
parentf843a090cdda120d58f968b7936bdcc53b61e323 (diff)
downloadsciteco-e909fb2179724b5619213520ca46cc31b4e6713b.tar.gz
Throw error when a macro terminates while a local q-reg is edited.
This is only a problem if the macro created the local Q-Register table (i.e. not when called with ":M") but resulted in segfaults. Since we do not want to save in a Q-Reg whether it is local (and that wouldn't suffice anyway), we do it in the Q-Register table cleanup. The corresponding QRegisterTable::clear() must be called explicitly, since the RBTree::clear() called on destruction does not and cannot throw errors. If QRegisterTable::clear() has been called successfully, the default object destructor will not do much. If it has thrown an error, the destructor will clean up the remaining Q-Registers.
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp40
1 files changed, 26 insertions, 14 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 0b11721..35b6add 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -146,25 +146,37 @@ Execute::macro(const gchar *macro, bool locals)
try {
step(macro, strlen(macro));
- if (Goto::skip_label) {
- Error error("Label \"%s\" not found",
- Goto::skip_label);
- error.pos = strlen(macro);
- String::get_coord(macro, error.pos,
- error.line, error.column);
- throw error;
- }
+ /*
+ * Subsequent errors must still be
+ * attached to this macro invocation.
+ */
+ try {
+ if (Goto::skip_label)
+ throw Error("Label \"%s\" not found",
+ Goto::skip_label);
+
+ if (States::current != &States::start)
+ /*
+ * can only happen if we returned because
+ * of macro end
+ */
+ throw Error("Unterminated command");
- if (States::current != &States::start) {
- Error error("Unterminated command");
/*
- * can only happen if we returned because
- * of macro end
+ * This handles the problem of Q-Registers
+ * local to the macro invocation being edited
+ * when the macro terminates.
+ * QRegisterTable::clear() throws an error
+ * if this happens and the Q-Reg editing
+ * is undone.
*/
+ if (locals)
+ QRegisters::locals->clear();
+ } catch (Error &error) {
error.pos = strlen(macro);
String::get_coord(macro, error.pos,
- error.line, error.column);
- throw error;
+ error.line, error.column);
+ throw; /* forward */
}
} catch (...) {
g_free(Goto::skip_label);