From 0dfb113b47d958093e6ae086c9695e5be83b24b8 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Sun, 28 Jun 2026 02:35:17 +0200 Subject: teco_globber_t is ported from GRegex to terex It's now a private struct, so we can include the regex_t wihout having to draw in the terex headers everywhere. --- src/glob.c | 76 +++++++++++++++++++++++++++++++++++++------------------------- src/glob.h | 14 ++++-------- src/ring.c | 6 ++--- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/glob.c b/src/glob.c index d15f601..0917e5c 100644 --- a/src/glob.c +++ b/src/glob.c @@ -25,6 +25,10 @@ #include #include +/* should always be from contrib/terex */ +#include +#include + #include "sciteco.h" #include "string-utils.h" #include "file-utils.h" @@ -40,14 +44,25 @@ static teco_state_t teco_state_glob_filename; +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(regex_t, tere_free); + +static void teco_globber_compile_pattern(regex_t *pattern_compiled, const gchar *pattern); + +struct teco_globber_t { + GFileTest test; + gchar *dirname; + GDir *dir; + regex_t pattern; +}; + /** @memberof teco_globber_t */ -void -teco_globber_init(teco_globber_t *ctx, const gchar *pattern, GFileTest test) +teco_globber_t * +teco_globber_new(const gchar *pattern, GFileTest test) { if (!pattern) pattern = ""; - memset(ctx, 0, sizeof(*ctx)); + teco_globber_t *ctx = g_new0(teco_globber_t, 1); ctx->test = test; /* @@ -65,7 +80,9 @@ teco_globber_init(teco_globber_t *ctx, const gchar *pattern, GFileTest test) ctx->dir = g_dir_open(*ctx->dirname ? ctx->dirname : ".", 0, NULL); /* if dirname does not exist, the result may be NULL */ - ctx->pattern = teco_globber_compile_pattern(pattern + dirname_len); + teco_globber_compile_pattern(&ctx->pattern, pattern + dirname_len); + + return ctx; } /** @memberof teco_globber_t */ @@ -78,7 +95,8 @@ teco_globber_next(teco_globber_t *ctx) return NULL; while ((basename = g_dir_read_name(ctx->dir))) { - if (!g_regex_match(ctx->pattern, basename, 0, NULL)) + gint rc = tere_exec(&ctx->pattern, (chr *)basename, strlen(basename), NULL, 0, NULL, 0); + if (rc != REG_OKAY) continue; /* @@ -102,13 +120,13 @@ teco_globber_next(teco_globber_t *ctx) /** @memberof teco_globber_t */ void -teco_globber_clear(teco_globber_t *ctx) +teco_globber_free(teco_globber_t *ctx) { - if (ctx->pattern) - g_regex_unref(ctx->pattern); + tere_free(&ctx->pattern); if (ctx->dir) g_dir_close(ctx->dir); g_free(ctx->dirname); + g_free(ctx); } /** @static @memberof teco_globber_t */ @@ -163,7 +181,7 @@ teco_globber_escape_pattern(const gchar *pattern) /** * Compile a fnmatch(3)-compatible glob pattern to - * a PCRE regular expression. + * a terex regular expression. * * There is GPattern, but it only supports the * "*" and "?" wildcards which most importantly @@ -175,8 +193,8 @@ teco_globber_escape_pattern(const gchar *pattern) * * @static @memberof teco_globber_t */ -GRegex * -teco_globber_compile_pattern(const gchar *pattern) +static void +teco_globber_compile_pattern(regex_t *pattern_compiled, const gchar *pattern) { enum { STATE_WILDCARD, @@ -195,7 +213,7 @@ teco_globber_compile_pattern(const gchar *pattern) * might be arbitrary user input and we must avoid * stack overflows at all costs. */ - g_autofree gchar *pattern_regex = g_malloc(strlen(pattern)*2 + 1 + 1); + g_autofree gchar *pattern_regex = g_malloc(strlen(pattern)*2 + 1); gchar *pout = pattern_regex; while (*pattern) { @@ -264,14 +282,14 @@ teco_globber_compile_pattern(const gchar *pattern) /* * fnmatch(3) allows the closing bracket as the * first character to include it in the set, while - * PCRE requires it to be escaped. + * ARE requires it to be escaped. */ if (state == STATE_CLASS) { state = STATE_WILDCARD; *pout++ = ']'; break; } - /* fall through: escape PCRE metacharacters */ + /* fall through: escape ARE metacharacters */ case '\\': case '[': *pout++ = '\\'; @@ -287,17 +305,15 @@ teco_globber_compile_pattern(const gchar *pattern) pattern++; } *pout++ = '$'; - *pout = '\0'; - GRegex *pattern_compiled = g_regex_new(pattern_regex, - G_REGEX_DOTALL | G_REGEX_ANCHORED, 0, NULL); + G_GNUC_UNUSED gint rc; + rc = tere_comp(pattern_compiled, (chr *)pattern_regex, pout-pattern_regex, + REG_ADVANCED | REG_BOSONLY); /* * Since the regex is generated from patterns that are * always valid, there must be no syntactic error. */ - g_assert(pattern_compiled != NULL); - - return pattern_compiled; + g_assert(rc == REG_OKAY); } /* @@ -505,10 +521,11 @@ teco_state_glob_filename_done(teco_machine_main_t *ctx, teco_string_t str, GErro * Match pattern against provided file name */ g_autofree gchar *filename = teco_file_expand_path(str.data); - g_autoptr(GRegex) pattern = teco_globber_compile_pattern(pattern_str.data); + g_auto(regex_t) pattern; + teco_globber_compile_pattern(&pattern, pattern_str.data); - if (g_regex_match(pattern, filename, 0, NULL) && - (teco_test_mode == 0 || g_file_test(filename, file_flags))) { + gint rc = tere_exec(&pattern, (chr *)filename, strlen(filename), NULL, 0, NULL, 0); + if (rc == REG_OKAY && (teco_test_mode == 0 || g_file_test(filename, file_flags))) { if (!colon_modified) { sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0); @@ -534,10 +551,9 @@ teco_state_glob_filename_done(teco_machine_main_t *ctx, teco_string_t str, GErro * Match pattern against directory contents (globbing), * returning TECO_SUCCESS if at least one file matches */ - g_auto(teco_globber_t) globber; - - teco_globber_init(&globber, pattern_str.data, file_flags); - g_autofree gchar *globbed_filename = teco_globber_next(&globber); + g_autoptr(teco_globber_t) globber; + globber = teco_globber_new(pattern_str.data, file_flags); + g_autofree gchar *globbed_filename = teco_globber_next(globber); matching = globbed_filename != NULL; } else { @@ -545,8 +561,8 @@ teco_state_glob_filename_done(teco_machine_main_t *ctx, teco_string_t str, GErro * Match pattern against directory contents (globbing), * inserting all matching file names (null-byte-terminated) */ - g_auto(teco_globber_t) globber; - teco_globber_init(&globber, pattern_str.data, file_flags); + g_autoptr(teco_globber_t) globber; + globber = teco_globber_new(pattern_str.data, file_flags); sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0); teco_undo_int(teco_ranges[0].from) = teco_interface_bytes2glyphs(pos); @@ -554,7 +570,7 @@ teco_state_glob_filename_done(teco_machine_main_t *ctx, teco_string_t str, GErro teco_interface_ssm(SCI_BEGINUNDOACTION, 0, 0); gchar *globbed_filename; - while ((globbed_filename = teco_globber_next(&globber))) { + while ((globbed_filename = teco_globber_next(globber))) { gsize len = strlen(globbed_filename); pos += len+1; diff --git a/src/glob.h b/src/glob.h index 995437c..0da32b5 100644 --- a/src/glob.h +++ b/src/glob.h @@ -23,18 +23,13 @@ #include "sciteco.h" #include "parser.h" -typedef struct { - GFileTest test; - gchar *dirname; - GDir *dir; - GRegex *pattern; -} teco_globber_t; +typedef struct teco_globber_t teco_globber_t; -void teco_globber_init(teco_globber_t *ctx, const gchar *pattern, GFileTest test); +teco_globber_t *teco_globber_new(const gchar *pattern, GFileTest test); gchar *teco_globber_next(teco_globber_t *ctx); -void teco_globber_clear(teco_globber_t *ctx); +void teco_globber_free(teco_globber_t *ctx); -G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(teco_globber_t, teco_globber_clear); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(teco_globber_t, teco_globber_free); /** @static @memberof teco_globber_t */ static inline gboolean @@ -44,7 +39,6 @@ teco_globber_is_pattern(const gchar *str) } gchar *teco_globber_escape_pattern(const gchar *pattern); -GRegex *teco_globber_compile_pattern(const gchar *pattern); /* in cmdline.c */ gboolean teco_state_expectglob_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, diff --git a/src/ring.c b/src/ring.c index 9feb444..548173b 100644 --- a/src/ring.c +++ b/src/ring.c @@ -574,11 +574,11 @@ teco_state_edit_file_done(teco_machine_main_t *ctx, teco_string_t str, GError ** g_autofree gchar *filename = teco_file_expand_path(str.data); if (teco_globber_is_pattern(filename)) { - g_auto(teco_globber_t) globber; - teco_globber_init(&globber, filename, G_FILE_TEST_IS_REGULAR); + g_autoptr(teco_globber_t) globber; + globber = teco_globber_new(filename, G_FILE_TEST_IS_REGULAR); gchar *globbed_filename; - while ((globbed_filename = teco_globber_next(&globber))) { + while ((globbed_filename = teco_globber_next(globber))) { gboolean rc = teco_current_doc_undo_edit(error) && teco_ring_edit(globbed_filename, error); g_free(globbed_filename); -- cgit v1.2.3