aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/parser.h5
-rw-r--r--src/qreg.h2
-rw-r--r--src/search.c43
-rw-r--r--tests/testsuite.at4
4 files changed, 33 insertions, 21 deletions
diff --git a/src/parser.h b/src/parser.h
index 659e9f9..53eb76b 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -301,8 +301,9 @@ teco_machine_init(teco_machine_t *ctx, teco_state_t *initial, gboolean must_undo
static inline void
teco_machine_reset(teco_machine_t *ctx, teco_state_t *initial)
{
- if (ctx->current != initial)
- teco_undo_ptr(ctx->current) = initial;
+ if (ctx->must_undo && ctx->current != initial)
+ teco_undo_ptr(ctx->current);
+ ctx->current = initial;
}
gboolean teco_machine_input(teco_machine_t *ctx, gunichar chr, GError **error);
diff --git a/src/qreg.h b/src/qreg.h
index 59cf2cc..e9a9b1b 100644
--- a/src/qreg.h
+++ b/src/qreg.h
@@ -241,6 +241,8 @@ gboolean teco_machine_qregspec_auto_complete(teco_machine_qregspec_t *ctx, teco_
void teco_machine_qregspec_free(teco_machine_qregspec_t *ctx);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(teco_machine_qregspec_t, teco_machine_qregspec_free);
+
/** @memberof teco_machine_qregspec_t */
void undo__teco_machine_qregspec_free(teco_machine_qregspec_t *);
TECO_DECLARE_UNDO_OBJECT(qregspec, teco_machine_qregspec_t *);
diff --git a/src/search.c b/src/search.c
index 0dea20c..07a5154 100644
--- a/src/search.c
+++ b/src/search.c
@@ -52,8 +52,6 @@ TECO_DEFINE_UNDO_OBJECT_OWN(parameters, teco_search_parameters_t, /* don't delet
*/
static teco_search_parameters_t teco_search_parameters;
-static teco_machine_qregspec_t *teco_search_qreg_machine = NULL;
-
static gboolean
teco_state_search_initial(teco_machine_main_t *ctx, GError **error)
{
@@ -63,10 +61,6 @@ teco_state_search_initial(teco_machine_main_t *ctx, GError **error)
teco_machine_stringbuilding_set_codepage(&ctx->expectstring.machine,
teco_interface_get_codepage());
- if (G_UNLIKELY(!teco_search_qreg_machine))
- teco_search_qreg_machine = teco_machine_qregspec_new(TECO_QREG_REQUIRED, ctx->qreg_table_locals,
- ctx->parent.must_undo);
-
teco_undo_object_parameters_push(&teco_search_parameters);
teco_search_parameters.dot = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
@@ -139,6 +133,7 @@ typedef enum {
* The pointer is modified and always left after
* the last character used, so it may point to the
* terminating null byte after the call.
+ * @param qreg_machine State machine for parsing Q-Regs (^EGq).
* @param codepage The codepage of pattern.
* @param escape_default Whether to treat single characters
* as classes or not.
@@ -154,6 +149,7 @@ typedef enum {
*/
static gchar *
teco_class2regexp(teco_search_state_t *state, teco_string_t *pattern,
+ teco_machine_qregspec_t *qreg_machine,
guint codepage, gboolean escape_default, GError **error)
{
while (pattern->len > 0) {
@@ -250,7 +246,7 @@ teco_class2regexp(teco_search_state_t *state, teco_string_t *pattern,
len = 1;
chr = *pattern->data;
}
- switch (teco_machine_qregspec_input(teco_search_qreg_machine,
+ switch (teco_machine_qregspec_input(qreg_machine,
chr, &reg, NULL, error)) {
case TECO_MACHINE_QREGSPEC_ERROR:
return NULL;
@@ -262,7 +258,7 @@ teco_class2regexp(teco_search_state_t *state, teco_string_t *pattern,
continue;
case TECO_MACHINE_QREGSPEC_DONE:
- teco_machine_qregspec_reset(teco_search_qreg_machine);
+ teco_machine_qregspec_reset(qreg_machine);
g_auto(teco_string_t) str = {NULL, 0};
if (!reg->vtable->get_string(reg, &str.data, &str.len, NULL, error))
@@ -308,6 +304,7 @@ teco_class2regexp(teco_search_state_t *state, teco_string_t *pattern,
* successfully scanned character, so it can be
* called recursively. It may also point to the
* terminating null byte after the call.
+ * @param qreg_machine State machine for parsing Q-Regs (^EGq).
* @param codepage The codepage of pattern.
* @param single_expr Whether to scan a single pattern
* expression or an arbitrary sequence.
@@ -316,7 +313,8 @@ teco_class2regexp(teco_search_state_t *state, teco_string_t *pattern,
* Must be freed with g_free().
*/
static gchar *
-teco_pattern2regexp(teco_string_t *pattern, guint codepage, gboolean single_expr, GError **error)
+teco_pattern2regexp(teco_string_t *pattern, teco_machine_qregspec_t *qreg_machine,
+ guint codepage, gboolean single_expr, GError **error)
{
teco_search_state_t state = TECO_SEARCH_STATE_START;
g_auto(teco_string_t) re = {NULL, 0};
@@ -340,7 +338,9 @@ teco_pattern2regexp(teco_string_t *pattern, guint codepage, gboolean single_expr
* as classes, so we do not convert them to regexp
* classes unnecessarily.
*/
- g_autofree gchar *temp = teco_class2regexp(&state, pattern, codepage, FALSE, error);
+ g_autofree gchar *temp;
+ temp = teco_class2regexp(&state, pattern, qreg_machine,
+ codepage, FALSE, error);
if (!temp)
return NULL;
@@ -395,7 +395,9 @@ teco_pattern2regexp(teco_string_t *pattern, guint codepage, gboolean single_expr
case TECO_SEARCH_STATE_NOT: {
state = TECO_SEARCH_STATE_START;
- g_autofree gchar *temp = teco_class2regexp(&state, pattern, codepage, TRUE, error);
+ g_autofree gchar *temp;
+ temp = teco_class2regexp(&state, pattern, qreg_machine,
+ codepage, TRUE, error);
if (!temp)
return NULL;
if (!*temp)
@@ -431,7 +433,9 @@ teco_pattern2regexp(teco_string_t *pattern, guint codepage, gboolean single_expr
case TECO_SEARCH_STATE_MANY: {
/* consume exactly one pattern element */
- g_autofree gchar *temp = teco_pattern2regexp(pattern, codepage, TRUE, error);
+ g_autofree gchar *temp;
+ temp = teco_pattern2regexp(pattern, qreg_machine,
+ codepage, TRUE, error);
if (!temp)
return NULL;
if (!*temp)
@@ -457,7 +461,9 @@ teco_pattern2regexp(teco_string_t *pattern, guint codepage, gboolean single_expr
state = TECO_SEARCH_STATE_START;
break;
default: {
- g_autofree gchar *temp = teco_pattern2regexp(pattern, codepage, TRUE, error);
+ g_autofree gchar *temp;
+ temp = teco_pattern2regexp(pattern, qreg_machine,
+ codepage, TRUE, error);
if (!temp)
return NULL;
if (!*temp)
@@ -620,14 +626,17 @@ teco_state_search_process(teco_machine_main_t *ctx, const teco_string_t *str, gs
!search_reg->vtable->set_integer(search_reg, TECO_FAILURE, error))
return FALSE;
+ g_autoptr(teco_machine_qregspec_t) qreg_machine;
+ qreg_machine = teco_machine_qregspec_new(TECO_QREG_REQUIRED, ctx->qreg_table_locals, FALSE);
+
g_autoptr(GRegex) re = NULL;
teco_string_t pattern = *str;
g_autofree gchar *re_pattern;
/* NOTE: teco_pattern2regexp() modifies str pointer */
- re_pattern = teco_pattern2regexp(&pattern, ctx->expectstring.machine.codepage, FALSE, error);
+ re_pattern = teco_pattern2regexp(&pattern, qreg_machine,
+ ctx->expectstring.machine.codepage, FALSE, error);
if (!re_pattern)
return FALSE;
- teco_machine_qregspec_reset(teco_search_qreg_machine);
#ifdef DEBUG
g_printf("REGEXP: %s\n", re_pattern);
#endif
@@ -833,10 +842,6 @@ teco_state_search_all_initial(teco_machine_main_t *ctx, GError **error)
teco_machine_stringbuilding_set_codepage(&ctx->expectstring.machine,
teco_interface_get_codepage());
- if (G_UNLIKELY(!teco_search_qreg_machine))
- teco_search_qreg_machine = teco_machine_qregspec_new(TECO_QREG_REQUIRED, ctx->qreg_table_locals,
- ctx->parent.must_undo);
-
teco_undo_object_parameters_push(&teco_search_parameters);
teco_search_parameters.dot = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0);
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 3770bbe..30ae985 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -182,6 +182,10 @@ AT_SETUP([Search for one of characters in uninitialized Q-Register])
AT_CHECK([$SCITECO -e ":@S/^EGa/\"S(0/0)'"], 0, ignore, ignore)
AT_CLEANUP
+AT_SETUP([Search accesses wrong Q-Register table])
+AT_CHECK([$SCITECO -e '@^U.#xx/123/ @^Um{:@S/^EG.#xx/$} :Mm Mm'], 1, ignore, ignore)
+AT_CLEANUP
+
AT_SETUP([Memory limiting during spawning])
# This might result in an OOM if memory limiting is not working
AT_CHECK([$SCITECO -e "50*1000*1000,2EJ 0,128ED @EC'dd if=/dev/zero'"], 1, ignore, ignore)