aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-20 03:33:06 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-20 06:07:34 +0100
commit2d31c1c5f08bbe19faf0e874604517fb67dc5ee7 (patch)
tree68c9cc91ad443e5f257861f6e56e4036aeafaf69
parentf797b2c8e30a4a6f9370db293289a158729b2525 (diff)
downloadsciteco-2d31c1c5f08bbe19faf0e874604517fb67dc5ee7.tar.gz
fixed rubout of macro invocations: goto tables and q-registers are allocated on the C++ call stack and configured to not emit undo tokens
this introduces additional logic but has the huge advantage that the tables can be freed after the macro invocation. if undo tokens were emitted, the tables had to be kept in the undo stack so they can be restored during rubout. this however would be both complicated and unnecessarily inefficient since the tables would reach their initial state during rubout and be deallocated anyways. * similar (but not strictly necessary optimizations) can be performed for macro invocations * also wrapper Q-Register setting/getting -> will allow a custom "*" register getter (e.g. calculates buffer position on the fly)
-rw-r--r--goto.h10
-rw-r--r--parser.cpp33
-rw-r--r--qbuffers.cpp35
-rw-r--r--qbuffers.h38
4 files changed, 80 insertions, 36 deletions
diff --git a/goto.h b/goto.h
index 146bade..6275d34 100644
--- a/goto.h
+++ b/goto.h
@@ -53,8 +53,13 @@ class GotoTable : public RBTree {
}
};
+ /*
+ * whether to generate UndoTokens (unnecessary in macro invocations)
+ */
+ bool must_undo;
+
public:
- GotoTable() : RBTree() {}
+ GotoTable(bool _undo = true) : RBTree(), must_undo(_undo) {}
gint remove(gchar *name);
gint find(gchar *name);
@@ -63,7 +68,8 @@ public:
inline void
undo_set(gchar *name, gint pc = -1)
{
- undo.push(new UndoTokenSet(this, name, pc));
+ if (must_undo)
+ undo.push(new UndoTokenSet(this, name, pc));
}
#ifdef DEBUG
diff --git a/parser.cpp b/parser.cpp
index fb31add..04c7a3e 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -64,10 +64,10 @@ void
Execute::macro(const gchar *macro, bool locals) throw (State::Error)
{
GotoTable *parent_goto_table = Goto::table;
- GotoTable macro_goto_table;
+ GotoTable macro_goto_table(false);
- QRegisterTable *parent_locals;
- QRegisterTable macro_locals;
+ QRegisterTable *parent_locals = QRegisters::locals;
+ QRegisterTable macro_locals(false);
State *parent_state = States::current;
gint parent_pc = macro_pc;
@@ -82,7 +82,6 @@ Execute::macro(const gchar *macro, bool locals) throw (State::Error)
Goto::table = &macro_goto_table;
if (locals) {
- parent_locals = QRegisters::locals;
macro_locals.initialize();
QRegisters::locals = &macro_locals;
}
@@ -96,10 +95,7 @@ Execute::macro(const gchar *macro, bool locals) throw (State::Error)
g_free(Goto::skip_label);
Goto::skip_label = NULL;
- if (locals) {
- delete QRegisters::locals;
- QRegisters::locals = parent_locals;
- }
+ QRegisters::locals = parent_locals;
Goto::table = parent_goto_table;
macro_pc = parent_pc;
@@ -108,10 +104,7 @@ Execute::macro(const gchar *macro, bool locals) throw (State::Error)
throw; /* forward */
}
- if (locals) {
- delete QRegisters::locals;
- QRegisters::locals = parent_locals;
- }
+ QRegisters::locals = parent_locals;
Goto::table = parent_goto_table;
macro_pc = parent_pc;
@@ -279,7 +272,7 @@ StateExpectString::machine_input(gchar chr) throw (Error)
reg = QRegisters::globals[g_ascii_toupper(chr)];
if (!reg)
throw InvalidQRegError(chr);
- return g_strdup((gchar []){(gchar)reg->integer, '\0'});
+ return g_strdup(CHR2STR(reg->get_integer()));
}
break;
@@ -290,7 +283,7 @@ StateExpectString::machine_input(gchar chr) throw (Error)
reg = (*QRegisters::locals)[g_ascii_toupper(chr)];
if (!reg)
throw InvalidQRegError(chr, true);
- return g_strdup((gchar []){(gchar)reg->integer, '\0'});
+ return g_strdup(CHR2STR(reg->get_integer()));
}
case Machine::STATE_CTL_EQ:
@@ -697,7 +690,7 @@ StateStart::custom(gchar chr) throw (Error)
case ';':
BEGIN_EXEC(this);
- v = QRegisters::globals["_"]->integer;
+ v = QRegisters::globals["_"]->get_integer();
rc = expressions.pop_num_calc(1, v);
if (eval_colon())
rc = ~rc;
@@ -1546,8 +1539,8 @@ StateSearch::process(const gchar *str,
undo.push_msg(SCI_GOTOPOS, interface.ssm(SCI_GETCURRENTPOS));
- undo.push_var<gint64>(search_reg->integer);
- search_reg->integer = FAILURE;
+ search_reg->undo_set_integer();
+ search_reg->set_integer(FAILURE);
/* NOTE: pattern2regexp() modifies str pointer */
re_pattern = pattern2regexp(str);
@@ -1611,7 +1604,7 @@ StateSearch::process(const gchar *str,
if (matched_from >= 0 && matched_to >= 0) {
/* match success */
- search_reg->integer = SUCCESS;
+ search_reg->set_integer(SUCCESS);
interface.ssm(SCI_SETSEL, matched_from, matched_to);
} else {
interface.ssm(SCI_GOTOPOS, parameters.dot);
@@ -1637,8 +1630,8 @@ StateSearch::done(const gchar *str) throw (Error)
}
if (eval_colon())
- expressions.push(search_reg->integer);
- else if (IS_FAILURE(search_reg->integer) &&
+ expressions.push(search_reg->get_integer());
+ else if (IS_FAILURE(search_reg->get_integer()) &&
!expressions.find_op(Expressions::OP_LOOP) /* not in loop */)
interface.msg(Interface::MSG_ERROR, "Search string not found!");
diff --git a/qbuffers.cpp b/qbuffers.cpp
index 4aa0c86..42ac436 100644
--- a/qbuffers.cpp
+++ b/qbuffers.cpp
@@ -93,6 +93,9 @@ QRegisterData::set_string(const gchar *str)
void
QRegisterData::undo_set_string(void)
{
+ if (!must_undo)
+ return;
+
current_save_dot();
if (ring.current)
ring.current->undo_edit();
@@ -133,6 +136,9 @@ QRegisterData::edit(void)
void
QRegisterData::undo_edit(void)
{
+ if (!must_undo)
+ return;
+
undo.push_msg(SCI_GOTOPOS, dot);
undo.push_msg(SCI_SETDOCPOINTER, 0, (sptr_t)get_document());
}
@@ -147,6 +153,9 @@ QRegister::edit(void)
void
QRegister::undo_edit(void)
{
+ if (!must_undo)
+ return;
+
interface.undo_info_update(this);
QRegisterData::undo_edit();
}
@@ -254,7 +263,7 @@ QRegisterStack::push(QRegister *reg)
{
Entry *entry = new Entry();
- entry->integer = reg->integer;
+ entry->set_integer(reg->get_integer());
if (reg->string) {
gchar *str = reg->get_string();
entry->set_string(str);
@@ -275,17 +284,19 @@ QRegisterStack::pop(QRegister *reg)
if (!entry)
return false;
- undo.push_var(reg->integer);
- reg->integer = entry->integer;
+ reg->undo_set_integer();
+ reg->set_integer(entry->get_integer());
/* exchange document ownership between Stack entry and Q-Register */
string = reg->string;
- undo.push_var(reg->string);
+ if (reg->must_undo)
+ undo.push_var(reg->string);
reg->string = entry->string;
undo.push_var(entry->string);
entry->string = string;
- undo.push_var(reg->dot);
+ if (reg->must_undo)
+ undo.push_var(reg->dot);
reg->dot = entry->dot;
SLIST_REMOVE_HEAD(&head, entries);
@@ -813,7 +824,7 @@ StateGetQRegInteger::got_register(QRegister *reg) throw (Error)
BEGIN_EXEC(&States::start);
expressions.eval();
- expressions.push(reg->integer);
+ expressions.push(reg->get_integer());
return &States::start;
}
@@ -823,8 +834,8 @@ StateSetQRegInteger::got_register(QRegister *reg) throw (Error)
{
BEGIN_EXEC(&States::start);
- undo.push_var<gint64>(reg->integer);
- reg->integer = expressions.pop_num_calc();
+ reg->undo_set_integer();
+ reg->set_integer(expressions.pop_num_calc());
return &States::start;
}
@@ -832,11 +843,13 @@ StateSetQRegInteger::got_register(QRegister *reg) throw (Error)
State *
StateIncreaseQReg::got_register(QRegister *reg) throw (Error)
{
+ gint64 res;
+
BEGIN_EXEC(&States::start);
- undo.push_var<gint64>(reg->integer);
- reg->integer += expressions.pop_num_calc();
- expressions.push(reg->integer);
+ reg->undo_set_integer();
+ res = reg->get_integer() + expressions.pop_num_calc();
+ expressions.push(reg->set_integer(res));
return &States::start;
}
diff --git a/qbuffers.h b/qbuffers.h
index 3613c93..fae77f5 100644
--- a/qbuffers.h
+++ b/qbuffers.h
@@ -31,14 +31,19 @@ gchar *get_absolute_path(const gchar *path);
*/
class QRegisterData {
-public:
gint64 integer;
+public:
typedef void document;
document *string;
gint dot;
- QRegisterData() : integer(0), string(NULL), dot(0) {}
+ /*
+ * whether to generate UndoTokens (unnecessary in macro invocations)
+ */
+ bool must_undo;
+
+ QRegisterData() : integer(0), string(NULL), dot(0), must_undo(true) {}
virtual
~QRegisterData()
{
@@ -54,6 +59,23 @@ public:
return string;
}
+ virtual gint64
+ set_integer(gint64 i)
+ {
+ return integer = i;
+ }
+ virtual void
+ undo_set_integer(void)
+ {
+ if (must_undo)
+ undo.push_var(integer);
+ }
+ virtual gint64
+ get_integer(void)
+ {
+ return integer;
+ }
+
virtual void set_string(const gchar *str);
virtual void undo_set_string(void);
virtual gchar *get_string(void);
@@ -108,8 +130,18 @@ public:
};
class QRegisterTable : public RBTree {
+ bool must_undo;
+
public:
- QRegisterTable() : RBTree() {}
+ QRegisterTable(bool _undo = true) : RBTree(), must_undo(_undo) {}
+
+ inline QRegister *
+ insert(QRegister *reg)
+ {
+ reg->must_undo = must_undo;
+ RBTree::insert(reg);
+ return reg;
+ }
inline void
initialize(const gchar *name)