aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <rhaberkorn@fmsbw.de>2026-06-28 02:35:17 +0200
committerRobin Haberkorn <rhaberkorn@fmsbw.de>2026-06-28 02:35:17 +0200
commit0dfb113b47d958093e6ae086c9695e5be83b24b8 (patch)
tree1fc64bdd464255f2c3d48e045208dfb4524f411f
parent4fe5bc6f3867096965270c90f2e1e5df77b8825f (diff)
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.
-rw-r--r--src/glob.c76
-rw-r--r--src/glob.h14
-rw-r--r--src/ring.c6
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 <glib/gprintf.h>
#include <glib/gstdio.h>
+/* should always be from contrib/terex */
+#include <regalone.h>
+#include <regex.h>
+
#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);