#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
use std::io::Write;
use std::sync::Mutex;
use std::sync::OnceLock;
use std::sync::atomic::{AtomicI64, Ordering};
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::{module, options, Eprog, FuncWrap, OPT_ISSET};
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 }
#[cfg(test)]
mod tests {
use super::*;
use crate::ported::zsh_h::MAX_OPS;
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 = 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() {
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() {
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 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 r = math_length("length", "hello", 0);
assert_eq!(r.type_, MN_INTEGER);
assert_eq!(r.l, 5);
}
#[test]
fn ex_wrapper_name_prefix_match() {
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 = 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")]);
}
}
use crate::ported::zsh_h::features as features_t;
static MODULE_FEATURES: OnceLock<Mutex<features_t>> = OnceLock::new();
fn module_features() -> &'static Mutex<features_t> {
MODULE_FEATURES.get_or_init(|| Mutex::new(features_t {
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,
}))
}
fn featuresarray(_m: *const module, _f: &Mutex<features_t>) -> 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_t>,
enables: &mut Option<Vec<i32>>,
) -> i32 {
if enables.is_none() {
*enables = Some(vec![1; 8]);
}
0
}
fn setfeatureenables(
_m: *const module,
_f: &Mutex<features_t>,
_e: Option<&[i32]>,
) -> i32 {
0
}