diff options
-rw-r--r-- | src/goto-commands.c | 8 | ||||
-rw-r--r-- | src/lexer.c | 4 | ||||
-rw-r--r-- | src/parser.c | 8 | ||||
-rw-r--r-- | src/parser.h | 22 | ||||
-rw-r--r-- | src/qreg-commands.c | 6 | ||||
-rw-r--r-- | src/view.c | 2 | ||||
-rw-r--r-- | tests/testsuite.at | 10 |
7 files changed, 33 insertions, 27 deletions
diff --git a/src/goto-commands.c b/src/goto-commands.c index a0e6634..72be48e 100644 --- a/src/goto-commands.c +++ b/src/goto-commands.c @@ -39,13 +39,6 @@ TECO_DECLARE_STATE(teco_state_eolcomment); teco_string_t teco_goto_skip_label = {NULL, 0}; -static gboolean -teco_state_label_initial(teco_machine_main_t *ctx, GError **error) -{ - memset(&ctx->goto_label, 0, sizeof(ctx->goto_label)); - return TRUE; -} - /* * NOTE: The comma is theoretically not allowed in a label * (see <O> syntax), but is accepted anyway since labels @@ -108,7 +101,6 @@ teco_state_label_input(teco_machine_main_t *ctx, gunichar chr, GError **error) } TECO_DEFINE_STATE(teco_state_label, - .initial_cb = (teco_state_initial_cb_t)teco_state_label_initial, .style = SCE_SCITECO_LABEL ); diff --git a/src/lexer.c b/src/lexer.c index 6bc696f..2f43b76 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -157,7 +157,9 @@ teco_lexer_step(teco_view_t *view, teco_machine_main_t *machine, * The curly braces will be styled like regular commands. * * FIXME: This works only for top-level macro definitions, - * not for embedded definitions. + * not for nested definitions. + * FIXME: The macrodef_machine's end-of-macro callback could be used + * to detect and highlight an error on the closing `}`. * FIXME: This cannot currently be disabled, not even with SCI_SETPROPERTY. * We could only map it to an ED flag or * rewrite the lexer against the ILexer5 interface, which requires C++. diff --git a/src/parser.c b/src/parser.c index ee705a0..33d2e7f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -81,7 +81,7 @@ teco_machine_input(teco_machine_t *ctx, gunichar chr, GError **error) gboolean teco_state_end_of_macro(teco_machine_t *ctx, GError **error) { - g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, + g_set_error_literal(error, TECO_ERROR, TECO_ERROR_SYNTAX, "Unterminated command"); return FALSE; } @@ -386,7 +386,8 @@ teco_machine_main_clear(teco_machine_main_t *ctx) teco_goto_table_clear(&ctx->goto_table); teco_string_clear(&ctx->expectstring.string); teco_machine_stringbuilding_clear(&ctx->expectstring.machine); - // FIXME: Could leak ctx->goto_label, but it's in an union + teco_string_clear(&ctx->goto_label); + teco_machine_qregspec_free(ctx->expectqreg); } /** Append string to result with case folding. */ @@ -1012,8 +1013,7 @@ teco_machine_stringbuilding_escape(teco_machine_stringbuilding_t *ctx, const gch void teco_machine_stringbuilding_clear(teco_machine_stringbuilding_t *ctx) { - if (ctx->machine_qregspec) - teco_machine_qregspec_free(ctx->machine_qregspec); + teco_machine_qregspec_free(ctx->machine_qregspec); teco_string_clear(&ctx->code); } diff --git a/src/parser.h b/src/parser.h index 36a0302..a1583d2 100644 --- a/src/parser.h +++ b/src/parser.h @@ -514,17 +514,19 @@ struct teco_machine_main_t { /* * teco_state_t-dependent state. * - * Some of these cannot be used concurrently and are therefore - * grouped into unions. - * We could further optimize memory usage by dynamically allocating - * some of these structures on demand. + * Some cannot theoretically be used at the same time + * but it's hard to prevent memory leaks if putting them into + * a common union. */ - teco_machine_expectstring_t expectstring; - union { - teco_string_t goto_label; - teco_machine_qregspec_t *expectqreg; - teco_machine_scintilla_t scintilla; - }; + teco_machine_expectstring_t expectstring; + /** + * State machine for parsing Q-reg specifications. + * This could theoretically be inlined, but it would introduce + * a recursive dependency between qreg.h and parser.h. + */ + teco_machine_qregspec_t *expectqreg; + teco_string_t goto_label; + teco_machine_scintilla_t scintilla; }; typedef struct teco_machine_main_flags_t teco_machine_main_flags_t; diff --git a/src/qreg-commands.c b/src/qreg-commands.c index 7189771..9407e6c 100644 --- a/src/qreg-commands.c +++ b/src/qreg-commands.c @@ -39,8 +39,8 @@ teco_state_expectqreg_initial(teco_machine_main_t *ctx, GError **error) teco_state_t *current = ctx->parent.current; /* - * NOTE: We have to allocate a new instance always since `expectqreg` - * is part of an union. + * NOTE: This could theoretically be allocated once in + * teco_machine_main_init(), but we'd have to set the type here anyway. */ ctx->expectqreg = teco_machine_qregspec_new(current->expectqreg.type, ctx->qreg_table_locals, ctx->parent.must_undo); @@ -69,7 +69,7 @@ teco_state_expectqreg_input(teco_machine_main_t *ctx, gunichar chr, GError **err /* * NOTE: ctx->expectqreg is preserved since we may want to query it from follow-up - * states. This means, it must usually be stored manually in got_register_cb() via: + * states. This means, it must usually be reset manually in got_register_cb() via: * teco_state_expectqreg_reset(ctx); */ return current->expectqreg.got_register_cb(ctx, qreg, table, error); @@ -315,7 +315,7 @@ cleanup: /** * Load file into view's document. - * + * * @param ctx The view to load. * @param filename File name to read * @param clear Whether to completely replace document diff --git a/tests/testsuite.at b/tests/testsuite.at index 8d4daa7..a5fa98e 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -228,6 +228,14 @@ TE_CHECK([[@^Ua{@EQ.x//} Ma @^U.x/FOO/]], 1, ignore, ignore) TE_CHECK([[@^Ua{@EQ.x// Mb Q*U*} Ma]], 0, ignore, ignore) AT_CLEANUP +# This is also for detecting leaks under Valgrind. +AT_SETUP([Unterminated commands]) +TE_CHECK([[G[foo^Q] ]], 1, ignore, ignore) +TE_CHECK([[!foo ]], 1, ignore, ignore) +TE_CHECK([[^Ua ]], 1, ignore, ignore) +TE_CHECK([[EGa ]], 1, ignore, ignore) +AT_CLEANUP + AT_SETUP([Loading files into Q-Registers]) TE_CHECK([[@I/../ @EW/loadqreg.txt/ @EQa/loadqreg.txt/ :Qa-2"N(0/0)']], 0, ignore, ignore) # Does the same as FG..$. Afterwards, the parent directory should be shorter. @@ -409,6 +417,8 @@ TE_CHECK([[@EU$"."]], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Empty help topic]) +# FIXME: Produces a false positive under Valgrind +# due to the value of $SCITECOPATH. TE_CHECK([[@?//]], 1, ignore, ignore) AT_CLEANUP |