#![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); mod stdlib { use std::env::current_exe; use std::io; use std::path::{Path, PathBuf}; const STDLIB_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/stdlib.tar.gz")); /// Guess where tcl will look for the standard library (from the directory containing the current executable, ../lib/tcl8.6/). pub fn guess_expected_stdlib_target() -> PathBuf { let exe = current_exe().unwrap(); let exe_parent = exe.parent().unwrap(); let exe_parent_parent = exe_parent.parent().unwrap(); let exe_parent_parent_lib = exe_parent_parent.join("lib"); let expected_stdlib_path = exe_parent_parent_lib.join("tcl8.6"); expected_stdlib_path } /// Extract the built-in standard library to the given path, ignoring if already exists. pub fn extract_stdlib_to(target: impl AsRef) -> io::Result<()> { let reader = flate2::read::GzDecoder::new(STDLIB_DATA); let mut ar = tar::Archive::new(reader); ar.set_overwrite(false); let result = ar.unpack(target); match result { Err(e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()), x => x, } } } pub use stdlib::*; #[cfg(test)] mod tests { use super::*; use std::ffi::{CStr, CString}; #[test] fn two_plus_two() { unsafe { extract_stdlib_to(guess_expected_stdlib_target()).unwrap(); let interp = Tcl_CreateInterp(); let init_status = Tcl_Init(interp); if init_status == TCL_ERROR as i32 { eprintln!( "{}", CStr::from_ptr(Tcl_GetStringResult(interp)).to_string_lossy() ); } assert_eq!(init_status, TCL_OK as i32); let script = CString::new("expr 2 + 2").unwrap(); let eval_status = Tcl_Eval(interp, script.as_ptr()); assert_eq!(eval_status, TCL_OK as i32); let result = Tcl_GetObjResult(interp); let mut result_value = 0; let get_int_status = Tcl_GetIntFromObj(interp, result, &mut result_value); assert_eq!(get_int_status, TCL_OK as i32); assert_eq!(result_value, 4); Tcl_DeleteInterp(interp); } } }