diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-04-13 00:40:37 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-04-13 01:33:43 +0300 |
commit | 628c73d984fd7663607cc3fd9368f809855906fd (patch) | |
tree | bf9922ec94bbce2df19ef146724bbfe124138998 /src/search.c | |
parent | 3b06b44fc22cd5c936dd3ce677290e3f65f7f8ce (diff) | |
download | sciteco-628c73d984fd7663607cc3fd9368f809855906fd.tar.gz |
fixed undoing bitfields on Windows
* It turns out that `bool` (_Bool) in bitfields may cause
padding to the next 32-bit word.
This was only observed on MinGW.
I am not entirely sure why, although the C standard does
not guarantee much with regard to bitfield memory layout
and there are 64-bit available due to passing anyway.
Actually, they could also be layed out in a different order.
* I am now consistently using guint instead of `bool` in bitfields
to prevent any potential surprises.
* The way that guint was aliased with bitfield structs
for undoing teco_machine_main_t and teco_machine_qregspec_t flags
was therefore insecure.
It was not guaranteed that the __flags field really "captures"
all of the bit field.
Even with `guint v : 1` fields, this was not guaranteed.
We would have required a static assertion for robustness.
Alternatively, we could have declared a `gsize __flags` variable
as well. This __should__ be safe since gsize should always be
pointer sized and correspond to the platform's alignment.
However, it's also not 100% guaranteed.
Using classic ANSI C enums with bit operations to encode multiple
fields and flags into a single integer also doesn't look very
attractive.
* Instead, we now define scalar types with their own teco_undo_push()
shortcuts for the bitfield structs.
This is in one way simpler and much more robust, but on the other
hand complicates access to the flag variables.
* It's a good question whether a `struct __attribute__((packed))` bitfield
with guint fields would be a reliable replacement for flag enums, that
are communicated with the "outside" (TECO) world.
I am not going to risk it until GCC gives any guarantees, though.
For the time being, bitfields are only used internally where
the concrete memory layout (bit positions) is not crucial.
* This fixes the test suite and therefore probably CI and nightly
builds on Windows.
* Test case: Rub out `@I//` or `@Xq` until before the `@`.
The parser doesn't know that `@` is still set and allows
all sorts of commands where `@` should be forbidden.
* It's unknown how long this has been broken on Windows - quite
possibly since v2.0.
Diffstat (limited to 'src/search.c')
-rw-r--r-- | src/search.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/src/search.c b/src/search.c index 13fb135..7fcf10e 100644 --- a/src/search.c +++ b/src/search.c @@ -97,7 +97,7 @@ teco_state_control_search_mode(teco_machine_main_t *ctx, GError **error) static gboolean teco_state_search_initial(teco_machine_main_t *ctx, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL) + if (ctx->flags.mode > TECO_MODE_NORMAL) return TRUE; teco_machine_stringbuilding_set_codepage(&ctx->expectstring.machine, @@ -691,7 +691,7 @@ teco_state_search_process(teco_machine_main_t *ctx, const teco_string_t *str, gs if (teco_is_failure(search_mode)) flags |= G_REGEX_CASELESS; - if (ctx->modifier_colon == 2) + if (ctx->flags.modifier_colon == 2) flags |= G_REGEX_ANCHORED; /* this is set in teco_state_search_initial() */ @@ -813,7 +813,7 @@ failure: static teco_state_t * teco_state_search_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL) + if (ctx->flags.mode > TECO_MODE_NORMAL) return &teco_state_start; teco_qreg_t *search_reg = teco_qreg_table_find(&teco_qreg_table_globals, "_", 1); @@ -943,7 +943,7 @@ TECO_DEFINE_STATE_SEARCH(teco_state_search); static gboolean teco_state_search_all_initial(teco_machine_main_t *ctx, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL) + if (ctx->flags.mode > TECO_MODE_NORMAL) return TRUE; teco_machine_stringbuilding_set_codepage(&ctx->expectstring.machine, @@ -1000,7 +1000,7 @@ teco_state_search_all_initial(teco_machine_main_t *ctx, GError **error) static teco_state_t * teco_state_search_all_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) { - if (ctx->mode <= TECO_MODE_NORMAL && + if (ctx->flags.mode <= TECO_MODE_NORMAL && (!teco_state_search_done(ctx, str, error) || !teco_ed_hook(TECO_ED_HOOK_EDIT, error))) return NULL; @@ -1060,7 +1060,7 @@ TECO_DEFINE_STATE_SEARCH(teco_state_search_all, static teco_state_t * teco_state_search_kill_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL) + if (ctx->flags.mode > TECO_MODE_NORMAL) return &teco_state_start; teco_qreg_t *search_reg = teco_qreg_table_find(&teco_qreg_table_globals, "_", 1); @@ -1140,7 +1140,7 @@ TECO_DEFINE_STATE_SEARCH(teco_state_search_kill); static teco_state_t * teco_state_search_delete_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL) + if (ctx->flags.mode > TECO_MODE_NORMAL) return &teco_state_start; teco_qreg_t *search_reg = teco_qreg_table_find(&teco_qreg_table_globals, "_", 1); @@ -1183,7 +1183,7 @@ TECO_DEFINE_STATE_SEARCH(teco_state_search_delete); static gboolean teco_state_replace_insert_initial(teco_machine_main_t *ctx, GError **error) { - if (ctx->mode == TECO_MODE_NORMAL) + if (ctx->flags.mode == TECO_MODE_NORMAL) teco_machine_stringbuilding_set_codepage(&ctx->expectstring.machine, teco_interface_get_codepage()); return TRUE; @@ -1210,7 +1210,7 @@ TECO_DEFINE_STATE_EXPECTSTRING(teco_state_replace_ignore); static teco_state_t * teco_state_replace_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL) + if (ctx->flags.mode > TECO_MODE_NORMAL) return &teco_state_replace_ignore; teco_qreg_t *search_reg = teco_qreg_table_find(&teco_qreg_table_globals, "_", 1); @@ -1259,7 +1259,7 @@ TECO_DEFINE_STATE_SEARCH(teco_state_replace, static teco_state_t * teco_state_replace_default_insert_done_overwrite(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL) + if (ctx->flags.mode > TECO_MODE_NORMAL) return &teco_state_start; teco_qreg_t *replace_reg = teco_qreg_table_find(&teco_qreg_table_globals, "-", 1); @@ -1292,7 +1292,7 @@ TECO_DEFINE_STATE_INSERT(teco_state_replace_default_insert, static teco_state_t * teco_state_replace_default_ignore_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL || + if (ctx->flags.mode > TECO_MODE_NORMAL || !str->len) return &teco_state_start; @@ -1315,7 +1315,7 @@ TECO_DEFINE_STATE_EXPECTSTRING(teco_state_replace_default_ignore); static teco_state_t * teco_state_replace_default_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) { - if (ctx->mode > TECO_MODE_NORMAL) + if (ctx->flags.mode > TECO_MODE_NORMAL) return &teco_state_replace_default_ignore; teco_qreg_t *search_reg = teco_qreg_table_find(&teco_qreg_table_globals, "_", 1); |