mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-regexp: prefix exposed engine entry points with mrb_re_
The Pike VM and pattern compiler were exporting bare names like `re_compile`, `re_exec`, `re_free`, `re_is_word_char`, `re_utf8_charlen`, `re_utf8_decode`. `re_exec` in particular collides with the obsolete BSD libc function of the same name (still present on FreeBSD/NetBSD base), so embedding mruby alongside platform regex could surface a link-time symbol clash. Rename all six entry points to `mrb_re_*` to keep the gem's external symbols inside mruby's namespace. Source file names and the public header path are unchanged. Refs #6858. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -76,7 +76,7 @@ typedef struct mrb_regexp_pattern {
|
||||
uint8_t first_bytes[16]; /* bitmap of possible first bytes (128-bit, ASCII) */
|
||||
mrb_bool has_first_bytes; /* true if first_bytes is usable for skipping */
|
||||
mrb_bool is_literal; /* true if pattern is pure literal (no metacharacters) */
|
||||
/* Cached VM state for pike_vm (avoids malloc per re_exec call) */
|
||||
/* Cached VM state for pike_vm (avoids malloc per mrb_re_exec call) */
|
||||
uint32_t *cached_visited; /* generation-based visited array */
|
||||
void *cached_threads[2]; /* curr/next thread lists */
|
||||
int cached_list_capa; /* capacity of cached thread lists */
|
||||
@@ -113,21 +113,21 @@ typedef struct {
|
||||
} re_thread_cache;
|
||||
|
||||
/* Compile a pattern string into bytecode */
|
||||
mrb_regexp_pattern* re_compile(mrb_state *mrb, const char *pattern, mrb_int len, uint32_t flags);
|
||||
mrb_regexp_pattern* mrb_re_compile(mrb_state *mrb, const char *pattern, mrb_int len, uint32_t flags);
|
||||
|
||||
/* Free a compiled pattern */
|
||||
void re_free(mrb_state *mrb, mrb_regexp_pattern *pat);
|
||||
void mrb_re_free(mrb_state *mrb, mrb_regexp_pattern *pat);
|
||||
|
||||
/* Execute a match.
|
||||
Returns number of captures filled (0 = no match).
|
||||
captures[2*n] = start, captures[2*n+1] = end for group n. */
|
||||
int re_exec(mrb_state *mrb, const mrb_regexp_pattern *pat,
|
||||
int mrb_re_exec(mrb_state *mrb, const mrb_regexp_pattern *pat,
|
||||
const char *str, mrb_int len, mrb_int start,
|
||||
int *captures, int captures_size);
|
||||
|
||||
/* UTF-8 helpers */
|
||||
int re_utf8_charlen(const char *s, const char *end);
|
||||
uint32_t re_utf8_decode(const char *s, int *len);
|
||||
mrb_bool re_is_word_char(uint32_t c);
|
||||
int mrb_re_utf8_charlen(const char *s, const char *end);
|
||||
uint32_t mrb_re_utf8_decode(const char *s, int *len);
|
||||
mrb_bool mrb_re_is_word_char(uint32_t c);
|
||||
|
||||
#endif /* MRB_RE_INTERNAL_H */
|
||||
|
||||
@@ -183,7 +183,7 @@ class_add_shorthand(re_charclass *cc, int ch)
|
||||
break;
|
||||
case 'W':
|
||||
for (int i = 0; i < 128; i++) {
|
||||
if (!re_is_word_char(i)) class_set_bit(cc, (uint8_t)i);
|
||||
if (!mrb_re_is_word_char(i)) class_set_bit(cc, (uint8_t)i);
|
||||
}
|
||||
cc->utf8_any = TRUE;
|
||||
break;
|
||||
@@ -857,7 +857,7 @@ compute_first_set(const re_inst *code, uint32_t code_len,
|
||||
}
|
||||
|
||||
mrb_regexp_pattern*
|
||||
re_compile(mrb_state *mrb, const char *pattern, mrb_int len, uint32_t flags)
|
||||
mrb_re_compile(mrb_state *mrb, const char *pattern, mrb_int len, uint32_t flags)
|
||||
{
|
||||
re_compiler c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
@@ -984,7 +984,7 @@ re_compile(mrb_state *mrb, const char *pattern, mrb_int len, uint32_t flags)
|
||||
}
|
||||
|
||||
void
|
||||
re_free(mrb_state *mrb, mrb_regexp_pattern *pat)
|
||||
mrb_re_free(mrb_state *mrb, mrb_regexp_pattern *pat)
|
||||
{
|
||||
if (pat) {
|
||||
mrb_free(mrb, pat->code);
|
||||
|
||||
@@ -170,16 +170,16 @@ add_thread(pike_state *s, re_threadlist *list,
|
||||
|
||||
case RE_WBOUND:
|
||||
{
|
||||
mrb_bool before = (sp > s->str) && re_is_word_char((uint8_t)sp[-1]);
|
||||
mrb_bool after = (sp < s->str_end) && re_is_word_char((uint8_t)*sp);
|
||||
mrb_bool before = (sp > s->str) && mrb_re_is_word_char((uint8_t)sp[-1]);
|
||||
mrb_bool after = (sp < s->str_end) && mrb_re_is_word_char((uint8_t)*sp);
|
||||
if (before != after) { pc++; continue; }
|
||||
}
|
||||
return;
|
||||
|
||||
case RE_NWBOUND:
|
||||
{
|
||||
mrb_bool before = (sp > s->str) && re_is_word_char((uint8_t)sp[-1]);
|
||||
mrb_bool after = (sp < s->str_end) && re_is_word_char((uint8_t)*sp);
|
||||
mrb_bool before = (sp > s->str) && mrb_re_is_word_char((uint8_t)sp[-1]);
|
||||
mrb_bool after = (sp < s->str_end) && mrb_re_is_word_char((uint8_t)*sp);
|
||||
if (before == after) { pc++; continue; }
|
||||
}
|
||||
return;
|
||||
@@ -301,7 +301,7 @@ pike_vm(mrb_state *mrb, const mrb_regexp_pattern *pat,
|
||||
next.count = 0;
|
||||
|
||||
int ch = (uint8_t)*sp;
|
||||
int advance = re_utf8_charlen(sp, str_end);
|
||||
int advance = mrb_re_utf8_charlen(sp, str_end);
|
||||
|
||||
for (int i = 0; i < curr.count; i++) {
|
||||
re_thread *th = &curr.threads[i];
|
||||
@@ -404,22 +404,22 @@ bt_match(const mrb_regexp_pattern *pat, const char *str, const char *str_end,
|
||||
|
||||
case RE_ANY:
|
||||
if (sp >= str_end || *sp == '\n') return FALSE;
|
||||
sp += re_utf8_charlen(sp, str_end); pc++;
|
||||
sp += mrb_re_utf8_charlen(sp, str_end); pc++;
|
||||
break;
|
||||
|
||||
case RE_ANY_NL:
|
||||
if (sp >= str_end) return FALSE;
|
||||
sp += re_utf8_charlen(sp, str_end); pc++;
|
||||
sp += mrb_re_utf8_charlen(sp, str_end); pc++;
|
||||
break;
|
||||
|
||||
case RE_CLASS:
|
||||
if (sp >= str_end || !class_match(&pat->classes[inst.a], (uint8_t)*sp)) return FALSE;
|
||||
sp += re_utf8_charlen(sp, str_end); pc++;
|
||||
sp += mrb_re_utf8_charlen(sp, str_end); pc++;
|
||||
break;
|
||||
|
||||
case RE_NCLASS:
|
||||
if (sp >= str_end || class_match(&pat->classes[inst.a], (uint8_t)*sp)) return FALSE;
|
||||
sp += re_utf8_charlen(sp, str_end); pc++;
|
||||
sp += mrb_re_utf8_charlen(sp, str_end); pc++;
|
||||
break;
|
||||
|
||||
case RE_MATCH:
|
||||
@@ -473,8 +473,8 @@ bt_match(const mrb_regexp_pattern *pat, const char *str, const char *str_end,
|
||||
|
||||
case RE_WBOUND:
|
||||
{
|
||||
mrb_bool before = (sp > str) && re_is_word_char((uint8_t)sp[-1]);
|
||||
mrb_bool after = (sp < str_end) && re_is_word_char((uint8_t)*sp);
|
||||
mrb_bool before = (sp > str) && mrb_re_is_word_char((uint8_t)sp[-1]);
|
||||
mrb_bool after = (sp < str_end) && mrb_re_is_word_char((uint8_t)*sp);
|
||||
if (before == after) return FALSE;
|
||||
}
|
||||
pc++;
|
||||
@@ -482,8 +482,8 @@ bt_match(const mrb_regexp_pattern *pat, const char *str, const char *str_end,
|
||||
|
||||
case RE_NWBOUND:
|
||||
{
|
||||
mrb_bool before = (sp > str) && re_is_word_char((uint8_t)sp[-1]);
|
||||
mrb_bool after = (sp < str_end) && re_is_word_char((uint8_t)*sp);
|
||||
mrb_bool before = (sp > str) && mrb_re_is_word_char((uint8_t)sp[-1]);
|
||||
mrb_bool after = (sp < str_end) && mrb_re_is_word_char((uint8_t)*sp);
|
||||
if (before != after) return FALSE;
|
||||
}
|
||||
pc++;
|
||||
@@ -611,7 +611,7 @@ literal_exec(const mrb_regexp_pattern *pat,
|
||||
|
||||
/* Public entry point */
|
||||
int
|
||||
re_exec(mrb_state *mrb, const mrb_regexp_pattern *pat,
|
||||
mrb_re_exec(mrb_state *mrb, const mrb_regexp_pattern *pat,
|
||||
const char *str, mrb_int len, mrb_int start,
|
||||
int *captures, int captures_size)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* Return byte length of UTF-8 character at s.
|
||||
Returns 1 for invalid sequences (treat as single byte). */
|
||||
int
|
||||
re_utf8_charlen(const char *s, const char *end)
|
||||
mrb_re_utf8_charlen(const char *s, const char *end)
|
||||
{
|
||||
uint8_t c = (uint8_t)*s;
|
||||
int len;
|
||||
@@ -28,7 +28,7 @@ re_utf8_charlen(const char *s, const char *end)
|
||||
/* Decode a UTF-8 character and return its codepoint.
|
||||
*len is set to the byte length consumed. */
|
||||
uint32_t
|
||||
re_utf8_decode(const char *s, int *len)
|
||||
mrb_re_utf8_decode(const char *s, int *len)
|
||||
{
|
||||
uint8_t c = (uint8_t)s[0];
|
||||
uint32_t cp;
|
||||
@@ -66,7 +66,7 @@ re_utf8_decode(const char *s, int *len)
|
||||
|
||||
/* Check if character is a "word" character (\w): [a-zA-Z0-9_] */
|
||||
mrb_bool
|
||||
re_is_word_char(uint32_t c)
|
||||
mrb_re_is_word_char(uint32_t c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z') return TRUE;
|
||||
if (c >= 'A' && c <= 'Z') return TRUE;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
/* Regexp data type */
|
||||
static void regexp_free(mrb_state *mrb, void *ptr) {
|
||||
re_free(mrb, (mrb_regexp_pattern*)ptr);
|
||||
mrb_re_free(mrb, (mrb_regexp_pattern*)ptr);
|
||||
}
|
||||
|
||||
static const struct mrb_data_type regexp_type = { "Regexp", regexp_free };
|
||||
@@ -107,13 +107,13 @@ regexp_init(mrb_state *mrb, mrb_value self)
|
||||
flags = parse_flags(mrb, flags_val);
|
||||
}
|
||||
|
||||
/* Set @source and @flags before re_compile() so a Regexp that survives
|
||||
/* Set @source and @flags before mrb_re_compile() so a Regexp that survives
|
||||
a compile-time exception (e.g. picked up by ObjectSpace.each_object)
|
||||
still has usable IVs for hash/eql?/inspect. */
|
||||
mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@source"), pattern);
|
||||
mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@flags"), mrb_int_value(mrb, (mrb_int)flags));
|
||||
|
||||
pat = re_compile(mrb, RSTRING_PTR(pattern), RSTRING_LEN(pattern), flags);
|
||||
pat = mrb_re_compile(mrb, RSTRING_PTR(pattern), RSTRING_LEN(pattern), flags);
|
||||
|
||||
DATA_TYPE(self) = ®exp_type;
|
||||
DATA_PTR(self) = pat;
|
||||
@@ -206,7 +206,7 @@ exec_match(mrb_state *mrb, mrb_value self, mrb_value str, mrb_int pos)
|
||||
int cap_size = pat->num_captures * 2;
|
||||
int *captures = (int*)mrb_malloc(mrb, sizeof(int) * cap_size);
|
||||
memset(captures, -1, sizeof(int) * cap_size);
|
||||
int ncap = re_exec(mrb, pat, RSTRING_PTR(str), RSTRING_LEN(str), pos,
|
||||
int ncap = mrb_re_exec(mrb, pat, RSTRING_PTR(str), RSTRING_LEN(str), pos,
|
||||
captures, cap_size);
|
||||
|
||||
if (ncap == 0) {
|
||||
@@ -244,7 +244,7 @@ regexp_match_p(mrb_state *mrb, mrb_value self)
|
||||
mrb_regexp_pattern *pat = DATA_GET_PTR(mrb, self, ®exp_type, mrb_regexp_pattern);
|
||||
if (!pat) mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized Regexp");
|
||||
|
||||
int ncap = re_exec(mrb, pat, RSTRING_PTR(str), RSTRING_LEN(str), pos, NULL, 0);
|
||||
int ncap = mrb_re_exec(mrb, pat, RSTRING_PTR(str), RSTRING_LEN(str), pos, NULL, 0);
|
||||
return mrb_bool_value(ncap > 0);
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ regexp_case_match(mrb_state *mrb, mrb_value self)
|
||||
pat = DATA_GET_PTR(mrb, self, ®exp_type, mrb_regexp_pattern);
|
||||
if (!pat) return mrb_false_value();
|
||||
|
||||
int ncap = re_exec(mrb, pat, RSTRING_PTR(str), RSTRING_LEN(str), 0, NULL, 0);
|
||||
int ncap = mrb_re_exec(mrb, pat, RSTRING_PTR(str), RSTRING_LEN(str), 0, NULL, 0);
|
||||
return mrb_bool_value(ncap > 0);
|
||||
}
|
||||
|
||||
@@ -726,7 +726,7 @@ regexp_gsub_str(mrb_state *mrb, mrb_value self)
|
||||
|
||||
while (pos <= slen) {
|
||||
memset(captures, -1, sizeof(int) * cap_size);
|
||||
int n = re_exec(mrb, pat, s, slen, pos, captures, cap_size);
|
||||
int n = mrb_re_exec(mrb, pat, s, slen, pos, captures, cap_size);
|
||||
if (n == 0) break;
|
||||
|
||||
/* save last match for $~ */
|
||||
@@ -800,7 +800,7 @@ regexp_sub_str(mrb_state *mrb, mrb_value self)
|
||||
int *captures = (int*)mrb_malloc(mrb, sizeof(int) * cap_size);
|
||||
memset(captures, -1, sizeof(int) * cap_size);
|
||||
|
||||
int n = re_exec(mrb, pat, s, slen, 0, captures, cap_size);
|
||||
int n = mrb_re_exec(mrb, pat, s, slen, 0, captures, cap_size);
|
||||
if (n == 0) {
|
||||
mrb_free(mrb, captures);
|
||||
clear_match_globals(mrb);
|
||||
@@ -858,7 +858,7 @@ regexp_scan(mrb_state *mrb, mrb_value self)
|
||||
|
||||
while (pos <= slen) {
|
||||
memset(captures, -1, sizeof(int) * cap_size);
|
||||
int n = re_exec(mrb, pat, s, slen, pos, captures, cap_size);
|
||||
int n = mrb_re_exec(mrb, pat, s, slen, pos, captures, cap_size);
|
||||
if (n == 0) break;
|
||||
|
||||
last_ncap = cap_size;
|
||||
|
||||
@@ -381,7 +381,7 @@ assert("MatchData#named_captures") do
|
||||
end
|
||||
|
||||
assert("Regexp - named captures survive /x preprocessing") do
|
||||
# Regression: with /x, re_compile freed the stripped buffer that
|
||||
# Regression: with /x, mrb_re_compile freed the stripped buffer that
|
||||
# named_captures[i].name pointed into.
|
||||
re = /(?<n>\d+) # comment
|
||||
\s* (?<u>\w+) /x
|
||||
|
||||
Reference in New Issue
Block a user