#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
use std::io::Write;
use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::{Mutex, OnceLock};
use crate::ported::compat::output64;
use crate::ported::cond::{cond_str, cond_val};
use crate::ported::math::{mnumber, MN_FLOAT, MN_INTEGER};
use crate::ported::string::dyncat;
use crate::ported::zsh_h::{features, module, options, OPT_ISSET, MAX_OPS};
pub static intparam: AtomicI64 = AtomicI64::new(0);
pub static strparam: Mutex<Option<String>> = Mutex::new(None);
pub static arrparam: Mutex<Option<Vec<String>>> = Mutex::new(None);
#[allow(unused_variables)]
pub fn bin_example(nam: &str, args: &[String], ops: &options, func: i32) -> i32 {
let mut stdout = std::io::stdout().lock();
let mut c: u8;
let oargs = args; let mut i: i64 = 0;
let _ = write!(stdout, "Options: "); c = 32; loop {
c += 1;
if c >= 128 {
break;
}
if OPT_ISSET(ops, c) {
let _ = write!(stdout, "{}", c as char); }
}
let _ = write!(stdout, "\nArguments:"); for a in args {
let _ = write!(stdout, " "); let _ = write!(stdout, "{}", a); i += 1; }
let _ = writeln!(stdout, "\nName: {}", nam); let _ = writeln!(
stdout,
"\nInteger Parameter: {}",
output64(intparam.load(Ordering::Relaxed))
); {
let sp = strparam.lock().unwrap();
let _ = writeln!(stdout, "String Parameter: {}", sp.as_deref().unwrap_or(""));
}
let _ = write!(stdout, "Array Parameter:"); {
let p = arrparam.lock().unwrap();
if let Some(arr) = p.as_ref() {
for s in arr {
let _ = write!(stdout, " {}", s); }
}
}
let _ = writeln!(stdout);
intparam.store(i, Ordering::Relaxed); let new_sp = if let Some(first) = oargs.first() {
first.clone()
} else {
String::new()
};
*strparam.lock().unwrap() = Some(new_sp); let new_ap: Vec<String> = oargs.to_vec(); *arrparam.lock().unwrap() = Some(new_ap);
0 }
#[allow(unused_variables)]
pub fn cond_p_len(a: &[String], id: i32) -> i32 {
let s1: String = cond_str(a, 0, false); if a.len() > 1 {
let v: i64 = cond_val(a, 1); if (s1.len() as i64) == v {
1
} else {
0
}
} else {
if s1.is_empty() {
1
} else {
0
}
}
}
#[allow(unused_variables)]
pub fn cond_i_ex(a: &[String], id: i32) -> i32 {
let s1: String = cond_str(a, 0, false); let s2: String = cond_str(a, 1, false); if dyncat(&s1, &s2) == "example" {
1
} else {
0
} }
#[allow(unused_variables)]
pub fn math_sum(name: &str, argc: i32, argv: &[mnumber], id: i32) -> mnumber {
let mut ret = mnumber {
l: 0,
d: 0.0,
type_: MN_INTEGER,
};
let mut f: i32 = 0;
ret.l = 0;
let mut argc = argc;
let mut p: usize = 0; while {
let go = argc > 0;
argc -= 1;
go
} {
if argv[p].type_ == MN_INTEGER {
if f != 0 {
ret.d += argv[p].l as f64; } else {
ret.l += argv[p].l; }
} else {
if f != 0 {
ret.d += argv[p].d; } else {
ret.d = (ret.l as f64) + argv[p].d; f = 1; }
}
p += 1; }
ret.type_ = if f != 0 { MN_FLOAT } else { MN_INTEGER };
ret }
#[allow(unused_variables)]
pub fn math_length(name: &str, arg: &str, id: i32) -> mnumber {
mnumber {
type_: MN_INTEGER,
l: arg.len() as i64,
d: 0.0,
}
}
pub fn ex_wrapper(
prog: *const crate::ported::zsh_h::eprog, w: *const crate::ported::zsh_h::funcwrap,
name: &str,
) -> i32 {
if !name.starts_with("example") {
return 1; }
let _ = (prog, w);
0 }
#[allow(unused_variables)]
pub fn setup_(m: *const module) -> i32 {
let mut stdout = std::io::stdout().lock();
let _ = writeln!(stdout, "The example module has now been set up."); let _ = stdout.flush(); 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) }
pub fn boot_(m: *const module) -> i32 {
intparam.store(42, Ordering::Relaxed); *strparam.lock().unwrap() = Some("example".to_string()); *arrparam.lock().unwrap() = Some(vec![
"example".to_string(), "array".to_string(), ]);
let _ = m;
0
}
pub fn cleanup_(m: *const module) -> i32 {
setfeatureenables(m, module_features(), None) }
#[allow(unused_variables)]
pub fn finish_(m: *const module) -> i32 {
let mut stdout = std::io::stdout().lock();
let _ = writeln!(
stdout,
"Thank you for using the example module. Have a nice day."
); let _ = stdout.flush(); 0 }
static MODULE_FEATURES: OnceLock<Mutex<features>> = OnceLock::new();
fn featuresarray(_m: *const module, _f: &Mutex<features>) -> Vec<String> {
vec![
"b:example".to_string(),
"c:ex".to_string(),
"c:len".to_string(),
"f:length".to_string(),
"f:sum".to_string(),
"p:exarr".to_string(),
"p:exint".to_string(),
"p:exstr".to_string(),
]
}
fn handlefeatures(
_m: *const module,
_f: &Mutex<features>,
enables: &mut Option<Vec<i32>>,
) -> i32 {
if enables.is_none() {
*enables = Some(vec![1; 8]);
}
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: 1,
cd_list: None,
cd_size: 2,
mf_list: None,
mf_size: 2,
pd_list: None,
pd_size: 3,
n_abstract: 0,
})
})
}
#[cfg(test)]
mod tests {
use super::*;
fn empty_ops() -> options {
options {
ind: [0u8; MAX_OPS],
args: Vec::new(),
argscount: 0,
argsalloc: 0,
}
}
fn s(x: &str) -> String {
x.to_string()
}
static EXAMPLE_TEST_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
#[test]
fn boot_populates_demo_params() {
let _g = crate::test_util::global_state_lock();
let _g = EXAMPLE_TEST_LOCK.lock().unwrap_or_else(|e| e.into_inner());
boot_(std::ptr::null());
assert_eq!(intparam.load(Ordering::SeqCst), 42);
assert_eq!(strparam.lock().unwrap().as_deref(), Some("example"));
let arr = arrparam.lock().unwrap();
let arr = arr.as_ref().expect("arrparam must be Some after boot_");
assert_eq!(arr.len(), 2);
assert_eq!(arr[0], "example");
assert_eq!(arr[1], "array");
}
#[test]
fn cond_p_len_arities() {
let _g = crate::test_util::global_state_lock();
assert_eq!(cond_p_len(&[s("hello"), s("5")], 0), 1);
assert_eq!(cond_p_len(&[s("hello"), s("4")], 0), 0);
assert_eq!(cond_p_len(&[s("")], 0), 1);
assert_eq!(cond_p_len(&[s("x")], 0), 0);
}
#[test]
fn cond_i_ex_concat_matches_example() {
let _g = crate::test_util::global_state_lock();
assert_eq!(cond_i_ex(&[s("exam"), s("ple")], 0), 1);
assert_eq!(cond_i_ex(&[s("example"), s("")], 0), 1);
assert_eq!(cond_i_ex(&[s("example"), s("x")], 0), 0);
assert_eq!(cond_i_ex(&[s("foo"), s("bar")], 0), 0);
}
#[test]
fn math_sum_int_then_float_promotion() {
let _g = crate::test_util::global_state_lock();
let ints = [
mnumber {
l: 1,
d: 0.0,
type_: MN_INTEGER,
},
mnumber {
l: 2,
d: 0.0,
type_: MN_INTEGER,
},
mnumber {
l: 3,
d: 0.0,
type_: MN_INTEGER,
},
];
let r = math_sum("sum", 3, &ints, 0);
assert_eq!(r.type_, MN_INTEGER);
assert_eq!(r.l, 6);
let mixed = [
mnumber {
l: 1,
d: 0.0,
type_: MN_INTEGER,
},
mnumber {
l: 0,
d: 2.5,
type_: MN_FLOAT,
},
mnumber {
l: 3,
d: 0.0,
type_: MN_INTEGER,
},
];
let r = math_sum("sum", 3, &mixed, 0);
assert_eq!(r.type_, MN_FLOAT);
assert!((r.d - 6.5).abs() < 1e-9);
}
#[test]
fn math_length_returns_strlen() {
let _g = crate::test_util::global_state_lock();
let r = math_length("length", "hello", 0);
assert_eq!(r.type_, MN_INTEGER);
assert_eq!(r.l, 5);
}
#[test]
fn ex_wrapper_name_prefix_match() {
let _g = crate::test_util::global_state_lock();
assert_eq!(ex_wrapper(std::ptr::null(), std::ptr::null(), "foo"), 1);
assert_eq!(ex_wrapper(std::ptr::null(), std::ptr::null(), "exampl"), 1);
assert_eq!(ex_wrapper(std::ptr::null(), std::ptr::null(), "example"), 0);
assert_eq!(
ex_wrapper(std::ptr::null(), std::ptr::null(), "example_func"),
0
);
}
#[test]
fn bin_example_returns_zero_and_assigns_state() {
let _g = crate::test_util::global_state_lock();
let _g = EXAMPLE_TEST_LOCK.lock().unwrap_or_else(|e| e.into_inner());
let ops = empty_ops();
let args = vec![s("hello"), s("world")];
let rc = bin_example("example", &args, &ops, 0);
assert_eq!(rc, 0);
assert_eq!(intparam.load(Ordering::Relaxed), 2);
assert_eq!(strparam.lock().unwrap().as_deref(), Some("hello"));
let arr = arrparam.lock().unwrap();
assert_eq!(arr.as_ref().unwrap().as_slice(), &[s("hello"), s("world")]);
}
#[test]
fn math_sum_zero_args_returns_zero() {
let _g = crate::test_util::global_state_lock();
let r = math_sum("sum", 0, &[], 0);
assert_eq!(r.type_, MN_INTEGER);
assert_eq!(r.l, 0, "sum of nothing must be 0");
}
#[test]
fn math_sum_single_int_arg_is_identity() {
let _g = crate::test_util::global_state_lock();
let argv = [mnumber {
l: 42,
d: 0.0,
type_: MN_INTEGER,
}];
let r = math_sum("sum", 1, &argv, 0);
assert_eq!(r.type_, MN_INTEGER);
assert_eq!(r.l, 42);
}
#[test]
fn math_sum_all_floats_preserves_float_type() {
let _g = crate::test_util::global_state_lock();
let argv = [
mnumber {
l: 0,
d: 1.5,
type_: MN_FLOAT,
},
mnumber {
l: 0,
d: 2.5,
type_: MN_FLOAT,
},
];
let r = math_sum("sum", 2, &argv, 0);
assert_eq!(r.type_, MN_FLOAT);
assert!((r.d - 4.0).abs() < 1e-9);
}
#[test]
fn math_sum_handles_negative_ints() {
let _g = crate::test_util::global_state_lock();
let argv = [
mnumber {
l: -5,
d: 0.0,
type_: MN_INTEGER,
},
mnumber {
l: 3,
d: 0.0,
type_: MN_INTEGER,
},
];
let r = math_sum("sum", 2, &argv, 0);
assert_eq!(r.type_, MN_INTEGER);
assert_eq!(r.l, -2, "−5 + 3 = −2");
}
#[test]
fn math_length_empty_string_returns_zero() {
let _g = crate::test_util::global_state_lock();
let r = math_length("length", "", 0);
assert_eq!(r.type_, MN_INTEGER);
assert_eq!(r.l, 0);
}
#[test]
fn math_length_multibyte_returns_byte_count() {
let _g = crate::test_util::global_state_lock();
let r = math_length("length", "café", 0);
assert_eq!(
r.l, 5,
"math_length must count bytes, not chars — got {}",
r.l
);
}
#[test]
fn cond_i_ex_returns_zero() {
let _g = crate::test_util::global_state_lock();
let r = cond_i_ex(&[], 0);
assert_eq!(r, 0, "cond_i_ex demo condition must return 0 (false)");
}
#[test]
fn module_lifecycle_shims_all_return_zero() {
let _g = crate::test_util::global_state_lock();
let m: *const module = std::ptr::null();
assert_eq!(setup_(m), 0);
assert_eq!(boot_(m), 0);
assert_eq!(cleanup_(m), 0);
assert_eq!(finish_(m), 0);
}
#[test]
fn example_corpus_math_sum_empty_is_zero_integer() {
let _g = crate::test_util::global_state_lock();
let r = math_sum("sum", 0, &[], 0);
assert_eq!(r.l, 0);
assert_eq!(r.type_, MN_INTEGER, "empty sum stays integer-typed");
}
#[test]
fn example_corpus_math_sum_int_args_stay_integer() {
let _g = crate::test_util::global_state_lock();
let args = vec![
mnumber { l: 1, d: 0.0, type_: MN_INTEGER },
mnumber { l: 2, d: 0.0, type_: MN_INTEGER },
mnumber { l: 3, d: 0.0, type_: MN_INTEGER },
];
let r = math_sum("sum", 3, &args, 0);
assert_eq!(r.l, 6, "1+2+3=6");
assert_eq!(r.type_, MN_INTEGER);
}
#[test]
fn example_corpus_math_sum_mixed_promotes_to_float() {
let _g = crate::test_util::global_state_lock();
let args = vec![
mnumber { l: 2, d: 0.0, type_: MN_INTEGER },
mnumber { l: 0, d: 1.5, type_: MN_FLOAT },
];
let r = math_sum("sum", 2, &args, 0);
assert_eq!(r.type_, MN_FLOAT, "int+float → float");
assert!((r.d - 3.5).abs() < 1e-9);
}
#[test]
fn example_corpus_math_sum_two_floats() {
let _g = crate::test_util::global_state_lock();
let args = vec![
mnumber { l: 0, d: 1.25, type_: MN_FLOAT },
mnumber { l: 0, d: 2.75, type_: MN_FLOAT },
];
let r = math_sum("sum", 2, &args, 0);
assert_eq!(r.type_, MN_FLOAT);
assert!((r.d - 4.0).abs() < 1e-9);
}
#[test]
fn example_corpus_math_length_ascii_byte_count() {
let _g = crate::test_util::global_state_lock();
let r = math_length("length", "hello", 0);
assert_eq!(r.l, 5);
assert_eq!(r.type_, MN_INTEGER);
}
#[test]
fn example_corpus_math_length_empty_is_zero() {
let _g = crate::test_util::global_state_lock();
let r = math_length("length", "", 0);
assert_eq!(r.l, 0);
}
#[test]
fn example_corpus_math_length_multibyte_byte_count() {
let _g = crate::test_util::global_state_lock();
let r = math_length("length", "日", 0);
assert_eq!(r.l, 3, "C strlen-style byte count for UTF-8");
}
#[test]
fn example_corpus_cond_p_len_does_not_panic() {
let _g = crate::test_util::global_state_lock();
let _ = cond_p_len(&["abc".to_string()], 0);
}
}