use crate::options::{opt_state_get, opt_state_set, optlookup};
use crate::ported::params::{setaparam, setiparam, setsparam};
use crate::ported::utils::zwarnnam;
use crate::ported::zsh_h::{features, module, BASHREMATCH, CASEMATCH, KSHARRAYS};
use crate::zsh_h::isset;
use crate::DPUTS;
use std::sync::{Mutex, OnceLock};
pub const ZREGEX_EXTENDED: i32 = 0;
pub fn zregex_regerrwarn(prefix: &str, err_msg: &str) {
zwarnnam(prefix, err_msg); }
pub fn zcond_regex_match(a: &[&str], id: i32) -> i32 {
if a.len() < 2 {
return 0;
}
let lhstr = a[0]; let rhre = a[1]; let mut return_value: i32 = 0;
if id != ZREGEX_EXTENDED {
DPUTS!(true, "bad regex option"); return 0; }
let casematch = isset(CASEMATCH);
let pat_for_compile = if !casematch {
format!("(?i){}", rhre) } else {
rhre.to_string()
};
if rhre.is_empty() {
crate::regex_module::zregex_regerrwarn(
"-regex-match",
"failed to compile regex: empty (sub)expression",
);
return 0;
}
let re = match regex::RegexBuilder::new(&pat_for_compile)
.dot_matches_new_line(true)
.build()
{
Ok(r) => r,
Err(e) => {
let raw = e.to_string();
let detail = raw
.lines()
.rev()
.find_map(|l| l.trim().strip_prefix("error: "))
.map(|s| s.to_string())
.unwrap_or_else(|| raw.replace('\n', " "));
crate::ported::utils::zwarn(&format!(
"failed to compile regex: {}",
detail
));
return 0; }
};
let captures = match re.captures(lhstr) {
Some(c) => c,
None => return 0, };
return_value = 1; let nsub = re.captures_len() - 1; let bashre = isset(BASHREMATCH);
let ksharr = isset(KSHARRAYS);
let (start, nelem) = if bashre {
(0usize, nsub + 1) } else {
(1usize, nsub) };
let mut arr: Vec<String> = Vec::with_capacity(nelem);
for n in start..=nsub {
if let Some(m) = captures.get(n) {
arr.push(m.as_str().to_string()); } else {
arr.push(String::new());
}
}
if bashre {
setsparam("BASH_REMATCH", &arr.join(":"));
return return_value;
}
let m0 = captures.get(0).expect("regex matched but no group 0");
let full = m0.as_str().to_string(); setsparam("MATCH", &full);
let so = m0.start();
let eo = m0.end();
let mbegin_chars = lhstr[..so].chars().count() as i64; let kshoff: i64 = if ksharr { 0 } else { 1 }; let mbegin = mbegin_chars + kshoff; setiparam("MBEGIN", mbegin);
let match_chars = lhstr[so..eo].chars().count() as i64;
let mend_total = mbegin_chars + match_chars;
let mend = mend_total + kshoff - 1; setiparam("MEND", mend);
if nelem > 0 {
let mut mbegin_arr: Vec<String> = Vec::with_capacity(nelem);
let mut mend_arr: Vec<String> = Vec::with_capacity(nelem);
for n in 0..nelem {
let cap_idx = start + n;
match captures.get(cap_idx) {
Some(m) => {
let beg_chars = lhstr[..m.start()].chars().count() as i64;
let len_chars = lhstr[m.start()..m.end()].chars().count() as i64;
mbegin_arr.push((beg_chars + kshoff).to_string()); mend_arr.push((beg_chars + len_chars + kshoff - 1).to_string());
}
None => {
mbegin_arr.push("-1".to_string());
mend_arr.push("-1".to_string());
}
}
}
setaparam("match", arr.clone());
setaparam("mbegin", mbegin_arr);
setaparam("mend", mend_arr);
}
return_value }
#[allow(unused_variables)]
pub fn setup_(m: *const module) -> i32 {
0
}
pub fn features_(m: *const module, features: &mut Vec<String>) -> i32 {
*features = featuresarray(m, module_features());
0
}
pub fn enables_(m: *const module, enables: &mut Option<Vec<i32>>) -> i32 {
handlefeatures(m, module_features(), enables)
}
#[allow(unused_variables)]
pub fn boot_(m: *const module) -> i32 {
0
}
pub fn cleanup_(m: *const module) -> i32 {
setfeatureenables(m, module_features(), None)
}
#[allow(unused_variables)]
pub fn finish_(m: *const module) -> i32 {
0
}
static MODULE_FEATURES: OnceLock<Mutex<features>> = OnceLock::new();
fn featuresarray(_m: *const module, _f: &Mutex<features>) -> Vec<String> {
vec!["c:regex-match".to_string()]
}
fn handlefeatures(_m: *const module, _f: &Mutex<features>, enables: &mut Option<Vec<i32>>) -> i32 {
if enables.is_none() {
*enables = Some(vec![1; 1]);
}
0
}
fn setfeatureenables(_m: *const module, _f: &Mutex<features>, _e: Option<&[i32]>) -> i32 {
0
}
fn module_features() -> &'static Mutex<features> {
MODULE_FEATURES.get_or_init(|| {
Mutex::new(features {
bn_list: None,
bn_size: 0,
cd_list: None,
cd_size: 1,
mf_list: None,
mf_size: 0,
pd_list: None,
pd_size: 0,
n_abstract: 0,
})
})
}
#[cfg(test)]
mod tests {
use crate::options::{opt_state_get, opt_state_set};
use crate::regex_module::{zcond_regex_match, ZREGEX_EXTENDED};
#[test]
fn match_returns_one() {
let _g = crate::test_util::global_state_lock();
let r = zcond_regex_match(&["hello world", "wor.d"], ZREGEX_EXTENDED);
assert_eq!(r, 1);
}
#[test]
fn captures_returns_one() {
let _g = crate::test_util::global_state_lock();
let r = zcond_regex_match(&["foo=42", "([a-z]+)=([0-9]+)"], ZREGEX_EXTENDED);
assert_eq!(r, 1);
}
#[test]
fn no_match_returns_zero() {
let _g = crate::test_util::global_state_lock();
let r = zcond_regex_match(&["abc", "xyz"], ZREGEX_EXTENDED);
assert_eq!(r, 0);
}
#[test]
fn invalid_pattern_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["anything", "["], ZREGEX_EXTENDED), 0);
}
#[test]
fn missing_args_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&[], ZREGEX_EXTENDED), 0);
assert_eq!(zcond_regex_match(&["only_lhs"], ZREGEX_EXTENDED), 0);
}
#[test]
fn casematch_off_is_case_insensitive() {
let _g = crate::test_util::global_state_lock();
let saved = opt_state_get("casematch").unwrap_or(false);
opt_state_set("casematch", true);
let r = zcond_regex_match(&["HELLO", "hello"], ZREGEX_EXTENDED);
opt_state_set("casematch", saved);
assert_eq!(
r, 0,
"casematch=true → case-sensitive → HELLO vs hello must NOT match"
);
}
#[test]
fn casematch_unset_is_case_insensitive() {
let _g = crate::test_util::global_state_lock();
let saved = opt_state_get("casematch").unwrap_or(false);
opt_state_set("casematch", false);
let r = zcond_regex_match(&["HELLO", "hello"], ZREGEX_EXTENDED);
opt_state_set("casematch", saved);
assert_eq!(
r, 1,
"casematch=false → case-insensitive → HELLO matches hello"
);
}
#[test]
fn matching_pattern_returns_one() {
let _g = crate::test_util::global_state_lock();
let r = zcond_regex_match(&["hello world", "world"], ZREGEX_EXTENDED);
assert_eq!(r, 1);
}
#[test]
fn anchor_caret_requires_match_at_start() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["foobar", "^foo"], ZREGEX_EXTENDED), 1);
assert_eq!(zcond_regex_match(&["barfoo", "^foo"], ZREGEX_EXTENDED), 0);
}
#[test]
fn anchor_dollar_requires_match_at_end() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["barfoo", "foo$"], ZREGEX_EXTENDED), 1);
assert_eq!(zcond_regex_match(&["foobar", "foo$"], ZREGEX_EXTENDED), 0);
}
#[test]
fn alternation_matches_either_branch() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
zcond_regex_match(&["xterm", "xterm|screen"], ZREGEX_EXTENDED),
1
);
assert_eq!(
zcond_regex_match(&["screen", "xterm|screen"], ZREGEX_EXTENDED),
1
);
assert_eq!(
zcond_regex_match(&["bash", "xterm|screen"], ZREGEX_EXTENDED),
0
);
}
#[test]
fn dot_matches_any_single_char() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["foo", "f.o"], ZREGEX_EXTENDED), 1);
assert_eq!(zcond_regex_match(&["fXo", "f.o"], ZREGEX_EXTENDED), 1);
}
#[test]
fn regex_corpus_charclass_plus_quantifier_matches() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
zcond_regex_match(&["abc123", "[a-z]+[0-9]+"], ZREGEX_EXTENDED),
1,
);
}
#[test]
fn regex_corpus_anchored_full_match() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["abc", "^abc$"], ZREGEX_EXTENDED), 1,);
}
#[test]
fn regex_corpus_anchored_rejects_extra_chars() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["xabcy", "^abc$"], ZREGEX_EXTENDED), 0,);
}
#[test]
fn regex_corpus_empty_pattern_rejected() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["", ""], ZREGEX_EXTENDED), 0);
}
#[test]
fn regex_corpus_star_quantifier() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["aaa", "a*"], ZREGEX_EXTENDED), 1);
assert_eq!(zcond_regex_match(&["", "a*"], ZREGEX_EXTENDED), 1);
assert_eq!(
zcond_regex_match(&["b", "a*"], ZREGEX_EXTENDED),
1,
"a* matches empty prefix of 'b'"
);
}
#[test]
fn regex_corpus_invalid_pattern_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
zcond_regex_match(&["abc", "[unterminated"], ZREGEX_EXTENDED),
0,
"invalid regex returns 0 (no match + warn)",
);
}
#[test]
fn regex_corpus_wrong_id_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
zcond_regex_match(&["abc", "abc"], 99),
0,
"unsupported id = 0",
);
}
#[test]
fn regex_corpus_one_arg_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["only_one"], ZREGEX_EXTENDED), 0,);
}
#[test]
fn zcond_regex_match_empty_args_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&[], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_identical_strings_returns_one() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
zcond_regex_match(&["abc", "abc"], ZREGEX_EXTENDED),
1,
"identical str=pattern matches"
);
}
#[test]
fn zcond_regex_match_substring_match_returns_one() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["abcdef", "abc"], ZREGEX_EXTENDED), 1);
}
#[test]
fn zcond_regex_match_no_match_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["abc", "xyz"], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_plus_quantifier_works() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["aaa", "a+"], ZREGEX_EXTENDED), 1);
}
#[test]
fn zregex_regerrwarn_no_panic() {
let _g = crate::test_util::global_state_lock();
crate::regex_module::zregex_regerrwarn("test", "bad regex");
}
#[test]
fn zcond_regex_match_empty_args_returns_zero_pin() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&[], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_single_arg_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["x"], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_empty_pattern_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["hello", ""], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_bad_id_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["hello", "h"], 999), 0);
}
#[test]
fn zcond_regex_match_exact_lower_matches_lower() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["abc", "abc"], ZREGEX_EXTENDED), 1);
}
#[test]
fn zcond_regex_match_anchored_start() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["hello", "^h"], ZREGEX_EXTENDED), 1);
assert_eq!(zcond_regex_match(&["xhello", "^h"], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_anchored_end() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["hello", "o$"], ZREGEX_EXTENDED), 1);
assert_eq!(zcond_regex_match(&["hellox", "o$"], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_character_class() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["abc123", "[0-9]+"], ZREGEX_EXTENDED), 1);
assert_eq!(zcond_regex_match(&["abcdef", "[0-9]+"], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_invalid_pattern_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(zcond_regex_match(&["hello", "[abc"], ZREGEX_EXTENDED), 0);
}
#[test]
fn zcond_regex_match_is_deterministic() {
let _g = crate::test_util::global_state_lock();
let inputs: [(&[&str], i32, i32); 3] = [
(&["abc", "b"], ZREGEX_EXTENDED, 1),
(&["xyz", "abc"], ZREGEX_EXTENDED, 0),
(&["hello", "^h"], ZREGEX_EXTENDED, 1),
];
for (args, id, expected) in inputs.iter() {
for _ in 0..5 {
assert_eq!(zcond_regex_match(args, *id), *expected);
}
}
}
#[test]
fn regex_setup_returns_zero_pin() {
let _g = crate::test_util::global_state_lock();
assert_eq!(crate::regex_module::setup_(std::ptr::null()), 0);
}
#[test]
fn regex_boot_returns_zero_pin() {
let _g = crate::test_util::global_state_lock();
assert_eq!(crate::regex_module::boot_(std::ptr::null()), 0);
}
#[test]
fn zcond_regex_match_return_in_boolean_set() {
let _g = crate::test_util::global_state_lock();
for (args, id) in [
(vec!["a"], 0i32),
(vec!["a", "b"], 0),
(vec![], 0),
(vec!["abc", "abc"], 0),
(vec!["a*", ""], 0),
] {
let r = crate::regex_module::zcond_regex_match(&args, id);
assert!(
r == 0 || r == 1,
"zcond_regex_match({:?}, {}) = {} not in {{0,1}}",
args,
id,
r
);
}
}
#[test]
fn zcond_regex_match_full_sweep_deterministic() {
let _g = crate::test_util::global_state_lock();
for (args, id) in [
(vec!["pat", "val"], 0i32),
(vec!["", ""], 0),
(vec!["abc"], 0),
(vec!["[a-z]+", "xyz"], 0),
] {
let first = crate::regex_module::zcond_regex_match(&args, id);
for _ in 0..5 {
assert_eq!(
crate::regex_module::zcond_regex_match(&args, id),
first,
"({:?}, {}) must be deterministic",
args,
id
);
}
}
}
#[test]
fn zregex_regerrwarn_both_empty_no_panic() {
let _g = crate::test_util::global_state_lock();
crate::regex_module::zregex_regerrwarn("", "");
}
#[test]
fn zregex_regerrwarn_multibyte_no_panic() {
let _g = crate::test_util::global_state_lock();
crate::regex_module::zregex_regerrwarn("プレフィックス", "エラー");
crate::regex_module::zregex_regerrwarn("préfixe", "erreur");
}
#[test]
fn zregex_regerrwarn_repeated_safe() {
let _g = crate::test_util::global_state_lock();
for _ in 0..20 {
crate::regex_module::zregex_regerrwarn("prefix", "msg");
}
}
#[test]
fn zcond_regex_match_no_args_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(crate::regex_module::zcond_regex_match(&[], 0), 0);
}
#[test]
fn zcond_regex_match_large_input_no_panic() {
let _g = crate::test_util::global_state_lock();
let big = "x".repeat(10000);
let pat = "x+";
let _ = crate::regex_module::zcond_regex_match(&[pat, big.as_str()], 0);
}
#[test]
fn regex_full_lifecycle_returns_zero_for_all() {
let _g = crate::test_util::global_state_lock();
use crate::regex_module::*;
let null = std::ptr::null();
assert_eq!(setup_(null), 0);
let mut feats = Vec::new();
let _ = features_(null, &mut feats);
let mut enables: Option<Vec<i32>> = None;
let _ = enables_(null, &mut enables);
assert_eq!(boot_(null), 0);
assert_eq!(cleanup_(null), 0);
assert_eq!(finish_(null), 0);
}
#[test]
fn regex_setup_idempotent() {
let _g = crate::test_util::global_state_lock();
for _ in 0..10 {
assert_eq!(crate::regex_module::setup_(std::ptr::null()), 0);
}
}
#[test]
fn regex_finish_idempotent() {
let _g = crate::test_util::global_state_lock();
for _ in 0..10 {
assert_eq!(crate::regex_module::finish_(std::ptr::null()), 0);
}
}
#[test]
fn zcond_regex_match_returns_i32_type_pin() {
let _g = crate::test_util::global_state_lock();
let _: i32 = crate::regex_module::zcond_regex_match(&[], 0);
}
#[test]
fn zcond_regex_match_anchored_alpha_matches() {
let _g = crate::test_util::global_state_lock();
let r = crate::regex_module::zcond_regex_match(&["^abc", "abcdef"], 0);
assert!(r == 0 || r == 1, "result is boolean i32");
}
#[test]
fn zcond_regex_match_case_sensitive_by_default() {
let _g = crate::test_util::global_state_lock();
let mismatch = crate::regex_module::zcond_regex_match(&["abc", "ABC"], 0);
assert_eq!(mismatch, 0, "abc !~ ABC by default");
}
#[test]
fn zcond_regex_match_empty_pattern_matches_empty_value() {
let _g = crate::test_util::global_state_lock();
let r = crate::regex_module::zcond_regex_match(&["", ""], 0);
assert!(r == 0 || r == 1, "result is boolean i32");
}
#[test]
fn zregex_regerrwarn_signature_void() {
let _g = crate::test_util::global_state_lock();
let _: () = crate::regex_module::zregex_regerrwarn("prefix", "msg");
}
#[test]
fn zregex_regerrwarn_both_empty_no_panic_pin() {
let _g = crate::test_util::global_state_lock();
crate::regex_module::zregex_regerrwarn("", "");
}
#[test]
fn zcond_regex_match_digit_class_matches() {
let _g = crate::test_util::global_state_lock();
let r = crate::regex_module::zcond_regex_match(&["[0-9]+", "123abc"], 0);
assert!(r == 0 || r == 1);
}
#[test]
fn zcond_regex_match_no_match_returns_zero_pin() {
let _g = crate::test_util::global_state_lock();
let r = crate::regex_module::zcond_regex_match(&["xyz", "abc"], 0);
assert_eq!(r, 0, "xyz not in abc → 0");
}
#[test]
fn zcond_regex_match_full_equal_matches() {
let _g = crate::test_util::global_state_lock();
let r = crate::regex_module::zcond_regex_match(&["^abc$", "abc"], 0);
assert!(r == 0 || r == 1);
}
#[test]
fn zcond_regex_match_dot_matches_single() {
let _g = crate::test_util::global_state_lock();
let r = crate::regex_module::zcond_regex_match(&[".", "a"], 0);
assert!(r == 0 || r == 1);
}
#[test]
fn zcond_regex_match_returns_i32_type() {
let _g = crate::test_util::global_state_lock();
let _: i32 = crate::regex_module::zcond_regex_match(&[".", "a"], 0);
}
#[test]
fn zcond_regex_match_deterministic_for_simple_pattern() {
let _g = crate::test_util::global_state_lock();
let first = crate::regex_module::zcond_regex_match(&["abc", "abcdef"], 0);
for _ in 0..5 {
assert_eq!(
crate::regex_module::zcond_regex_match(&["abc", "abcdef"], 0),
first,
"zcond_regex_match must be pure across calls"
);
}
}
#[test]
fn zcond_regex_match_result_is_boolean_only() {
let _g = crate::test_util::global_state_lock();
for pair in &[
(".", "a"),
("[0-9]+", "abc"),
("xyz", "abc"),
("^foo", "foobar"),
(".+", ""),
] {
let r = crate::regex_module::zcond_regex_match(&[pair.0, pair.1], 0);
assert!(
r == 0 || r == 1,
"regex match ({:?}, {:?}) → {} not in 0/1",
pair.0,
pair.1,
r
);
}
}
#[test]
fn zregex_regerrwarn_long_inputs_safe() {
let _g = crate::test_util::global_state_lock();
let long_prefix = "p".repeat(1000);
let long_msg = "m".repeat(2000);
crate::regex_module::zregex_regerrwarn(&long_prefix, &long_msg);
}
#[test]
fn zregex_regerrwarn_multibyte_and_ansi_safe() {
let _g = crate::test_util::global_state_lock();
crate::regex_module::zregex_regerrwarn("日本", "包含中文");
crate::regex_module::zregex_regerrwarn("\x1b[31m", "red message\x1b[0m");
}
#[test]
fn zcond_regex_match_malformed_pattern_no_panic() {
let _g = crate::test_util::global_state_lock();
for bad in &["[", "(", "*", "+", "(?", "[a-"] {
let _ = crate::regex_module::zcond_regex_match(&[bad, "input"], 0);
}
}
#[test]
fn regex_setup_returns_i32_type() {
let _g = crate::test_util::global_state_lock();
let _: i32 = crate::regex_module::setup_(std::ptr::null());
}
#[test]
fn regex_enables_with_none_returns_i32() {
let _g = crate::test_util::global_state_lock();
let mut e: Option<Vec<i32>> = None;
let _: i32 = crate::regex_module::enables_(std::ptr::null(), &mut e);
}
#[test]
fn regex_features_safe_with_caller_vec() {
let _g = crate::test_util::global_state_lock();
let mut v: Vec<String> = Vec::new();
let _ = crate::regex_module::features_(std::ptr::null(), &mut v);
}
#[test]
fn regex_each_lifecycle_hook_returns_zero_individually() {
let _g = crate::test_util::global_state_lock();
let null = std::ptr::null();
let mut v: Vec<String> = Vec::new();
let mut e: Option<Vec<i32>> = None;
assert_eq!(crate::regex_module::setup_(null), 0, "c:215 setup_");
assert_eq!(
crate::regex_module::features_(null, &mut v),
0,
"c:222 features_"
);
assert_eq!(
crate::regex_module::enables_(null, &mut e),
0,
"c:228 enables_"
);
assert_eq!(crate::regex_module::boot_(null), 0, "c:234 boot_");
assert_eq!(crate::regex_module::cleanup_(null), 0, "c:242 cleanup_");
assert_eq!(crate::regex_module::finish_(null), 0, "c:248 finish_");
}
#[test]
fn zcond_regex_match_single_arg_no_panic() {
let _g = crate::test_util::global_state_lock();
let _ = crate::regex_module::zcond_regex_match(&["pattern"], 0);
}
}