1#![allow(clippy::not_unsafe_ptr_arg_deref)]
7use std::ffi::CStr;
17use std::os::raw::{c_char, c_int, c_void};
18use std::ptr;
19
20use super::sexp::{self, PairlistData, Sexp, SexpRec};
21
22#[allow(dead_code)] struct AllocNode {
27 sexp: Sexp,
28 next: *mut AllocNode,
29}
30
31type CbResult = Result<crate::interpreter::value::RValue, crate::interpreter::value::RError>;
33
34#[derive(Default)]
36pub struct InterpreterCallbacks {
37 pub find_var: Option<fn(&str) -> Option<crate::interpreter::value::RValue>>,
38 pub define_var: Option<fn(&str, crate::interpreter::value::RValue)>,
39 pub eval_expr: Option<fn(&crate::interpreter::value::RValue) -> CbResult>,
40 pub parse_text: Option<fn(&str) -> CbResult>,
41}
42
43struct RuntimeState {
46 alloc_head: *mut AllocNode,
47 protect_stack: Vec<Sexp>,
48 callbacks: InterpreterCallbacks,
49 rvalue_stash: Vec<crate::interpreter::value::RValue>,
53}
54
55thread_local! {
56 static STATE: std::cell::RefCell<RuntimeState> = std::cell::RefCell::new(RuntimeState {
57 alloc_head: ptr::null_mut(),
58 protect_stack: Vec::with_capacity(128),
59 callbacks: InterpreterCallbacks::default(),
60 rvalue_stash: Vec::new(),
61 });
62}
63
64pub(super) fn stash_rvalue(val: crate::interpreter::value::RValue) -> usize {
66 STATE.with(|state| {
67 let mut st = state.borrow_mut();
68 let idx = st.rvalue_stash.len();
69 st.rvalue_stash.push(val);
70 idx
71 })
72}
73
74fn get_stashed_rvalue(idx: usize) -> Option<crate::interpreter::value::RValue> {
76 STATE.with(|state| {
77 let st = state.borrow();
78 st.rvalue_stash.get(idx).cloned()
79 })
80}
81
82pub fn set_callbacks(callbacks: InterpreterCallbacks) {
84 STATE.with(|state| {
85 state.borrow_mut().callbacks = callbacks;
86 });
87}
88
89pub fn init_global_envs(
92 base_env: &crate::interpreter::environment::Environment,
93 global_env: &crate::interpreter::environment::Environment,
94) {
95 use super::convert::rvalue_to_sexp;
96 use crate::interpreter::value::RValue;
97 unsafe {
98 R_BaseEnv = rvalue_to_sexp(&RValue::Environment(base_env.clone()));
99 R_GlobalEnv = rvalue_to_sexp(&RValue::Environment(global_env.clone()));
100 R_BaseNamespace = R_BaseEnv;
101 }
103}
104
105fn langsxp_to_text(s: Sexp) -> Option<String> {
110 if s.is_null() || unsafe { (*s).stype != sexp::LANGSXP } {
111 return None;
112 }
113
114 let data = unsafe { (*s).data as *const sexp::PairlistData };
115 if data.is_null() {
116 return None;
117 }
118
119 let func = unsafe { (*data).car };
121 let args = unsafe { (*data).cdr };
122
123 let func_name = if !func.is_null() && unsafe { (*func).stype } == sexp::SYMSXP {
125 unsafe { sexp::char_data(func) }.to_string()
126 } else if !func.is_null() && unsafe { (*func).stype } == sexp::LANGSXP {
127 langsxp_to_text(func)?
129 } else {
130 return None;
131 };
132
133 let mut arg_strs = Vec::new();
135 let mut node = args;
136 while !node.is_null() && unsafe { (*node).stype } != sexp::NILSXP {
137 let nd = unsafe { (*node).data as *const sexp::PairlistData };
138 if nd.is_null() {
139 break;
140 }
141
142 let val = unsafe { (*nd).car };
143 let tag = unsafe { (*nd).tag };
144
145 let val_str = sexp_to_text_repr(val);
147
148 if !tag.is_null() && unsafe { (*tag).stype } == sexp::SYMSXP {
150 let tag_name = unsafe { sexp::char_data(tag) };
151 if !tag_name.is_empty() {
152 arg_strs.push(format!("{tag_name} = {val_str}"));
153 } else {
154 arg_strs.push(val_str);
155 }
156 } else {
157 arg_strs.push(val_str);
158 }
159
160 node = unsafe { (*nd).cdr };
161 }
162
163 if (func_name == "::" || func_name == ":::" || func_name == "$") && arg_strs.len() == 2 {
165 return Some(format!("{}{func_name}{}", arg_strs[0], arg_strs[1]));
166 }
167
168 Some(format!("{}({})", func_name, arg_strs.join(", ")))
169}
170
171fn sexp_to_text_repr(s: Sexp) -> String {
173 if s.is_null() {
174 return "NULL".to_string();
175 }
176 let stype = unsafe { (*s).stype };
177 match stype {
178 sexp::NILSXP => "NULL".to_string(),
179 sexp::SYMSXP => unsafe { sexp::char_data(s) }.to_string(),
180 sexp::LANGSXP => langsxp_to_text(s).unwrap_or_else(|| "NULL".to_string()),
181 sexp::LGLSXP => {
182 let rval = unsafe { super::convert::sexp_to_rvalue(s) };
183 format!("{}", rval)
184 }
185 sexp::INTSXP | sexp::REALSXP => {
186 let rval = unsafe { super::convert::sexp_to_rvalue(s) };
187 format!("{}", rval)
188 }
189 sexp::STRSXP => {
190 let rval = unsafe { super::convert::sexp_to_rvalue(s) };
191 if let Some(rv) = rval.as_vector() {
192 if let Some(s) = rv.as_character_scalar() {
193 return format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\""));
194 }
195 }
196 format!("{}", rval)
197 }
198 _ => {
199 let rval = unsafe { super::convert::sexp_to_rvalue(s) };
201 format!("{}", rval)
202 }
203 }
204}
205
206pub fn clear_callbacks() {
208 STATE.with(|state| {
209 let mut st = state.borrow_mut();
210 st.callbacks = InterpreterCallbacks::default();
211 st.rvalue_stash.clear();
212 });
213}
214
215pub(super) fn track(s: Sexp) {
216 let node = Box::into_raw(Box::new(AllocNode {
217 sexp: s,
218 next: ptr::null_mut(),
219 }));
220 STATE.with(|state| {
221 let mut st = state.borrow_mut();
222 unsafe {
223 (*node).next = st.alloc_head;
224 }
225 st.alloc_head = node;
226 });
227}
228
229static mut NIL_REC: SexpRec = SexpRec {
239 stype: sexp::NILSXP,
240 flags: 0,
241 padding: 0,
242 length: 0,
243 data: ptr::null_mut(),
244 attrib: ptr::null_mut(),
245};
246
247#[no_mangle]
249pub static mut R_NilValue: Sexp = ptr::null_mut();
250
251#[no_mangle]
252pub static mut R_NaString: Sexp = ptr::null_mut();
253
254#[no_mangle]
256pub static mut R_NaInt: c_int = i32::MIN;
257
258#[no_mangle]
260pub static mut R_NaReal: f64 = sexp::NA_REAL;
261
262#[no_mangle]
263pub static mut R_BlankString: Sexp = ptr::null_mut();
264
265#[no_mangle]
266pub static mut R_GlobalEnv: Sexp = ptr::null_mut();
267
268#[no_mangle]
269pub static mut R_BaseEnv: Sexp = ptr::null_mut();
270
271#[no_mangle]
272pub static mut R_UnboundValue: Sexp = ptr::null_mut();
273
274static mut SYM_NAMES: SexpRec = SexpRec {
276 stype: sexp::SYMSXP,
277 flags: 0,
278 padding: 0,
279 length: 5,
280 data: ptr::null_mut(),
281 attrib: ptr::null_mut(),
282};
283static mut SYM_DIM: SexpRec = SexpRec {
284 stype: sexp::SYMSXP,
285 flags: 0,
286 padding: 0,
287 length: 3,
288 data: ptr::null_mut(),
289 attrib: ptr::null_mut(),
290};
291static mut SYM_DIMNAMES: SexpRec = SexpRec {
292 stype: sexp::SYMSXP,
293 flags: 0,
294 padding: 0,
295 length: 8,
296 data: ptr::null_mut(),
297 attrib: ptr::null_mut(),
298};
299static mut SYM_CLASS: SexpRec = SexpRec {
300 stype: sexp::SYMSXP,
301 flags: 0,
302 padding: 0,
303 length: 5,
304 data: ptr::null_mut(),
305 attrib: ptr::null_mut(),
306};
307static mut SYM_ROWNAMES: SexpRec = SexpRec {
308 stype: sexp::SYMSXP,
309 flags: 0,
310 padding: 0,
311 length: 10,
312 data: ptr::null_mut(),
313 attrib: ptr::null_mut(),
314};
315static mut SYM_LEVELS: SexpRec = SexpRec {
316 stype: sexp::SYMSXP,
317 flags: 0,
318 padding: 0,
319 length: 6,
320 data: ptr::null_mut(),
321 attrib: ptr::null_mut(),
322};
323
324#[no_mangle]
325pub static mut R_NamesSymbol: Sexp = ptr::null_mut();
326#[no_mangle]
327pub static mut R_DimSymbol: Sexp = ptr::null_mut();
328#[no_mangle]
329pub static mut R_DimNamesSymbol: Sexp = ptr::null_mut();
330#[no_mangle]
331pub static mut R_ClassSymbol: Sexp = ptr::null_mut();
332#[no_mangle]
333pub static mut R_RowNamesSymbol: Sexp = ptr::null_mut();
334#[no_mangle]
335pub static mut R_LevelsSymbol: Sexp = ptr::null_mut();
336
337static mut SYM_DOTS: SexpRec = SexpRec {
338 stype: sexp::SYMSXP,
339 flags: 0,
340 padding: 0,
341 length: 3,
342 data: ptr::null_mut(),
343 attrib: ptr::null_mut(),
344};
345#[no_mangle]
346pub static mut R_DotsSymbol: Sexp = ptr::null_mut();
347
348#[no_mangle]
349pub static mut _minir_current_dll_info: *mut c_void = ptr::null_mut();
350
351pub fn init_globals() {
353 unsafe {
354 static NA_STR: &[u8] = b"NA\0";
356 static BLANK_STR: &[u8] = b"\0";
357 static NAMES_STR: &[u8] = b"names\0";
358 static DIM_STR: &[u8] = b"dim\0";
359 static DIMNAMES_STR: &[u8] = b"dimnames\0";
360 static CLASS_STR: &[u8] = b"class\0";
361 static ROWNAMES_STR: &[u8] = b"row.names\0";
362 static LEVELS_STR: &[u8] = b"levels\0";
363 static DOTS_STR: &[u8] = b"...\0";
364
365 R_NilValue = &raw mut NIL_REC;
366
367 static mut NA_STRING_REC: SexpRec = SexpRec {
369 stype: sexp::CHARSXP,
370 flags: 0,
371 padding: 0,
372 length: 2,
373 data: ptr::null_mut(),
374 attrib: ptr::null_mut(),
375 };
376 NA_STRING_REC.data = NA_STR.as_ptr() as *mut u8;
377 NA_STRING_REC.attrib = R_NilValue;
378 R_NaString = &raw mut NA_STRING_REC;
379
380 static mut BLANK_STRING_REC: SexpRec = SexpRec {
382 stype: sexp::CHARSXP,
383 flags: 0,
384 padding: 0,
385 length: 0,
386 data: ptr::null_mut(),
387 attrib: ptr::null_mut(),
388 };
389 BLANK_STRING_REC.data = BLANK_STR.as_ptr() as *mut u8;
390 BLANK_STRING_REC.attrib = R_NilValue;
391 R_BlankString = &raw mut BLANK_STRING_REC;
392
393 R_GlobalEnv = R_NilValue;
394 R_BaseEnv = R_NilValue;
395 R_UnboundValue = R_NilValue;
396 R_EmptyEnv = R_NilValue;
397 R_MissingArg = R_NilValue;
398 R_NamespaceRegistry = R_NilValue;
399 R_Srcref = R_NilValue;
400 R_BaseNamespace = R_NilValue;
401 R_NameSymbol = R_NilValue;
402 R_BraceSymbol = R_NilValue;
403 R_BracketSymbol = R_NilValue;
404 R_Bracket2Symbol = R_NilValue;
405 R_DollarSymbol = R_NilValue;
406 R_DoubleColonSymbol = R_NilValue;
407 R_TripleColonSymbol = R_NilValue;
408
409 SYM_NAMES.data = NAMES_STR.as_ptr() as *mut u8;
411 SYM_NAMES.attrib = R_NilValue;
412 R_NamesSymbol = &raw mut SYM_NAMES;
413
414 SYM_DIM.data = DIM_STR.as_ptr() as *mut u8;
415 SYM_DIM.attrib = R_NilValue;
416 R_DimSymbol = &raw mut SYM_DIM;
417
418 SYM_DIMNAMES.data = DIMNAMES_STR.as_ptr() as *mut u8;
419 SYM_DIMNAMES.attrib = R_NilValue;
420 R_DimNamesSymbol = &raw mut SYM_DIMNAMES;
421
422 SYM_CLASS.data = CLASS_STR.as_ptr() as *mut u8;
423 SYM_CLASS.attrib = R_NilValue;
424 R_ClassSymbol = &raw mut SYM_CLASS;
425
426 SYM_ROWNAMES.data = ROWNAMES_STR.as_ptr() as *mut u8;
427 SYM_ROWNAMES.attrib = R_NilValue;
428 R_RowNamesSymbol = &raw mut SYM_ROWNAMES;
429
430 SYM_LEVELS.data = LEVELS_STR.as_ptr() as *mut u8;
431 SYM_LEVELS.attrib = R_NilValue;
432 R_LevelsSymbol = &raw mut SYM_LEVELS;
433
434 SYM_DOTS.data = DOTS_STR.as_ptr() as *mut u8;
435 SYM_DOTS.attrib = R_NilValue;
436 R_DotsSymbol = &raw mut SYM_DOTS;
437 }
438}
439
440extern "C" {
445 fn calloc(count: usize, size: usize) -> *mut u8;
446 fn realloc(ptr: *mut u8, size: usize) -> *mut u8;
447 fn free(ptr: *mut u8);
448}
449
450#[no_mangle]
455pub extern "C" fn Rf_allocVector(stype: c_int, length: isize) -> Sexp {
456 let s = sexp::alloc_vector(stype as u8, length as i32);
457 if !s.is_null() {
458 unsafe {
459 (*s).attrib = R_NilValue;
460 }
461 }
462 track(s);
463 s
464}
465
466#[no_mangle]
467pub extern "C" fn Rf_allocMatrix(stype: c_int, nrow: c_int, ncol: c_int) -> Sexp {
468 Rf_allocVector(stype, (nrow as isize) * (ncol as isize))
469}
470
471#[no_mangle]
476pub extern "C" fn Rf_ScalarReal(x: f64) -> Sexp {
477 let s = Rf_allocVector(sexp::REALSXP as c_int, 1);
478 unsafe {
479 *((*s).data as *mut f64) = x;
480 }
481 s
482}
483
484#[no_mangle]
485pub extern "C" fn Rf_ScalarInteger(x: c_int) -> Sexp {
486 let s = Rf_allocVector(sexp::INTSXP as c_int, 1);
487 unsafe {
488 *((*s).data as *mut i32) = x;
489 }
490 s
491}
492
493#[no_mangle]
494pub extern "C" fn Rf_ScalarLogical(x: c_int) -> Sexp {
495 let s = Rf_allocVector(sexp::LGLSXP as c_int, 1);
496 unsafe {
497 *((*s).data as *mut i32) = x;
498 }
499 s
500}
501
502#[no_mangle]
503pub extern "C" fn Rf_ScalarString(x: Sexp) -> Sexp {
504 let s = Rf_allocVector(sexp::STRSXP as c_int, 1);
505 unsafe {
506 let elts = (*s).data as *mut Sexp;
507 *elts = x;
508 }
509 s
510}
511
512#[no_mangle]
517pub extern "C" fn Rf_mkChar(str_ptr: *const c_char) -> Sexp {
518 if str_ptr.is_null() {
519 return unsafe { R_NaString };
520 }
521 let cstr = unsafe { CStr::from_ptr(str_ptr) };
522 let s = sexp::mk_char(cstr.to_str().unwrap_or(""));
523 track(s);
524 s
525}
526
527#[no_mangle]
528pub extern "C" fn Rf_mkCharLen(str_ptr: *const c_char, len: c_int) -> Sexp {
529 if str_ptr.is_null() {
530 return unsafe { R_NaString };
531 }
532 let bytes = unsafe { std::slice::from_raw_parts(str_ptr as *const u8, len as usize) };
533 let st = std::str::from_utf8(bytes).unwrap_or("");
534 let s = sexp::mk_char(st);
535 track(s);
536 s
537}
538
539#[no_mangle]
540pub extern "C" fn Rf_mkCharCE(str_ptr: *const c_char, _encoding: c_int) -> Sexp {
541 Rf_mkChar(str_ptr) }
543
544#[no_mangle]
545pub extern "C" fn Rf_getCharCE(_x: Sexp) -> c_int {
546 1 }
548
549#[no_mangle]
550pub extern "C" fn Rf_mkString(str_ptr: *const c_char) -> Sexp {
551 let s = Rf_allocVector(sexp::STRSXP as c_int, 1);
552 let ch = Rf_mkChar(str_ptr);
553 unsafe {
554 let elts = (*s).data as *mut Sexp;
555 *elts = ch;
556 }
557 s
558}
559
560#[no_mangle]
561pub extern "C" fn Rf_StringBlank(x: Sexp) -> c_int {
562 if x.is_null() {
563 return 1;
564 }
565 unsafe {
566 if x == R_NilValue || x == R_BlankString {
567 return 1;
568 }
569 if (*x).stype != sexp::CHARSXP {
570 return 1;
571 }
572 if (*x).data.is_null() {
573 return 1;
574 }
575 if *((*x).data) == 0 {
576 return 1;
577 }
578 }
579 0
580}
581
582#[no_mangle]
587pub extern "C" fn Rf_length(x: Sexp) -> c_int {
588 if x.is_null() {
589 return 0;
590 }
591 unsafe {
592 if x == R_NilValue {
593 return 0;
594 }
595 (*x).length
596 }
597}
598
599#[no_mangle]
604pub extern "C" fn Rf_install(name: *const c_char) -> Sexp {
605 if name.is_null() {
606 return unsafe { R_NilValue };
607 }
608 let cstr = unsafe { CStr::from_ptr(name) };
609 let s = cstr.to_str().unwrap_or("");
610
611 unsafe {
613 match s {
614 "names" => return R_NamesSymbol,
615 "dim" => return R_DimSymbol,
616 "dimnames" => return R_DimNamesSymbol,
617 "class" => return R_ClassSymbol,
618 "row.names" => return R_RowNamesSymbol,
619 "levels" => return R_LevelsSymbol,
620 "..." => return R_DotsSymbol,
621 _ => {}
622 }
623 }
624
625 let rec = sexp::mk_char(s); unsafe {
628 (*rec).stype = sexp::SYMSXP;
629 }
630 track(rec);
631 rec
632}
633
634#[no_mangle]
639pub extern "C" fn Rf_cons(car: Sexp, cdr: Sexp) -> Sexp {
640 unsafe {
641 let s = calloc(1, std::mem::size_of::<SexpRec>()) as Sexp;
642 if s.is_null() {
643 return R_NilValue;
644 }
645 (*s).stype = sexp::LISTSXP;
646 (*s).attrib = R_NilValue;
647 let pd = calloc(1, std::mem::size_of::<PairlistData>()) as *mut PairlistData;
648 if !pd.is_null() {
649 (*pd).car = car;
650 (*pd).cdr = cdr;
651 (*pd).tag = R_NilValue;
652 }
653 (*s).data = pd as *mut u8;
654 track(s);
655 s
656 }
657}
658
659#[no_mangle]
660pub extern "C" fn Rf_lcons(car: Sexp, cdr: Sexp) -> Sexp {
661 let s = Rf_cons(car, cdr);
662 if !s.is_null() {
663 unsafe {
664 (*s).stype = 6;
665 } }
667 s
668}
669
670#[no_mangle]
675pub extern "C" fn Rf_protect(s: Sexp) -> Sexp {
676 STATE.with(|state| {
677 state.borrow_mut().protect_stack.push(s);
678 });
679 s
680}
681
682#[no_mangle]
683pub extern "C" fn Rf_unprotect(n: c_int) {
684 STATE.with(|state| {
685 let mut st = state.borrow_mut();
686 let n = n as usize;
687 let new_len = st.protect_stack.len().saturating_sub(n);
688 st.protect_stack.truncate(new_len);
689 });
690}
691
692#[no_mangle]
697pub extern "C" fn Rf_isNull(x: Sexp) -> c_int {
698 if x.is_null() {
699 return 1;
700 }
701 (unsafe { (*x).stype } == sexp::NILSXP) as c_int
702}
703
704#[no_mangle]
705pub extern "C" fn Rf_isReal(x: Sexp) -> c_int {
706 if x.is_null() {
707 0
708 } else {
709 (unsafe { (*x).stype } == sexp::REALSXP) as c_int
710 }
711}
712#[no_mangle]
713pub extern "C" fn Rf_isInteger(x: Sexp) -> c_int {
714 if x.is_null() {
715 0
716 } else {
717 (unsafe { (*x).stype } == sexp::INTSXP) as c_int
718 }
719}
720#[no_mangle]
721pub extern "C" fn Rf_isLogical(x: Sexp) -> c_int {
722 if x.is_null() {
723 0
724 } else {
725 (unsafe { (*x).stype } == sexp::LGLSXP) as c_int
726 }
727}
728#[no_mangle]
729pub extern "C" fn Rf_isString(x: Sexp) -> c_int {
730 if x.is_null() {
731 0
732 } else {
733 (unsafe { (*x).stype } == sexp::STRSXP) as c_int
734 }
735}
736
737#[no_mangle]
738pub extern "C" fn Rf_isVector(x: Sexp) -> c_int {
739 if x.is_null() {
740 return 0;
741 }
742 let t = unsafe { (*x).stype };
743 matches!(
744 t,
745 sexp::REALSXP
746 | sexp::INTSXP
747 | sexp::LGLSXP
748 | sexp::STRSXP
749 | sexp::VECSXP
750 | sexp::RAWSXP
751 | sexp::CPLXSXP
752 ) as c_int
753}
754
755#[no_mangle]
756pub extern "C" fn Rf_inherits(x: Sexp, name: *const c_char) -> c_int {
757 if x.is_null() || name.is_null() {
758 return 0;
759 }
760 let target = unsafe { CStr::from_ptr(name) }.to_str().unwrap_or("");
761 let klass = Rf_getAttrib(x, unsafe { R_ClassSymbol });
762 if klass.is_null() || unsafe { (*klass).stype } != sexp::STRSXP {
763 return 0;
764 }
765 let len = unsafe { (*klass).length } as usize;
766 for i in 0..len {
767 let elt = unsafe { *((*klass).data as *const Sexp).add(i) };
768 if !elt.is_null() {
769 let s = unsafe { sexp::char_data(elt) };
770 if s == target {
771 return 1;
772 }
773 }
774 }
775 0
776}
777
778fn sym_eq(a: Sexp, b: Sexp) -> bool {
783 if a == b {
784 return true;
785 }
786 if a.is_null() || b.is_null() {
787 return false;
788 }
789 unsafe {
790 if (*a).stype != sexp::SYMSXP || (*b).stype != sexp::SYMSXP {
791 return false;
792 }
793 if (*a).data.is_null() || (*b).data.is_null() {
794 return false;
795 }
796 let a_str = CStr::from_ptr((*a).data as *const c_char);
797 let b_str = CStr::from_ptr((*b).data as *const c_char);
798 a_str == b_str
799 }
800}
801
802#[no_mangle]
803pub extern "C" fn Rf_getAttrib(x: Sexp, name: Sexp) -> Sexp {
804 if x.is_null() {
805 return unsafe { R_NilValue };
806 }
807 let mut attr = unsafe { (*x).attrib };
808 while !attr.is_null() && unsafe { (*attr).stype } == sexp::LISTSXP {
809 let pd = unsafe { (*attr).data as *const PairlistData };
810 if !pd.is_null() && sym_eq(unsafe { (*pd).tag }, name) {
811 return unsafe { (*pd).car };
812 }
813 attr = if pd.is_null() {
814 ptr::null_mut()
815 } else {
816 unsafe { (*pd).cdr }
817 };
818 }
819 unsafe { R_NilValue }
820}
821
822#[no_mangle]
823pub extern "C" fn Rf_setAttrib(x: Sexp, name: Sexp, val: Sexp) -> Sexp {
824 if x.is_null() {
825 return val;
826 }
827 let mut attr = unsafe { (*x).attrib };
829 while !attr.is_null() && unsafe { (*attr).stype } == sexp::LISTSXP {
830 let pd = unsafe { (*attr).data as *mut PairlistData };
831 if !pd.is_null() && sym_eq(unsafe { (*pd).tag }, name) {
832 unsafe {
833 (*pd).car = val;
834 }
835 return val;
836 }
837 attr = if pd.is_null() {
838 ptr::null_mut()
839 } else {
840 unsafe { (*pd).cdr }
841 };
842 }
843 let node = Rf_cons(val, unsafe { (*x).attrib });
845 unsafe {
846 let pd = (*node).data as *mut PairlistData;
847 if !pd.is_null() {
848 (*pd).tag = name;
849 }
850 (*x).attrib = node;
851 }
852 val
853}
854
855#[no_mangle]
860pub extern "C" fn Rf_asReal(x: Sexp) -> f64 {
861 if x.is_null() {
862 return sexp::NA_REAL;
863 }
864 unsafe {
865 match (*x).stype {
866 sexp::REALSXP if (*x).length > 0 => *((*x).data as *const f64),
867 sexp::INTSXP if (*x).length > 0 => {
868 let v = *((*x).data as *const i32);
869 if v == sexp::NA_INTEGER {
870 sexp::NA_REAL
871 } else {
872 f64::from(v)
873 }
874 }
875 sexp::LGLSXP if (*x).length > 0 => {
876 let v = *((*x).data as *const i32);
877 if v == sexp::NA_LOGICAL {
878 sexp::NA_REAL
879 } else {
880 f64::from(v)
881 }
882 }
883 _ => sexp::NA_REAL,
884 }
885 }
886}
887
888#[no_mangle]
889pub extern "C" fn Rf_asInteger(x: Sexp) -> c_int {
890 if x.is_null() {
891 return sexp::NA_INTEGER;
892 }
893 unsafe {
894 match (*x).stype {
895 sexp::INTSXP if (*x).length > 0 => *((*x).data as *const i32),
896 sexp::REALSXP if (*x).length > 0 => {
897 let v = *((*x).data as *const f64);
898 if sexp::is_na_real(v) {
899 sexp::NA_INTEGER
900 } else {
901 v as i32
902 }
903 }
904 sexp::LGLSXP if (*x).length > 0 => *((*x).data as *const i32),
905 _ => sexp::NA_INTEGER,
906 }
907 }
908}
909
910#[no_mangle]
911pub extern "C" fn Rf_asLogical(x: Sexp) -> c_int {
912 if x.is_null() {
913 return sexp::NA_LOGICAL;
914 }
915 unsafe {
916 match (*x).stype {
917 sexp::LGLSXP if (*x).length > 0 => *((*x).data as *const i32),
918 sexp::INTSXP if (*x).length > 0 => {
919 let v = *((*x).data as *const i32);
920 if v == sexp::NA_INTEGER {
921 sexp::NA_LOGICAL
922 } else {
923 (v != 0) as i32
924 }
925 }
926 sexp::REALSXP if (*x).length > 0 => {
927 let v = *((*x).data as *const f64);
928 if sexp::is_na_real(v) {
929 sexp::NA_LOGICAL
930 } else {
931 (v != 0.0) as i32
932 }
933 }
934 _ => sexp::NA_LOGICAL,
935 }
936 }
937}
938
939#[no_mangle]
940pub extern "C" fn Rf_coerceVector(x: Sexp, stype: c_int) -> Sexp {
941 if x.is_null() {
942 return unsafe { R_NilValue };
943 }
944 let from = unsafe { (*x).stype };
945 if from == stype as u8 {
946 return x;
947 }
948 let n = unsafe { (*x).length } as isize;
949 let out = Rf_protect(Rf_allocVector(stype, n));
950 for i in 0..(n as usize) {
951 unsafe {
952 match stype as u8 {
953 sexp::REALSXP => {
954 let dst = ((*out).data as *mut f64).add(i);
955 *dst = match from {
956 sexp::INTSXP => {
957 let v = *((*x).data as *const i32).add(i);
958 if v == sexp::NA_INTEGER {
959 sexp::NA_REAL
960 } else {
961 f64::from(v)
962 }
963 }
964 sexp::LGLSXP => {
965 let v = *((*x).data as *const i32).add(i);
966 if v == sexp::NA_LOGICAL {
967 sexp::NA_REAL
968 } else {
969 f64::from(v)
970 }
971 }
972 _ => sexp::NA_REAL,
973 };
974 }
975 sexp::INTSXP => {
976 let dst = ((*out).data as *mut i32).add(i);
977 *dst = match from {
978 sexp::REALSXP => {
979 let v = *((*x).data as *const f64).add(i);
980 if sexp::is_na_real(v) {
981 sexp::NA_INTEGER
982 } else {
983 v as i32
984 }
985 }
986 sexp::LGLSXP => *((*x).data as *const i32).add(i),
987 _ => sexp::NA_INTEGER,
988 };
989 }
990 sexp::LGLSXP => {
991 let dst = ((*out).data as *mut i32).add(i);
992 *dst = match from {
993 sexp::INTSXP => {
994 let v = *((*x).data as *const i32).add(i);
995 if v == sexp::NA_INTEGER {
996 sexp::NA_LOGICAL
997 } else {
998 (v != 0) as i32
999 }
1000 }
1001 sexp::REALSXP => {
1002 let v = *((*x).data as *const f64).add(i);
1003 if sexp::is_na_real(v) {
1004 sexp::NA_LOGICAL
1005 } else {
1006 (v != 0.0) as i32
1007 }
1008 }
1009 _ => sexp::NA_LOGICAL,
1010 };
1011 }
1012 _ => {}
1013 }
1014 }
1015 }
1016 Rf_unprotect(1);
1017 out
1018}
1019
1020#[no_mangle]
1025pub extern "C" fn Rf_duplicate(x: Sexp) -> Sexp {
1026 if x.is_null() {
1027 return unsafe { R_NilValue };
1028 }
1029 unsafe {
1030 if x == R_NilValue {
1031 return R_NilValue;
1032 }
1033 }
1034 let len = unsafe { (*x).length };
1035 let stype = unsafe { (*x).stype };
1036 let out = Rf_allocVector(stype as c_int, len as isize);
1037 if len > 0 {
1038 let elem_size = match stype {
1039 sexp::REALSXP => 8,
1040 sexp::INTSXP | sexp::LGLSXP => 4,
1041 sexp::RAWSXP => 1,
1042 sexp::CPLXSXP => 16,
1043 sexp::STRSXP | sexp::VECSXP => std::mem::size_of::<Sexp>(),
1044 _ => 0,
1045 };
1046 if elem_size > 0 {
1047 unsafe {
1048 ptr::copy_nonoverlapping((*x).data, (*out).data, len as usize * elem_size);
1049 }
1050 }
1051 }
1052 unsafe {
1053 (*out).attrib = (*x).attrib;
1054 }
1055 out
1056}
1057
1058#[repr(C)]
1063struct ExtPtrData {
1064 ptr: *mut c_void,
1065 tag: Sexp,
1066 prot: Sexp,
1067}
1068
1069#[no_mangle]
1070pub extern "C" fn R_MakeExternalPtr(p: *mut c_void, tag: Sexp, prot: Sexp) -> Sexp {
1071 unsafe {
1072 let s = calloc(1, std::mem::size_of::<SexpRec>()) as Sexp;
1073 if s.is_null() {
1074 return R_NilValue;
1075 }
1076 (*s).stype = 22; (*s).flags = 1; (*s).attrib = R_NilValue;
1079 let d = calloc(1, std::mem::size_of::<ExtPtrData>()) as *mut ExtPtrData;
1080 if !d.is_null() {
1081 (*d).ptr = p;
1082 (*d).tag = tag;
1083 (*d).prot = prot;
1084 }
1085 (*s).data = d as *mut u8;
1086 track(s);
1087 s
1088 }
1089}
1090
1091#[no_mangle]
1092pub extern "C" fn R_ExternalPtrAddr(s: Sexp) -> *mut c_void {
1093 if s.is_null() {
1094 return ptr::null_mut();
1095 }
1096 unsafe {
1097 if (*s).stype != 22 || (*s).data.is_null() {
1098 return ptr::null_mut();
1099 }
1100 (*((*s).data as *const ExtPtrData)).ptr
1101 }
1102}
1103
1104#[no_mangle]
1105pub extern "C" fn R_ExternalPtrTag(s: Sexp) -> Sexp {
1106 if s.is_null() {
1107 return unsafe { R_NilValue };
1108 }
1109 unsafe {
1110 if (*s).stype != 22 || (*s).data.is_null() {
1111 return R_NilValue;
1112 }
1113 (*((*s).data as *const ExtPtrData)).tag
1114 }
1115}
1116
1117#[no_mangle]
1118pub extern "C" fn R_ExternalPtrProtected(s: Sexp) -> Sexp {
1119 if s.is_null() {
1120 return unsafe { R_NilValue };
1121 }
1122 unsafe {
1123 if (*s).stype != 22 || (*s).data.is_null() {
1124 return R_NilValue;
1125 }
1126 (*((*s).data as *const ExtPtrData)).prot
1127 }
1128}
1129
1130#[no_mangle]
1131pub extern "C" fn R_ClearExternalPtr(s: Sexp) {
1132 if !s.is_null() {
1133 unsafe {
1134 if (*s).stype == 22 && !(*s).data.is_null() {
1135 (*((*s).data as *mut ExtPtrData)).ptr = ptr::null_mut();
1136 }
1137 }
1138 }
1139}
1140
1141#[no_mangle]
1142pub extern "C" fn R_SetExternalPtrAddr(s: Sexp, p: *mut c_void) {
1143 if !s.is_null() {
1144 unsafe {
1145 if (*s).stype == 22 && !(*s).data.is_null() {
1146 (*((*s).data as *mut ExtPtrData)).ptr = p;
1147 }
1148 }
1149 }
1150}
1151
1152#[no_mangle]
1153pub extern "C" fn R_RegisterCFinalizer(_s: Sexp, _fun: *const c_void) {
1154 }
1156
1157#[no_mangle]
1158pub extern "C" fn R_RegisterCFinalizerEx(_s: Sexp, _fun: *const c_void, _onexit: c_int) {
1159 }
1161
1162#[repr(C)]
1167pub struct RCallMethodDef {
1168 name: *const c_char,
1169 fun: *const (),
1170 num_args: c_int,
1171}
1172
1173#[derive(Clone, Copy)]
1175pub struct SendPtr(pub *const ());
1176unsafe impl Send for SendPtr {}
1177
1178pub static REGISTERED_CALLS: std::sync::Mutex<Vec<(String, SendPtr)>> =
1180 std::sync::Mutex::new(Vec::new());
1181
1182pub static REGISTERED_C_METHODS: std::sync::Mutex<Vec<(String, SendPtr)>> =
1184 std::sync::Mutex::new(Vec::new());
1185
1186type RCMethodDef = RCallMethodDef;
1188
1189#[no_mangle]
1190pub extern "C" fn R_registerRoutines(
1191 _info: *mut c_void,
1192 c_methods: *const RCMethodDef,
1193 call_methods: *const RCallMethodDef,
1194 _fortran_methods: *const c_void,
1195 external_methods: *const RCallMethodDef,
1196) -> c_int {
1197 if !c_methods.is_null() {
1199 let mut reg = REGISTERED_C_METHODS
1200 .lock()
1201 .expect("lock registered C methods");
1202 unsafe {
1203 let mut i = 0;
1204 loop {
1205 let entry = &*c_methods.add(i);
1206 if entry.name.is_null() {
1207 break;
1208 }
1209 let name = CStr::from_ptr(entry.name)
1210 .to_str()
1211 .unwrap_or("")
1212 .to_string();
1213 if !name.is_empty() {
1214 reg.push((name, SendPtr(entry.fun)));
1215 }
1216 i += 1;
1217 }
1218 }
1219 }
1220 if !call_methods.is_null() {
1222 register_call_methods(call_methods);
1223 }
1224 if !external_methods.is_null() {
1226 register_call_methods(external_methods);
1227 }
1228 1
1229}
1230
1231fn register_call_methods(methods: *const RCallMethodDef) {
1232 let mut reg = REGISTERED_CALLS.lock().expect("lock registered calls");
1233 unsafe {
1234 let mut i = 0;
1235 loop {
1236 let entry = &*methods.add(i);
1237 if entry.name.is_null() {
1238 break;
1239 }
1240 let name = CStr::from_ptr(entry.name)
1241 .to_str()
1242 .unwrap_or("")
1243 .to_string();
1244 if !name.is_empty() {
1245 reg.push((name, SendPtr(entry.fun)));
1246 }
1247 i += 1;
1248 }
1249 }
1250}
1251
1252#[no_mangle]
1253pub extern "C" fn R_useDynamicSymbols(_info: *mut c_void, _value: c_int) {}
1254#[no_mangle]
1255pub extern "C" fn R_forceSymbols(_info: *mut c_void, _value: c_int) {}
1256
1257pub fn find_registered_call(name: &str) -> Option<*const ()> {
1259 let reg = REGISTERED_CALLS.lock().expect("lock registered calls");
1260 reg.iter().find(|(n, _)| n == name).map(|(_, ptr)| ptr.0)
1261}
1262
1263pub fn find_registered_c_method(name: &str) -> Option<*const ()> {
1265 let reg = REGISTERED_C_METHODS
1266 .lock()
1267 .expect("lock registered C methods");
1268 reg.iter().find(|(n, _)| n == name).map(|(_, ptr)| ptr.0)
1269}
1270
1271pub fn registered_call_names() -> Vec<String> {
1273 let reg = REGISTERED_CALLS.lock().expect("lock registered calls");
1274 reg.iter().map(|(n, _)| n.clone()).collect()
1275}
1276
1277pub fn registered_c_method_names() -> Vec<String> {
1279 let reg = REGISTERED_C_METHODS
1280 .lock()
1281 .expect("lock registered C methods");
1282 reg.iter().map(|(n, _)| n.clone()).collect()
1283}
1284
1285static CCALLABLE: std::sync::Mutex<Vec<(String, String, SendPtr)>> =
1290 std::sync::Mutex::new(Vec::new());
1291
1292#[no_mangle]
1293pub extern "C" fn R_RegisterCCallable(
1294 package: *const c_char,
1295 name: *const c_char,
1296 fptr: *const (),
1297) {
1298 if package.is_null() || name.is_null() {
1299 return;
1300 }
1301 let pkg = unsafe { CStr::from_ptr(package) }
1302 .to_str()
1303 .unwrap_or("")
1304 .to_string();
1305 let nm = unsafe { CStr::from_ptr(name) }
1306 .to_str()
1307 .unwrap_or("")
1308 .to_string();
1309 let mut reg = CCALLABLE.lock().expect("lock ccallable");
1310 reg.push((pkg, nm, SendPtr(fptr)));
1311}
1312
1313#[no_mangle]
1314pub extern "C" fn R_GetCCallable(package: *const c_char, name: *const c_char) -> *const () {
1315 if package.is_null() || name.is_null() {
1316 return ptr::null();
1317 }
1318 let pkg = unsafe { CStr::from_ptr(package) }.to_str().unwrap_or("");
1319 let nm = unsafe { CStr::from_ptr(name) }.to_str().unwrap_or("");
1320 let reg = CCALLABLE.lock().expect("lock ccallable");
1321 if let Some(ptr) = reg
1323 .iter()
1324 .rfind(|(p, n, _)| p == pkg && n == nm)
1325 .map(|(_, _, ptr)| ptr.0)
1326 {
1327 return ptr;
1328 }
1329 if pkg == "rlang" {
1332 tracing::debug!(name = nm, "returning stub for unregistered rlang CCallable");
1333 if nm.contains("type_friendly") || nm.contains("format_error_arg") {
1336 return rlang_ccallable_str_stub as *const ();
1337 }
1338 return rlang_ccallable_sexp_stub as *const ();
1339 }
1340 ptr::null()
1341}
1342
1343extern "C" fn rlang_ccallable_str_stub() -> *const c_char {
1345 c"<unknown>".as_ptr()
1346}
1347
1348extern "C" fn rlang_ccallable_sexp_stub() -> Sexp {
1350 unsafe { R_NilValue }
1351}
1352
1353#[no_mangle]
1358pub extern "C" fn R_alloc(nelem: usize, eltsize: c_int) -> *mut c_char {
1359 let bytes = nelem * eltsize as usize;
1360 unsafe {
1361 let ptr = calloc(1, bytes);
1362 if !ptr.is_null() {
1363 let dummy = calloc(1, std::mem::size_of::<SexpRec>()) as Sexp;
1365 if !dummy.is_null() {
1366 (*dummy).stype = sexp::RAWSXP;
1367 (*dummy).data = ptr;
1368 (*dummy).length = bytes as i32;
1369 (*dummy).attrib = R_NilValue;
1370 track(dummy);
1371 }
1372 }
1373 ptr as *mut c_char
1374 }
1375}
1376
1377#[no_mangle]
1383pub extern "C" fn Rf_lengthgets(x: Sexp, new_len: c_int) -> Sexp {
1384 if x.is_null() {
1385 return unsafe { R_NilValue };
1386 }
1387 let stype = unsafe { (*x).stype };
1388 let old_len = unsafe { (*x).length };
1389 let out = Rf_allocVector(stype as c_int, new_len as isize);
1390 let copy_len = std::cmp::min(old_len, new_len) as usize;
1391 if copy_len > 0 {
1392 let elem_size = match stype {
1393 sexp::REALSXP => 8,
1394 sexp::INTSXP | sexp::LGLSXP => 4,
1395 sexp::RAWSXP => 1,
1396 sexp::CPLXSXP => 16,
1397 sexp::STRSXP | sexp::VECSXP => std::mem::size_of::<Sexp>(),
1398 _ => 0,
1399 };
1400 if elem_size > 0 {
1401 unsafe {
1402 ptr::copy_nonoverlapping((*x).data, (*out).data, copy_len * elem_size);
1403 }
1404 }
1405 }
1406 unsafe {
1408 (*out).attrib = (*x).attrib;
1409 }
1410 out
1411}
1412
1413#[no_mangle]
1414pub extern "C" fn R_CheckUserInterrupt() {}
1415
1416#[no_mangle]
1417pub extern "C" fn R_do_slot(obj: Sexp, name: Sexp) -> Sexp {
1418 Rf_getAttrib(obj, name)
1419}
1420
1421#[no_mangle]
1422pub extern "C" fn Rf_nrows(x: Sexp) -> c_int {
1423 let dim = Rf_getAttrib(x, unsafe { R_DimSymbol });
1424 if !dim.is_null() && unsafe { (*dim).stype } == sexp::INTSXP && unsafe { (*dim).length } >= 1 {
1425 return unsafe { *((*dim).data as *const i32) };
1426 }
1427 Rf_length(x)
1428}
1429
1430#[no_mangle]
1431pub extern "C" fn Rf_ncols(x: Sexp) -> c_int {
1432 let dim = Rf_getAttrib(x, unsafe { R_DimSymbol });
1433 if !dim.is_null() && unsafe { (*dim).stype } == sexp::INTSXP && unsafe { (*dim).length } >= 2 {
1434 return unsafe { *((*dim).data as *const i32).add(1) };
1435 }
1436 1
1437}
1438
1439#[no_mangle]
1442pub extern "C" fn Rf_eval(expr: Sexp, _env: Sexp) -> Sexp {
1443 if expr.is_null() {
1444 return unsafe { R_NilValue };
1445 }
1446
1447 if unsafe { (*expr).stype == sexp::LANGSXP && (*expr).length == -1 } {
1450 let idx = unsafe { (*expr).data as usize };
1451 if let Some(stashed) = get_stashed_rvalue(idx) {
1452 let eval_fn = STATE.with(|state| state.borrow().callbacks.eval_expr);
1453 let result = eval_fn.map(|f| f(&stashed));
1454 return match result {
1455 Some(Ok(val)) => {
1456 let s = super::convert::rvalue_to_sexp(&val);
1457 track(s);
1458 s
1459 }
1460 Some(Err(_)) => unsafe { R_NilValue },
1461 None => unsafe { R_NilValue },
1462 };
1463 }
1464 }
1465
1466 if unsafe { (*expr).stype == sexp::LANGSXP && (*expr).length != -1 } {
1469 if let Some(call_text) = langsxp_to_text(expr) {
1470 let (parse_fn, eval_fn) = STATE.with(|state| {
1472 let st = state.borrow();
1473 (st.callbacks.parse_text, st.callbacks.eval_expr)
1474 });
1475 if let (Some(parse), Some(eval)) = (parse_fn, eval_fn) {
1476 let result = match parse(&call_text) {
1477 Ok(parsed) => Some(eval(&parsed)),
1478 Err(e) => Some(Err(e)),
1479 };
1480 return match result {
1481 Some(Ok(val)) => {
1482 let s = super::convert::rvalue_to_sexp(&val);
1483 track(s);
1484 s
1485 }
1486 Some(Err(_)) | None => unsafe { R_NilValue },
1487 };
1488 }
1489 }
1490 }
1491
1492 let rval = unsafe { super::convert::sexp_to_rvalue(expr) };
1494
1495 let (find_var, eval_expr) = STATE.with(|state| {
1498 let st = state.borrow();
1499 (st.callbacks.find_var, st.callbacks.eval_expr)
1500 });
1501
1502 let mut result: Option<
1504 Result<crate::interpreter::value::RValue, crate::interpreter::value::RError>,
1505 > = None;
1506
1507 if let Some(find) = find_var {
1508 if let crate::interpreter::value::RValue::Vector(ref rv) = rval {
1510 if let crate::interpreter::value::Vector::Character(ref c) = rv.inner {
1511 if c.len() == 1 {
1512 if let Some(Some(name)) = c.first() {
1513 if let Some(val) = find(name) {
1514 result = Some(Ok(val));
1515 }
1516 }
1517 }
1518 }
1519 }
1520 if result.is_none() {
1522 unsafe {
1523 if (*expr).stype == sexp::SYMSXP && !(*expr).data.is_null() {
1524 let name = sexp::char_data(expr);
1525 if !name.is_empty() {
1526 if let Some(val) = find(name) {
1527 result = Some(Ok(val));
1528 }
1529 }
1530 }
1531 }
1532 }
1533 }
1534
1535 if result.is_none() {
1537 if let Some(eval_fn) = eval_expr {
1538 result = Some(eval_fn(&rval));
1539 }
1540 }
1541
1542 match result {
1543 Some(Ok(val)) => {
1544 let s = super::convert::rvalue_to_sexp(&val);
1545 track(s);
1546 s
1547 }
1548 Some(Err(_)) => unsafe { R_NilValue },
1549 None => unsafe { R_NilValue },
1550 }
1551}
1552
1553#[no_mangle]
1555pub extern "C" fn R_Serialize(_s: Sexp, _stream: *mut c_void) {
1556 let _ = std::io::Write::write_all(
1557 &mut std::io::stderr(),
1558 b"Warning: R_Serialize() is a stub in miniR -- serialization from C not supported\n",
1559 );
1560}
1561
1562#[no_mangle]
1564pub extern "C" fn Rf_xlength(x: Sexp) -> isize {
1565 Rf_length(x) as isize
1566}
1567
1568#[no_mangle]
1570pub extern "C" fn Rf_xlengthgets(x: Sexp, new_len: isize) -> Sexp {
1571 Rf_lengthgets(x, new_len as c_int)
1572}
1573
1574#[no_mangle]
1576pub extern "C" fn Rf_mkCharLenCE(str_ptr: *const c_char, len: c_int, _encoding: c_int) -> Sexp {
1577 Rf_mkCharLen(str_ptr, len)
1578}
1579
1580#[no_mangle]
1582pub extern "C" fn Rf_translateChar(x: Sexp) -> *const c_char {
1583 if x.is_null() {
1584 return c"".as_ptr();
1585 }
1586 unsafe { (*x).data as *const c_char }
1587}
1588
1589#[no_mangle]
1591pub extern "C" fn Rf_classgets(x: Sexp, klass: Sexp) -> Sexp {
1592 Rf_setAttrib(x, unsafe { R_ClassSymbol }, klass);
1593 x
1594}
1595
1596#[no_mangle]
1598pub extern "C" fn Rf_namesgets(x: Sexp, names: Sexp) -> Sexp {
1599 Rf_setAttrib(x, unsafe { R_NamesSymbol }, names);
1600 x
1601}
1602
1603#[no_mangle]
1605pub extern "C" fn Rf_dimgets(x: Sexp, dim: Sexp) -> Sexp {
1606 Rf_setAttrib(x, unsafe { R_DimSymbol }, dim);
1607 x
1608}
1609
1610#[no_mangle]
1612pub extern "C" fn GetRNGstate() {}
1613#[no_mangle]
1614pub extern "C" fn PutRNGstate() {}
1615
1616#[no_mangle]
1618pub extern "C" fn unif_rand() -> f64 {
1619 use std::cell::RefCell;
1620 thread_local! {
1621 static RNG: RefCell<u64> = const { RefCell::new(0x12345678) };
1622 }
1623 RNG.with(|rng| {
1624 let mut state = rng.borrow_mut();
1625 *state ^= *state << 13;
1627 *state ^= *state >> 7;
1628 *state ^= *state << 17;
1629 (*state as f64) / (u64::MAX as f64)
1630 })
1631}
1632
1633#[no_mangle]
1635pub static mut R_EmptyEnv: Sexp = ptr::null_mut();
1636
1637#[no_mangle]
1638pub static mut R_MissingArg: Sexp = ptr::null_mut();
1639
1640#[no_mangle]
1642pub extern "C" fn R_PreserveObject(x: Sexp) {
1643 if x.is_null() {
1644 return;
1645 }
1646 unsafe {
1647 if (*x).flags & 0x01 != 0 {
1648 return; }
1650 (*x).flags |= 0x01;
1651
1652 if matches!((*x).stype, sexp::LISTSXP | sexp::LANGSXP) && !(*x).data.is_null() {
1654 let pd = (*x).data as *const PairlistData;
1655 R_PreserveObject((*pd).car);
1656 R_PreserveObject((*pd).cdr);
1657 }
1658 if (*x).stype == sexp::VECSXP && !(*x).data.is_null() {
1660 let elts = (*x).data as *const Sexp;
1661 for i in 0..(*x).length.max(0) as usize {
1662 R_PreserveObject(*elts.add(i));
1663 }
1664 }
1665 if !(*x).attrib.is_null() {
1667 R_PreserveObject((*x).attrib);
1668 }
1669 }
1670}
1671
1672#[no_mangle]
1674pub extern "C" fn R_ReleaseObject(x: Sexp) {
1675 if !x.is_null() {
1676 unsafe {
1677 (*x).flags &= !0x01;
1678 }
1679 }
1680}
1681
1682#[no_mangle]
1684pub extern "C" fn MARK_NOT_MUTABLE(_x: Sexp) {}
1685
1686#[no_mangle]
1688pub extern "C" fn PRENV(_x: Sexp) -> Sexp {
1689 unsafe { R_NilValue }
1690}
1691
1692#[no_mangle]
1694pub extern "C" fn PREXPR(_x: Sexp) -> Sexp {
1695 unsafe { R_NilValue }
1696}
1697
1698#[no_mangle]
1700pub extern "C" fn Rf_isVectorAtomic(x: Sexp) -> c_int {
1701 if x.is_null() {
1702 return 0;
1703 }
1704 let t = unsafe { (*x).stype };
1705 matches!(
1706 t,
1707 sexp::REALSXP | sexp::INTSXP | sexp::LGLSXP | sexp::STRSXP | sexp::RAWSXP | sexp::CPLXSXP
1708 ) as c_int
1709}
1710
1711#[no_mangle]
1712pub extern "C" fn Rf_isVectorList(x: Sexp) -> c_int {
1713 if x.is_null() {
1714 return 0;
1715 }
1716 (unsafe { (*x).stype } == sexp::VECSXP) as c_int
1717}
1718
1719#[no_mangle]
1720pub extern "C" fn Rf_isMatrix(x: Sexp) -> c_int {
1721 let dim = Rf_getAttrib(x, unsafe { R_DimSymbol });
1722 (!dim.is_null() && unsafe { (*dim).stype } == sexp::INTSXP && unsafe { (*dim).length } == 2)
1723 as c_int
1724}
1725
1726#[no_mangle]
1727pub extern "C" fn Rf_isNumeric(x: Sexp) -> c_int {
1728 if x.is_null() {
1729 return 0;
1730 }
1731 let t = unsafe { (*x).stype };
1732 matches!(t, sexp::REALSXP | sexp::INTSXP) as c_int
1733}
1734
1735#[no_mangle]
1736pub extern "C" fn Rf_isFunction(x: Sexp) -> c_int {
1737 if x.is_null() {
1738 return 0;
1739 }
1740 let t = unsafe { (*x).stype };
1741 matches!(t, 3 | 7 | 8) as c_int }
1743
1744#[no_mangle]
1745pub extern "C" fn Rf_isEnvironment(x: Sexp) -> c_int {
1746 if x.is_null() {
1747 return 0;
1748 }
1749 (unsafe { (*x).stype } == 4) as c_int }
1751
1752#[no_mangle]
1754pub extern "C" fn R_ProtectWithIndex(s: Sexp, pi: *mut c_int) {
1755 Rf_protect(s);
1756 STATE.with(|state| {
1757 let st = state.borrow();
1758 if !pi.is_null() {
1759 unsafe {
1760 *pi = (st.protect_stack.len() - 1) as c_int;
1761 }
1762 }
1763 });
1764}
1765
1766#[no_mangle]
1767pub extern "C" fn R_Reprotect(s: Sexp, i: c_int) {
1768 STATE.with(|state| {
1769 let mut st = state.borrow_mut();
1770 let idx = i as usize;
1771 if idx < st.protect_stack.len() {
1772 st.protect_stack[idx] = s;
1773 }
1774 });
1775}
1776
1777#[no_mangle]
1779pub extern "C" fn Rf_findVar(sym: Sexp, env: Sexp) -> Sexp {
1780 if sym.is_null() {
1781 return unsafe { R_UnboundValue };
1782 }
1783
1784 if !env.is_null() && unsafe { (*env).stype } == sexp::ENVSXP {
1786 let var_name = unsafe { sexp::char_data(sym) };
1787 if let Some(e) = unsafe { super::convert::env_from_sexp(env) } {
1788 if let Some(val) = e.get(var_name) {
1789 let s = super::convert::rvalue_to_sexp(&val);
1790 track(s);
1791 return s;
1792 }
1793 }
1794 let mut node = unsafe { (*env).attrib };
1796 while !node.is_null() && unsafe { (*node).stype } == sexp::LISTSXP {
1797 let pd = unsafe { (*node).data as *const sexp::PairlistData };
1798 if !pd.is_null() && sym_eq(unsafe { (*pd).tag }, sym) {
1799 return unsafe { (*pd).car };
1800 }
1801 node = if pd.is_null() {
1802 ptr::null_mut()
1803 } else {
1804 unsafe { (*pd).cdr }
1805 };
1806 }
1807 return unsafe { R_UnboundValue };
1808 }
1809
1810 let name = unsafe { sexp::char_data(sym) };
1812 if name.is_empty() {
1813 return unsafe { R_UnboundValue };
1814 }
1815 let result = STATE.with(|state| {
1817 let st = state.borrow();
1818 if let Some(find) = st.callbacks.find_var {
1819 find(name)
1820 } else {
1821 None
1822 }
1823 });
1824 match result {
1825 Some(val) => {
1826 let s = super::convert::rvalue_to_sexp(&val);
1828 track(s);
1829 s
1830 }
1831 None => unsafe { R_UnboundValue },
1832 }
1833}
1834
1835#[no_mangle]
1836pub extern "C" fn Rf_findVarInFrame3(env: Sexp, sym: Sexp, _inherits: c_int) -> Sexp {
1837 Rf_findVar(sym, env)
1838}
1839
1840#[no_mangle]
1842pub extern "C" fn R_ExecWithCleanup(
1843 fun: Option<unsafe extern "C" fn(*mut c_void) -> Sexp>,
1844 data: *mut c_void,
1845 cleanup: Option<unsafe extern "C" fn(*mut c_void)>,
1846 cleandata: *mut c_void,
1847) -> Sexp {
1848 let result = match fun {
1849 Some(f) => unsafe { f(data) },
1850 None => unsafe { R_NilValue },
1851 };
1852 if let Some(c) = cleanup {
1853 unsafe {
1854 c(cleandata);
1855 }
1856 }
1857 result
1858}
1859
1860#[no_mangle]
1862pub extern "C" fn R_ExternalPtrAddrFn(s: Sexp) -> *mut c_void {
1863 R_ExternalPtrAddr(s)
1864}
1865
1866#[no_mangle]
1868pub extern "C" fn Rf_lang1(s: Sexp) -> Sexp {
1869 Rf_lcons(s, unsafe { R_NilValue })
1870}
1871
1872#[no_mangle]
1873pub extern "C" fn Rf_lang2(s: Sexp, t: Sexp) -> Sexp {
1874 Rf_lcons(s, Rf_cons(t, unsafe { R_NilValue }))
1875}
1876
1877#[no_mangle]
1878pub extern "C" fn Rf_lang3(s: Sexp, t: Sexp, u: Sexp) -> Sexp {
1879 Rf_lcons(s, Rf_cons(t, Rf_cons(u, unsafe { R_NilValue })))
1880}
1881
1882#[no_mangle]
1883pub extern "C" fn Rf_lang4(s: Sexp, t: Sexp, u: Sexp, v: Sexp) -> Sexp {
1884 Rf_lcons(s, Rf_cons(t, Rf_cons(u, Rf_cons(v, unsafe { R_NilValue }))))
1885}
1886
1887#[no_mangle]
1889pub extern "C" fn S_alloc(nelem: isize, eltsize: c_int) -> *mut c_char {
1890 R_alloc(nelem as usize, eltsize)
1891}
1892
1893#[no_mangle]
1895pub extern "C" fn Rf_type2char(stype: c_int) -> *const c_char {
1896 match stype as u8 {
1897 sexp::NILSXP => c"NULL".as_ptr(),
1898 sexp::LGLSXP => c"logical".as_ptr(),
1899 sexp::INTSXP => c"integer".as_ptr(),
1900 sexp::REALSXP => c"double".as_ptr(),
1901 sexp::CPLXSXP => c"complex".as_ptr(),
1902 sexp::STRSXP => c"character".as_ptr(),
1903 sexp::VECSXP => c"list".as_ptr(),
1904 sexp::RAWSXP => c"raw".as_ptr(),
1905 _ => c"unknown".as_ptr(),
1906 }
1907}
1908
1909#[no_mangle]
1911pub extern "C" fn R_finite(x: f64) -> c_int {
1912 x.is_finite() as c_int
1913}
1914
1915#[no_mangle]
1917pub extern "C" fn Rf_nchar(
1918 x: Sexp,
1919 _ntype: c_int,
1920 _allow_na: c_int,
1921 _keep_na: c_int,
1922 _msg_name: *const c_char,
1923) -> c_int {
1924 if x.is_null() {
1925 return 0;
1926 }
1927 unsafe {
1928 if (*x).stype == sexp::CHARSXP && !(*x).data.is_null() {
1929 let s = CStr::from_ptr((*x).data as *const c_char);
1930 s.to_bytes().len() as c_int
1931 } else {
1932 0
1933 }
1934 }
1935}
1936
1937#[no_mangle]
1939pub extern "C" fn Rf_isFrame(x: Sexp) -> c_int {
1940 Rf_inherits(x, c"data.frame".as_ptr())
1941}
1942
1943#[no_mangle]
1951pub extern "C" fn R_check_class_etc(x: Sexp, valid: *const *const c_char) -> c_int {
1952 if x.is_null() || valid.is_null() {
1953 return -1;
1954 }
1955
1956 let stype = if x.is_null() {
1958 0
1959 } else {
1960 unsafe { (*x).stype }
1961 };
1962 let dim_sym = Rf_install(c"dim".as_ptr());
1963 let dim = Rf_getAttrib(x, dim_sym);
1964 let dim_len = if dim.is_null() {
1965 0
1966 } else {
1967 (unsafe { (*dim).length }) as usize
1968 };
1969
1970 let mut i = 0;
1971 loop {
1972 let class_ptr = unsafe { *valid.add(i) };
1973 if class_ptr.is_null() {
1974 break;
1975 }
1976 if Rf_inherits(x, class_ptr) != 0 {
1978 return i as c_int;
1979 }
1980 if let Ok(name) = unsafe { CStr::from_ptr(class_ptr) }.to_str() {
1982 let matches = match name {
1983 "matrix" => dim_len == 2,
1984 "array" => dim_len > 0,
1985 "numeric" => stype == sexp::REALSXP,
1986 "integer" => stype == sexp::INTSXP,
1987 "logical" => stype == sexp::LGLSXP,
1988 "character" => stype == sexp::STRSXP,
1989 "complex" => stype == sexp::CPLXSXP,
1990 "raw" => stype == sexp::RAWSXP,
1991 "list" => stype == sexp::VECSXP,
1992 _ => false,
1993 };
1994 if matches {
1995 return i as c_int;
1996 }
1997 }
1998 i += 1;
1999 }
2000 -1
2001}
2002
2003#[no_mangle]
2007pub extern "C" fn R_new_custom_connection(
2008 _description: *const c_char,
2009 _mode: *const c_char,
2010 _class_name: *const c_char,
2011 ptr: *mut *mut SexpRec, ) -> Sexp {
2013 let layout = std::alloc::Layout::from_size_align(512, 8).unwrap();
2016 let conn = unsafe { std::alloc::alloc_zeroed(layout) as *mut SexpRec };
2017 if !ptr.is_null() {
2018 unsafe { *ptr = conn };
2019 }
2020 let sexp = sexp::alloc_vector(sexp::INTSXP, 1);
2022 if !sexp.is_null() {
2023 let data = unsafe { (*sexp).data as *mut i64 };
2024 if !data.is_null() {
2025 unsafe { *data = 3 };
2026 }
2027 }
2028 sexp
2029}
2030
2031#[no_mangle]
2034pub extern "C" fn R_GetConnection(_con: Sexp) -> *mut SexpRec {
2035 ptr::null_mut()
2036}
2037
2038#[no_mangle]
2040pub extern "C" fn Rf_copyMostAttrib(from: Sexp, to: Sexp) {
2041 if from.is_null() || to.is_null() {
2042 return;
2043 }
2044 unsafe {
2045 (*to).attrib = (*from).attrib;
2046 }
2047}
2048
2049#[no_mangle]
2051pub extern "C" fn Rf_nthcdr(mut s: Sexp, n: c_int) -> Sexp {
2052 for _ in 0..n {
2053 if s.is_null() {
2054 return unsafe { R_NilValue };
2055 }
2056 unsafe {
2057 if (*s).stype == sexp::LISTSXP && !(*s).data.is_null() {
2058 s = (*((*s).data as *const PairlistData)).cdr;
2059 } else {
2060 return R_NilValue;
2061 }
2062 }
2063 }
2064 s
2065}
2066
2067#[no_mangle]
2069pub extern "C" fn R_FlushConsole() {}
2070
2071#[no_mangle]
2073pub extern "C" fn R_do_slot_assign(obj: Sexp, name: Sexp, val: Sexp) -> Sexp {
2074 Rf_setAttrib(obj, name, val);
2075 obj
2076}
2077
2078#[no_mangle]
2080pub extern "C" fn Rf_allocList(n: c_int) -> Sexp {
2081 let mut result = unsafe { R_NilValue };
2082 for _ in 0..n {
2083 result = Rf_cons(unsafe { R_NilValue }, result);
2084 }
2085 result
2086}
2087
2088#[no_mangle]
2090pub extern "C" fn Rf_match(_table: Sexp, x: Sexp, nomatch: c_int) -> Sexp {
2091 let n = if x.is_null() {
2092 0
2093 } else {
2094 (unsafe { (*x).length }) as isize
2095 };
2096 let result = Rf_allocVector(sexp::INTSXP as c_int, n);
2097 if n > 0 {
2098 unsafe {
2099 let ptr = (*result).data as *mut i32;
2100 for i in 0..n as usize {
2101 *ptr.add(i) = nomatch;
2102 }
2103 }
2104 }
2105 result
2106}
2107
2108#[no_mangle]
2110pub extern "C" fn Rf_asCharacterFactor(_x: Sexp) -> Sexp {
2111 Rf_allocVector(sexp::STRSXP as c_int, 0)
2112}
2113
2114#[no_mangle]
2116pub extern "C" fn R_isort(x: *mut c_int, n: c_int) {
2117 if x.is_null() || n <= 0 {
2118 return;
2119 }
2120 let slice = unsafe { std::slice::from_raw_parts_mut(x, n as usize) };
2121 slice.sort_unstable();
2122}
2123
2124#[no_mangle]
2126pub extern "C" fn R_rsort(x: *mut f64, n: c_int) {
2127 if x.is_null() || n <= 0 {
2128 return;
2129 }
2130 let slice = unsafe { std::slice::from_raw_parts_mut(x, n as usize) };
2131 slice.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
2132}
2133
2134#[no_mangle]
2136pub extern "C" fn revsort(x: *mut f64, index: *mut c_int, n: c_int) {
2137 if x.is_null() || n <= 0 {
2138 return;
2139 }
2140 let xs = unsafe { std::slice::from_raw_parts_mut(x, n as usize) };
2141 let mut is = if index.is_null() {
2142 None
2143 } else {
2144 Some(unsafe { std::slice::from_raw_parts_mut(index, n as usize) })
2145 };
2146 let mut pairs: Vec<(f64, i32)> = xs
2148 .iter()
2149 .enumerate()
2150 .map(|(i, &v)| (v, is.as_ref().map_or(i as i32, |idx| idx[i])))
2151 .collect();
2152 pairs.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(std::cmp::Ordering::Equal));
2153 for (i, (v, idx)) in pairs.into_iter().enumerate() {
2154 xs[i] = v;
2155 if let Some(ref mut is) = is {
2156 is[i] = idx;
2157 }
2158 }
2159}
2160
2161#[no_mangle]
2163pub extern "C" fn Rf_installTrChar(x: Sexp) -> Sexp {
2164 Rf_installChar(x)
2165}
2166
2167#[no_mangle]
2169pub static mut R_NameSymbol: Sexp = ptr::null_mut();
2170
2171#[no_mangle]
2173pub extern "C" fn rsort_with_index(x: *mut f64, index: *mut c_int, n: c_int) {
2174 revsort(x, index, n);
2175}
2176
2177#[no_mangle]
2179pub extern "C" fn R_qsort_I(v: *mut f64, _ii: *mut c_int, lo: c_int, hi: c_int) {
2180 if v.is_null() || lo >= hi {
2181 return;
2182 }
2183 let n = (hi - lo + 1) as usize;
2184 let offset = lo.max(1) as usize - 1;
2185 let vs = unsafe { std::slice::from_raw_parts_mut(v.add(offset), n) };
2186 vs.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
2187}
2188
2189#[no_mangle]
2190pub extern "C" fn R_qsort_int_I(v: *mut c_int, _ii: *mut c_int, lo: c_int, hi: c_int) {
2191 if v.is_null() || lo >= hi {
2192 return;
2193 }
2194 let n = (hi - lo + 1) as usize;
2195 let offset = lo.max(1) as usize - 1;
2196 let vs = unsafe { std::slice::from_raw_parts_mut(v.add(offset), n) };
2197 vs.sort_unstable();
2198}
2199
2200#[no_mangle]
2202pub extern "C" fn R_qsort(v: *mut f64, lo: c_int, hi: c_int) {
2203 R_qsort_I(v, ptr::null_mut(), lo, hi);
2204}
2205#[no_mangle]
2206pub extern "C" fn R_qsort_int(v: *mut c_int, lo: c_int, hi: c_int) {
2207 R_qsort_int_I(v, ptr::null_mut(), lo, hi);
2208}
2209
2210#[no_mangle]
2212pub extern "C" fn Rf_dimnamesgets(x: Sexp, val: Sexp) -> Sexp {
2213 Rf_setAttrib(x, unsafe { R_DimNamesSymbol }, val);
2214 x
2215}
2216
2217#[no_mangle]
2219pub extern "C" fn dgemv_(
2220 _trans: *const u8,
2221 _m: *const c_int,
2222 _n: *const c_int,
2223 _alpha: *const f64,
2224 _a: *const f64,
2225 _lda: *const c_int,
2226 _x: *const f64,
2227 _incx: *const c_int,
2228 _beta: *const f64,
2229 _y: *mut f64,
2230 _incy: *const c_int,
2231) {
2232}
2233#[no_mangle]
2234pub extern "C" fn dpotrf_(
2235 _uplo: *const u8,
2236 _n: *const c_int,
2237 _a: *mut f64,
2238 _lda: *const c_int,
2239 _info: *mut c_int,
2240) {
2241}
2242#[no_mangle]
2243pub extern "C" fn dpotri_(
2244 _uplo: *const u8,
2245 _n: *const c_int,
2246 _a: *mut f64,
2247 _lda: *const c_int,
2248 _info: *mut c_int,
2249) {
2250}
2251#[no_mangle]
2252pub extern "C" fn dtrsm_(
2253 _side: *const u8,
2254 _uplo: *const u8,
2255 _transa: *const u8,
2256 _diag: *const u8,
2257 _m: *const c_int,
2258 _n: *const c_int,
2259 _alpha: *const f64,
2260 _a: *const f64,
2261 _lda: *const c_int,
2262 _b: *mut f64,
2263 _ldb: *const c_int,
2264) {
2265}
2266
2267#[no_mangle]
2269pub extern "C" fn Rf_allocArray(stype: c_int, dims: Sexp) -> Sexp {
2270 let total = if dims.is_null() {
2272 0
2273 } else {
2274 let n = unsafe { (*dims).length } as usize;
2275 let mut product: isize = 1;
2276 for i in 0..n {
2277 let d = unsafe { *((*dims).data as *const i32).add(i) } as isize;
2278 product *= d;
2279 }
2280 product
2281 };
2282 let result = Rf_allocVector(stype, total);
2283 Rf_setAttrib(result, unsafe { R_DimSymbol }, dims);
2284 result
2285}
2286
2287#[no_mangle]
2291pub extern "C" fn dqrdc2_(
2292 _x: *mut f64,
2293 _ldx: *const c_int,
2294 _n: *const c_int,
2295 _p: *const c_int,
2296 _tol: *const f64,
2297 _k: *mut c_int,
2298 _qraux: *mut f64,
2299 _jpvt: *mut c_int,
2300 _work: *mut f64,
2301) {
2302 std::io::Write::write_all(
2303 &mut std::io::stderr(),
2304 b"Warning: dqrdc2_ is a stub in miniR\n",
2305 )
2306 .ok();
2307}
2308
2309#[no_mangle]
2310pub extern "C" fn dqrsl_(
2311 _x: *mut f64,
2312 _ldx: *const c_int,
2313 _n: *const c_int,
2314 _k: *const c_int,
2315 _qraux: *mut f64,
2316 _y: *mut f64,
2317 _qy: *mut f64,
2318 _qty: *mut f64,
2319 _b: *mut f64,
2320 _rsd: *mut f64,
2321 _xb: *mut f64,
2322 _job: *const c_int,
2323 _info: *mut c_int,
2324) {
2325}
2326
2327#[no_mangle]
2328pub extern "C" fn dgemm_(
2329 _transa: *const u8,
2330 _transb: *const u8,
2331 _m: *const c_int,
2332 _n: *const c_int,
2333 _k: *const c_int,
2334 _alpha: *const f64,
2335 _a: *const f64,
2336 _lda: *const c_int,
2337 _b: *const f64,
2338 _ldb: *const c_int,
2339 _beta: *const f64,
2340 _c: *mut f64,
2341 _ldc: *const c_int,
2342) {
2343}
2344
2345#[no_mangle]
2346pub extern "C" fn dsyrk_(
2347 _uplo: *const u8,
2348 _trans: *const u8,
2349 _n: *const c_int,
2350 _k: *const c_int,
2351 _alpha: *const f64,
2352 _a: *const f64,
2353 _lda: *const c_int,
2354 _beta: *const f64,
2355 _c: *mut f64,
2356 _ldc: *const c_int,
2357) {
2358}
2359
2360#[no_mangle]
2362pub extern "C" fn dtrsl_(
2363 _t: *mut f64,
2364 _ldt: *const c_int,
2365 _n: *const c_int,
2366 _b: *mut f64,
2367 _job: *const c_int,
2368 _info: *mut c_int,
2369) {
2370}
2371#[no_mangle]
2372pub extern "C" fn chol_(
2373 _a: *mut f64,
2374 _lda: *const c_int,
2375 _n: *const c_int,
2376 _v: *mut f64,
2377 _info: *mut c_int,
2378) {
2379}
2380#[no_mangle]
2381pub extern "C" fn rs_(
2382 _nm: *const c_int,
2383 _n: *const c_int,
2384 _a: *mut f64,
2385 _w: *mut f64,
2386 _matz: *const c_int,
2387 _z: *mut f64,
2388 _fv1: *mut f64,
2389 _fv2: *mut f64,
2390 _ierr: *mut c_int,
2391) {
2392}
2393
2394#[no_mangle]
2396pub extern "C" fn dnorm(_x: f64, _mu: f64, _sigma: f64, _log_p: c_int) -> f64 {
2397 f64::NAN
2398}
2399#[no_mangle]
2400pub extern "C" fn pnorm(_x: f64, _mu: f64, _sigma: f64, _lt: c_int, _lp: c_int) -> f64 {
2401 f64::NAN
2402}
2403#[no_mangle]
2404pub extern "C" fn qnorm(_p: f64, _mu: f64, _sigma: f64, _lt: c_int, _lp: c_int) -> f64 {
2405 f64::NAN
2406}
2407#[no_mangle]
2408pub extern "C" fn qchisq(_p: f64, _df: f64, _lt: c_int, _lp: c_int) -> f64 {
2409 f64::NAN
2410}
2411#[no_mangle]
2412pub extern "C" fn rexp(_scale: f64) -> f64 {
2413 exp_rand() * _scale
2414}
2415#[no_mangle]
2416pub extern "C" fn rnorm(_mu: f64, _sigma: f64) -> f64 {
2417 _mu + _sigma * norm_rand()
2418}
2419#[no_mangle]
2420pub extern "C" fn runif(a: f64, b: f64) -> f64 {
2421 a + (b - a) * unif_rand()
2422}
2423#[no_mangle]
2424pub extern "C" fn rpois(_lambda: f64) -> f64 {
2425 _lambda
2426} #[no_mangle]
2428pub extern "C" fn rbinom(_n: f64, _p: f64) -> f64 {
2429 _n * _p
2430} #[no_mangle]
2432pub extern "C" fn choose(n: f64, k: f64) -> f64 {
2433 if k < 0.0 || k > n {
2434 return 0.0;
2435 }
2436 lgammafn(n + 1.0) - lgammafn(k + 1.0) - lgammafn(n - k + 1.0)
2437}
2438#[no_mangle]
2439pub extern "C" fn lchoose(n: f64, k: f64) -> f64 {
2440 choose(n, k).ln()
2441}
2442#[no_mangle]
2443pub extern "C" fn lgammafn(x: f64) -> f64 {
2444 libm::lgamma(x)
2445}
2446#[no_mangle]
2447pub extern "C" fn gammafn(x: f64) -> f64 {
2448 libm::tgamma(x)
2449}
2450#[no_mangle]
2451pub extern "C" fn beta(a: f64, b: f64) -> f64 {
2452 (lgammafn(a) + lgammafn(b) - lgammafn(a + b)).exp()
2453}
2454#[no_mangle]
2455pub extern "C" fn lbeta(a: f64, b: f64) -> f64 {
2456 lgammafn(a) + lgammafn(b) - lgammafn(a + b)
2457}
2458#[no_mangle]
2459pub extern "C" fn dbinom(_x: f64, _n: f64, _p: f64, _lg: c_int) -> f64 {
2460 f64::NAN
2461}
2462#[no_mangle]
2463pub extern "C" fn dpois(_x: f64, _lambda: f64, _lg: c_int) -> f64 {
2464 f64::NAN
2465}
2466#[no_mangle]
2467pub extern "C" fn pgamma(_x: f64, _shape: f64, _scale: f64, _lt: c_int, _lp: c_int) -> f64 {
2468 f64::NAN
2469}
2470#[no_mangle]
2471pub extern "C" fn qgamma(_p: f64, _shape: f64, _scale: f64, _lt: c_int, _lp: c_int) -> f64 {
2472 f64::NAN
2473}
2474
2475#[no_mangle]
2477pub extern "C" fn R_atof(str_ptr: *const c_char) -> f64 {
2478 if str_ptr.is_null() {
2479 return 0.0;
2480 }
2481 let s = unsafe { CStr::from_ptr(str_ptr) }.to_str().unwrap_or("0");
2482 s.parse::<f64>().unwrap_or(0.0)
2483}
2484
2485#[no_mangle]
2487pub extern "C" fn optif9(
2488 _nr: *const c_int,
2489 _n: *const c_int,
2490 _x: *mut f64,
2491 _fcn: *const (),
2492 _d1fcn: *const (),
2493 _d2fcn: *const (),
2494 _typsiz: *mut f64,
2495 _fscale: *const f64,
2496 _method: *const c_int,
2497 _iexp: *const c_int,
2498 _msg: *mut c_int,
2499 _ndigit: *const c_int,
2500 _itnlim: *const c_int,
2501 _iagflg: *const c_int,
2502 _iahflg: *const c_int,
2503 _dlt: *const f64,
2504 _gradtl: *const f64,
2505 _stepmx: *const f64,
2506 _steptl: *const f64,
2507 _xpls: *mut f64,
2508 _fpls: *mut f64,
2509 _gpls: *mut f64,
2510 _itrmcd: *mut c_int,
2511 _a: *mut f64,
2512 _wrk: *mut f64,
2513) {
2514}
2515
2516#[no_mangle]
2518pub extern "C" fn R_do_MAKE_CLASS(_name: *const c_char) -> Sexp {
2519 Rf_allocVector(sexp::VECSXP as c_int, 0)
2520}
2521
2522#[no_mangle]
2524pub extern "C" fn iPsort(x: *mut c_int, n: c_int, _k: c_int) {
2525 R_isort(x, n); }
2527#[no_mangle]
2528pub extern "C" fn rPsort(x: *mut f64, n: c_int, _k: c_int) {
2529 R_rsort(x, n);
2530}
2531
2532#[no_mangle]
2534pub extern "C" fn Rf_isPrimitive(x: Sexp) -> c_int {
2535 if x.is_null() {
2536 return 0;
2537 }
2538 let t = unsafe { (*x).stype };
2539 matches!(t, 7 | 8) as c_int }
2541
2542#[no_mangle]
2544pub extern "C" fn Rf_isSymbol(x: Sexp) -> c_int {
2545 if x.is_null() {
2546 return 0;
2547 }
2548 (unsafe { (*x).stype } == sexp::SYMSXP) as c_int
2549}
2550
2551#[no_mangle]
2553pub extern "C" fn Rf_lang5(s: Sexp, t: Sexp, u: Sexp, v: Sexp, w: Sexp) -> Sexp {
2554 Rf_lcons(
2555 s,
2556 Rf_cons(t, Rf_cons(u, Rf_cons(v, Rf_cons(w, unsafe { R_NilValue })))),
2557 )
2558}
2559
2560#[no_mangle]
2561pub extern "C" fn Rf_lang6(s: Sexp, t: Sexp, u: Sexp, v: Sexp, w: Sexp, x: Sexp) -> Sexp {
2562 Rf_lcons(
2563 s,
2564 Rf_cons(
2565 t,
2566 Rf_cons(u, Rf_cons(v, Rf_cons(w, Rf_cons(x, unsafe { R_NilValue })))),
2567 ),
2568 )
2569}
2570
2571#[no_mangle]
2573pub extern "C" fn Rf_findFun(sym: Sexp, env: Sexp) -> Sexp {
2574 Rf_findVar(sym, env)
2575}
2576
2577#[no_mangle]
2579pub extern "C" fn R_tryEval(expr: Sexp, env: Sexp, error_occurred: *mut c_int) -> Sexp {
2580 let result = Rf_eval(expr, env);
2581 if !error_occurred.is_null() {
2582 unsafe {
2583 *error_occurred = 0;
2584 }
2585 }
2586 result
2587}
2588
2589#[no_mangle]
2593pub extern "C" fn R_forceAndCall(call: Sexp, _n: c_int, env: Sexp) -> Sexp {
2594 Rf_eval(call, env)
2595}
2596
2597#[no_mangle]
2599pub extern "C" fn R_tryEvalSilent(expr: Sexp, env: Sexp, error_occurred: *mut c_int) -> Sexp {
2600 R_tryEval(expr, env, error_occurred)
2601}
2602
2603#[no_mangle]
2605pub extern "C" fn R_ToplevelExec(
2606 fun: Option<unsafe extern "C" fn(*mut c_void)>,
2607 data: *mut c_void,
2608) -> c_int {
2609 if let Some(f) = fun {
2610 unsafe {
2611 f(data);
2612 }
2613 }
2614 1 }
2616
2617#[no_mangle]
2619pub extern "C" fn Rf_mkNamed(stype: c_int, names: *const *const c_char) -> Sexp {
2620 let mut n: usize = 0;
2622 if !names.is_null() {
2623 unsafe {
2624 loop {
2625 let name_ptr = *names.add(n);
2626 if name_ptr.is_null() || *name_ptr == 0 {
2627 break;
2628 }
2629 n += 1;
2630 }
2631 }
2632 }
2633
2634 let vec = Rf_protect(Rf_allocVector(stype, n as isize));
2635 let names_vec = Rf_protect(Rf_allocVector(sexp::STRSXP as c_int, n as isize));
2636 for i in 0..n {
2637 unsafe {
2638 let name_ptr = *names.add(i);
2639 let ch = Rf_mkChar(name_ptr);
2640 let elts = (*names_vec).data as *mut Sexp;
2641 *elts.add(i) = ch;
2642 }
2643 }
2644 Rf_setAttrib(vec, unsafe { R_NamesSymbol }, names_vec);
2645 Rf_unprotect(2);
2646 vec
2647}
2648
2649#[no_mangle]
2651pub extern "C" fn Rf_isLanguage(x: Sexp) -> c_int {
2652 if x.is_null() {
2653 return 0;
2654 }
2655 (unsafe { (*x).stype } == 6) as c_int }
2657
2658#[no_mangle]
2660pub extern "C" fn R_ExpandFileName(fn_ptr: *const c_char) -> *const c_char {
2661 fn_ptr
2662}
2663
2664#[no_mangle]
2666pub extern "C" fn R_chk_calloc(nelem: usize, elsize: usize) -> *mut c_void {
2667 unsafe { calloc(nelem, elsize) as *mut c_void }
2668}
2669
2670#[no_mangle]
2672pub extern "C" fn R_chk_realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
2673 unsafe { realloc(ptr as *mut u8, size) as *mut c_void }
2674}
2675
2676#[no_mangle]
2678pub extern "C" fn R_chk_free(ptr: *mut c_void) {
2679 unsafe {
2680 free(ptr as *mut u8);
2681 }
2682}
2683
2684#[no_mangle]
2686pub extern "C" fn R_removeVarFromFrame(_sym: Sexp, _env: Sexp) {}
2687
2688#[no_mangle]
2690pub extern "C" fn Rf_allocS4Object() -> Sexp {
2691 Rf_allocVector(sexp::NILSXP as c_int, 0)
2692}
2693
2694#[no_mangle]
2696pub static mut R_interrupts_pending: c_int = 0;
2697#[no_mangle]
2698pub static mut R_interrupts_suspended: c_int = 0;
2699
2700#[no_mangle]
2702pub static mut R_InputHandlers: *mut c_void = ptr::null_mut();
2703#[no_mangle]
2704pub static mut R_PolledEvents: *mut c_void = ptr::null_mut();
2705#[no_mangle]
2706pub static mut R_wait_usec: c_int = 0;
2707
2708#[no_mangle]
2709pub extern "C" fn addInputHandler(
2710 handlers: *mut c_void,
2711 _fd: c_int,
2712 _action: *mut c_void,
2713 _activity: c_int,
2714) -> *mut c_void {
2715 handlers
2716}
2717
2718#[no_mangle]
2719pub extern "C" fn removeInputHandler(
2720 _handlers: *mut *mut c_void,
2721 _handler: *mut c_void,
2722) -> *mut c_void {
2723 ptr::null_mut()
2724}
2725
2726#[no_mangle]
2728pub extern "C" fn ps__list_apps() -> Sexp {
2729 ptr::null_mut()
2730}
2731#[no_mangle]
2732pub extern "C" fn ps__define_errno() -> Sexp {
2733 ptr::null_mut()
2734}
2735
2736#[no_mangle]
2738pub extern "C" fn R_CheckStack() {}
2739#[no_mangle]
2740pub extern "C" fn R_CheckStack2(_extra: c_int) {}
2741#[no_mangle]
2742pub extern "C" fn R_MakeActiveBinding(_sym: Sexp, _fun: Sexp, _env: Sexp) {}
2743#[no_mangle]
2744pub extern "C" fn R_MakeExternalPtrFn(p: *const (), tag: Sexp, prot: Sexp) -> Sexp {
2745 R_MakeExternalPtr(p as *mut c_void, tag, prot)
2746}
2747#[no_mangle]
2748pub extern "C" fn Rf_allocSExp(stype: c_int) -> Sexp {
2749 Rf_allocVector(stype, 0)
2750}
2751#[no_mangle]
2752pub extern "C" fn Rf_any_duplicated(_x: Sexp, _from_last: c_int) -> isize {
2753 0
2754}
2755#[no_mangle]
2756pub extern "C" fn Rf_countContexts(_type: c_int, _subtype: c_int) -> c_int {
2757 0
2758}
2759#[no_mangle]
2760pub extern "C" fn R_PromiseExpr(_p: Sexp) -> Sexp {
2761 unsafe { R_NilValue }
2762}
2763#[no_mangle]
2764pub extern "C" fn R_ClosureFormals(_x: Sexp) -> Sexp {
2765 unsafe { R_NilValue }
2766}
2767#[no_mangle]
2768pub extern "C" fn R_ClosureBody(_x: Sexp) -> Sexp {
2769 unsafe { R_NilValue }
2770}
2771#[no_mangle]
2772pub extern "C" fn R_ClosureEnv(_x: Sexp) -> Sexp {
2773 unsafe { R_NilValue }
2774}
2775#[no_mangle]
2776pub extern "C" fn R_compute_identical(x: Sexp, y: Sexp, _flags: c_int) -> c_int {
2777 if x == y {
2778 return 1;
2779 }
2780 if x.is_null() || y.is_null() {
2781 return 0;
2782 }
2783 unsafe {
2784 if (*x).stype != (*y).stype {
2785 return 0;
2786 }
2787 if (*x).length != (*y).length {
2788 return 0;
2789 }
2790 let len = (*x).length as usize;
2791 if len == 0 {
2792 return 1;
2793 }
2794 let elem_size = match (*x).stype {
2796 sexp::REALSXP => 8,
2797 sexp::INTSXP => 4,
2798 sexp::LGLSXP => 4,
2799 sexp::RAWSXP => 1,
2800 sexp::CPLXSXP => 16,
2801 _ => 0,
2802 };
2803 if elem_size > 0 && !(*x).data.is_null() && !(*y).data.is_null() {
2804 let bytes = len * elem_size;
2805 return (std::ptr::eq((*x).data, (*y).data)
2806 || std::slice::from_raw_parts((*x).data, bytes)
2807 == std::slice::from_raw_parts((*y).data, bytes)) as c_int;
2808 }
2809 if (*x).stype == sexp::STRSXP || (*x).stype == sexp::VECSXP {
2811 let ex = (*x).data as *const Sexp;
2812 let ey = (*y).data as *const Sexp;
2813 for i in 0..len {
2814 if R_compute_identical(*ex.add(i), *ey.add(i), _flags) == 0 {
2815 return 0;
2816 }
2817 }
2818 return 1;
2819 }
2820 if (*x).stype == sexp::CHARSXP {
2822 if (*x).data.is_null() && (*y).data.is_null() {
2823 return 1;
2824 }
2825 if (*x).data.is_null() || (*y).data.is_null() {
2826 return 0;
2827 }
2828 let sx = CStr::from_ptr((*x).data as *const c_char);
2829 let sy = CStr::from_ptr((*y).data as *const c_char);
2830 return (sx == sy) as c_int;
2831 }
2832 0
2833 }
2834}
2835#[no_mangle]
2836pub extern "C" fn R_envHasNoSpecialSymbols(_env: Sexp) -> c_int {
2837 1
2838}
2839#[no_mangle]
2840pub extern "C" fn R_OrderVector1(
2841 _indx: *mut c_int,
2842 _n: c_int,
2843 _x: Sexp,
2844 _nalast: c_int,
2845 _decreasing: c_int,
2846) {
2847}
2848#[no_mangle]
2849pub extern "C" fn SET_PRENV(_x: Sexp, _v: Sexp) {}
2850#[no_mangle]
2851pub extern "C" fn SET_PRCODE(_x: Sexp, _v: Sexp) {}
2852#[no_mangle]
2853pub extern "C" fn SET_PRVALUE(_x: Sexp, _v: Sexp) {}
2854#[no_mangle]
2855pub extern "C" fn PRCODE(_x: Sexp) -> Sexp {
2856 unsafe { R_NilValue }
2857}
2858#[no_mangle]
2859pub extern "C" fn PRVALUE(_x: Sexp) -> Sexp {
2860 unsafe { R_NilValue }
2861}
2862
2863#[no_mangle]
2865pub extern "C" fn R_BindingIsActive(_sym: Sexp, _env: Sexp) -> c_int {
2866 0
2867}
2868#[no_mangle]
2869pub extern "C" fn R_ActiveBindingFunction(_sym: Sexp, _env: Sexp) -> Sexp {
2870 unsafe { R_NilValue }
2871}
2872#[no_mangle]
2873pub extern "C" fn Rf_onintr() {}
2874
2875#[no_mangle]
2877pub static mut R_BraceSymbol: Sexp = ptr::null_mut();
2878#[no_mangle]
2879pub static mut R_BracketSymbol: Sexp = ptr::null_mut();
2880#[no_mangle]
2881pub static mut R_Bracket2Symbol: Sexp = ptr::null_mut();
2882#[no_mangle]
2883pub static mut R_DollarSymbol: Sexp = ptr::null_mut();
2884#[no_mangle]
2885pub static mut R_DoubleColonSymbol: Sexp = ptr::null_mut();
2886#[no_mangle]
2887pub static mut R_TripleColonSymbol: Sexp = ptr::null_mut();
2888#[no_mangle]
2889pub static mut R_Interactive: c_int = 0;
2890
2891#[no_mangle]
2893pub extern "C" fn Rf_type2str(stype: c_int) -> Sexp {
2894 Rf_mkChar(Rf_type2char(stype))
2895}
2896
2897#[no_mangle]
2899pub extern "C" fn R_MakeWeakRef(key: Sexp, val: Sexp, _fin: Sexp, _onexit: c_int) -> Sexp {
2900 Rf_cons(key, Rf_cons(val, unsafe { R_NilValue }))
2901}
2902#[no_mangle]
2903pub extern "C" fn R_MakeWeakRefC(key: Sexp, val: Sexp, _fin: *const (), onexit: c_int) -> Sexp {
2904 R_MakeWeakRef(key, val, unsafe { R_NilValue }, onexit)
2905}
2906#[no_mangle]
2907pub extern "C" fn R_WeakRefKey(_w: Sexp) -> Sexp {
2908 unsafe { R_NilValue }
2909}
2910#[no_mangle]
2911pub extern "C" fn R_WeakRefValue(_w: Sexp) -> Sexp {
2912 unsafe { R_NilValue }
2913}
2914#[no_mangle]
2915pub extern "C" fn Rf_duplicated(_x: Sexp, _from_last: c_int) -> Sexp {
2916 Rf_allocVector(sexp::LGLSXP as c_int, 0)
2917}
2918#[no_mangle]
2919pub extern "C" fn Rf_any_duplicated3(_x: Sexp, _incomp: Sexp, _from_last: c_int) -> isize {
2920 0
2921}
2922#[no_mangle]
2923pub extern "C" fn Rf_reEnc(
2924 x: *const c_char,
2925 _ce_in: c_int,
2926 _ce_out: c_int,
2927 _subst: c_int,
2928) -> *const c_char {
2929 x
2930}
2931#[no_mangle]
2932pub extern "C" fn Rf_ucstoutf8(buf: *mut c_char, _wc: u32) -> *const c_char {
2933 buf as *const c_char
2934}
2935#[no_mangle]
2936pub extern "C" fn SET_BODY(_x: Sexp, _v: Sexp) {}
2937#[no_mangle]
2938pub extern "C" fn SET_FORMALS(_x: Sexp, _v: Sexp) {}
2939#[no_mangle]
2940pub extern "C" fn SET_CLOENV(_x: Sexp, _v: Sexp) {}
2941#[no_mangle]
2942pub static mut R_NamespaceRegistry: Sexp = ptr::null_mut();
2943#[no_mangle]
2944pub static mut R_Srcref: Sexp = ptr::null_mut();
2945#[no_mangle]
2946pub static mut R_BaseNamespace: Sexp = ptr::null_mut();
2947#[no_mangle]
2948pub extern "C" fn R_EnvironmentIsLocked(_env: Sexp) -> c_int {
2949 0
2950}
2951
2952#[no_mangle]
2954pub extern "C" fn Rf_installChar(x: Sexp) -> Sexp {
2955 if x.is_null() {
2956 return unsafe { R_NilValue };
2957 }
2958 let name = unsafe { sexp::char_data(x) };
2959 Rf_install(name.as_ptr() as *const c_char)
2960}
2961#[no_mangle]
2963pub extern "C" fn Rf_ScalarRaw(x: u8) -> Sexp {
2964 let s = Rf_allocVector(sexp::RAWSXP as c_int, 1);
2965 unsafe {
2966 *(*s).data = x;
2967 }
2968 s
2969}
2970
2971#[no_mangle]
2973pub extern "C" fn Rf_shallow_duplicate(x: Sexp) -> Sexp {
2974 Rf_duplicate(x)
2975}
2976
2977#[no_mangle]
2980pub extern "C" fn R_NewEnv(parent: Sexp, _hash: c_int, _size: c_int) -> Sexp {
2981 unsafe {
2982 let s = calloc(1, std::mem::size_of::<SexpRec>()) as Sexp;
2983 if s.is_null() {
2984 return R_NilValue;
2985 }
2986 (*s).stype = 4; (*s).flags = 1; (*s).data = parent as *mut u8; (*s).attrib = R_NilValue; track(s);
2991 s
2992 }
2993}
2994
2995#[no_mangle]
2997pub extern "C" fn Rf_defineVar(sym: Sexp, val: Sexp, env: Sexp) {
2998 if sym.is_null() {
2999 return;
3000 }
3001
3002 if !env.is_null() && unsafe { (*env).stype } == sexp::ENVSXP {
3004 let var_name = unsafe { sexp::char_data(sym) };
3005 if let Some(e) = unsafe { super::convert::env_from_sexp(env) } {
3006 let rval = unsafe { super::convert::sexp_to_rvalue(val) };
3007 e.set(var_name.to_string(), rval);
3008 return;
3009 }
3010 let node = Rf_cons(val, unsafe { (*env).attrib });
3012 unsafe {
3013 let pd = (*node).data as *mut sexp::PairlistData;
3014 if !pd.is_null() {
3015 (*pd).tag = sym;
3016 }
3017 (*env).attrib = node;
3018 }
3019 return;
3020 }
3021
3022 let name = unsafe { sexp::char_data(sym) };
3024 if name.is_empty() {
3025 return;
3026 }
3027 let rval = unsafe { super::convert::sexp_to_rvalue(val) };
3028 STATE.with(|state| {
3029 let st = state.borrow();
3030 if let Some(define) = st.callbacks.define_var {
3031 define(name, rval);
3032 }
3033 });
3034}
3035
3036#[no_mangle]
3038pub extern "C" fn BODY(_x: Sexp) -> Sexp {
3039 unsafe { R_NilValue }
3040}
3041
3042#[no_mangle]
3043pub extern "C" fn CLOENV(_x: Sexp) -> Sexp {
3044 unsafe { R_NilValue }
3045}
3046
3047#[no_mangle]
3048pub extern "C" fn FORMALS(_x: Sexp) -> Sexp {
3049 unsafe { R_NilValue }
3050}
3051
3052#[no_mangle]
3054pub extern "C" fn Rf_isObject(x: Sexp) -> c_int {
3055 if x.is_null() {
3056 return 0;
3057 }
3058 let klass = Rf_getAttrib(x, unsafe { R_ClassSymbol });
3059 (!klass.is_null() && unsafe { (*klass).stype } == sexp::STRSXP) as c_int
3060}
3061
3062#[no_mangle]
3064pub extern "C" fn Rf_str2type(s: *const c_char) -> c_int {
3065 if s.is_null() {
3066 return -1;
3067 }
3068 let name = unsafe { CStr::from_ptr(s) }.to_str().unwrap_or("");
3069 match name {
3070 "NULL" => sexp::NILSXP as c_int,
3071 "logical" => sexp::LGLSXP as c_int,
3072 "integer" => sexp::INTSXP as c_int,
3073 "double" | "numeric" => sexp::REALSXP as c_int,
3074 "complex" => sexp::CPLXSXP as c_int,
3075 "character" => sexp::STRSXP as c_int,
3076 "list" => sexp::VECSXP as c_int,
3077 "raw" => sexp::RAWSXP as c_int,
3078 _ => -1,
3079 }
3080}
3081
3082#[repr(C)]
3083pub struct Rcomplex {
3084 r: f64,
3085 i: f64,
3086}
3087
3088#[no_mangle]
3090pub extern "C" fn Rf_ScalarComplex(c: Rcomplex) -> Sexp {
3091 let s = Rf_allocVector(sexp::CPLXSXP as c_int, 1);
3092 unsafe {
3093 let ptr = (*s).data as *mut Rcomplex;
3094 *ptr = c;
3095 }
3096 s
3097}
3098
3099#[no_mangle]
3101pub extern "C" fn ENCLOS(_x: Sexp) -> Sexp {
3102 unsafe { R_NilValue }
3103}
3104#[no_mangle]
3105pub extern "C" fn R_existsVarInFrame(_env: Sexp, _sym: Sexp) -> c_int {
3106 0
3107}
3108#[no_mangle]
3109pub extern "C" fn R_IsNamespaceEnv(env: Sexp) -> c_int {
3110 if let Some(e) = unsafe { super::convert::env_from_sexp(env) } {
3111 if let Some(name) = e.name() {
3112 if name.starts_with("namespace:") {
3113 return 1;
3114 }
3115 }
3116 }
3117 0
3118}
3119#[no_mangle]
3120pub extern "C" fn R_lsInternal3(_env: Sexp, _all: c_int, _sorted: c_int) -> Sexp {
3121 Rf_allocVector(sexp::STRSXP as c_int, 0)
3122}
3123#[no_mangle]
3124pub extern "C" fn R_ClosureExpr(_x: Sexp) -> Sexp {
3125 unsafe { R_NilValue }
3126}
3127#[no_mangle]
3128pub extern "C" fn R_ParentEnv(_env: Sexp) -> Sexp {
3129 unsafe { R_NilValue }
3130}
3131#[no_mangle]
3132pub extern "C" fn R_LockBinding(_sym: Sexp, _env: Sexp) {}
3133#[no_mangle]
3134pub extern "C" fn SET_FRAME(_x: Sexp, _v: Sexp) {}
3135#[no_mangle]
3136pub extern "C" fn SET_ENCLOS(_x: Sexp, _v: Sexp) {}
3137#[no_mangle]
3138pub extern "C" fn SET_HASHTAB(_x: Sexp, _v: Sexp) {}
3139#[no_mangle]
3140pub extern "C" fn R_BindingIsLocked(_sym: Sexp, _env: Sexp) -> c_int {
3141 0
3142}
3143#[no_mangle]
3144pub extern "C" fn R_NamespaceEnvSpec(_ns: Sexp) -> Sexp {
3145 unsafe { R_NilValue }
3146}
3147#[no_mangle]
3148pub extern "C" fn R_FindNamespace(_name: Sexp) -> Sexp {
3149 unsafe { R_NilValue }
3150}
3151#[no_mangle]
3152pub extern "C" fn R_IsPackageEnv(_env: Sexp) -> c_int {
3153 0
3154}
3155#[no_mangle]
3156pub extern "C" fn R_PackageEnvName(_env: Sexp) -> Sexp {
3157 unsafe { R_NilValue }
3158}
3159
3160#[no_mangle]
3162pub extern "C" fn Rf_findVarInFrame(env: Sexp, sym: Sexp) -> Sexp {
3163 Rf_findVarInFrame3(env, sym, 1)
3164}
3165
3166#[no_mangle]
3168pub extern "C" fn Rf_GetOption1(_tag: Sexp) -> Sexp {
3169 unsafe { R_NilValue }
3170}
3171
3172#[no_mangle]
3174pub extern "C" fn Rf_GetOptionWidth() -> c_int {
3175 80 }
3177
3178#[no_mangle]
3180pub extern "C" fn S_realloc(
3181 ptr: *mut c_char,
3182 new_size: isize,
3183 old_size: isize,
3184 elt_size: c_int,
3185) -> *mut c_char {
3186 extern "C" {
3187 fn realloc(ptr: *mut u8, size: usize) -> *mut u8;
3188 }
3189 let new_bytes = new_size as usize * elt_size as usize;
3190 let old_bytes = old_size as usize * elt_size as usize;
3191 unsafe {
3192 let new_ptr = realloc(ptr as *mut u8, new_bytes);
3193 if !new_ptr.is_null() && new_bytes > old_bytes {
3194 ptr::write_bytes(new_ptr.add(old_bytes), 0, new_bytes - old_bytes);
3195 }
3196 new_ptr as *mut c_char
3197 }
3198}
3199
3200#[no_mangle]
3202pub extern "C" fn norm_rand() -> f64 {
3203 let u1 = unif_rand();
3204 let u2 = unif_rand();
3205 (-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos()
3206}
3207
3208#[no_mangle]
3210pub extern "C" fn exp_rand() -> f64 {
3211 -unif_rand().ln()
3212}
3213
3214#[no_mangle]
3216pub extern "C" fn R_ParseVector(
3217 text: Sexp,
3218 _n: c_int,
3219 parse_status: *mut c_int,
3220 _srcfile: Sexp,
3221) -> Sexp {
3222 let src = if text.is_null() {
3224 String::new()
3225 } else {
3226 unsafe {
3227 if (*text).stype == sexp::STRSXP && (*text).length > 0 {
3228 let elt = *((*text).data as *const Sexp);
3229 if !elt.is_null() {
3230 sexp::char_data(elt).to_string()
3231 } else {
3232 String::new()
3233 }
3234 } else if (*text).stype == sexp::CHARSXP {
3235 sexp::char_data(text).to_string()
3236 } else {
3237 String::new()
3238 }
3239 }
3240 };
3241
3242 if src.is_empty() {
3243 if !parse_status.is_null() {
3244 unsafe {
3245 *parse_status = 1;
3246 } }
3248 return unsafe { R_NilValue };
3249 }
3250
3251 let result = STATE.with(|state| {
3253 let st = state.borrow();
3254 st.callbacks.parse_text.map(|parse_fn| parse_fn(&src))
3255 });
3256
3257 match result {
3258 Some(Ok(val)) => {
3259 if !parse_status.is_null() {
3260 unsafe {
3261 *parse_status = 1;
3262 } }
3264 let idx = stash_rvalue(val);
3267 let expr_sexp = sexp::alloc_vector(sexp::LANGSXP, 0);
3268 unsafe {
3269 (*expr_sexp).length = -1;
3271 (*expr_sexp).data = idx as *mut u8;
3272 }
3273 track(expr_sexp);
3274 let list = Rf_allocVector(sexp::VECSXP as c_int, 1);
3276 unsafe {
3277 let elts = (*list).data as *mut Sexp;
3278 *elts = expr_sexp;
3279 }
3280 list
3281 }
3282 Some(Err(_)) => {
3283 if !parse_status.is_null() {
3284 unsafe {
3285 *parse_status = 3;
3286 } }
3288 unsafe { R_NilValue }
3289 }
3290 None => {
3291 if !parse_status.is_null() {
3293 unsafe {
3294 *parse_status = 1;
3295 }
3296 }
3297 unsafe { R_NilValue }
3298 }
3299 }
3300}
3301
3302#[no_mangle]
3304pub extern "C" fn nmmin(
3305 _n: c_int,
3306 _xin: *mut f64,
3307 _x: *mut f64,
3308 _fmin: *mut f64,
3309 _fn_ptr: *const (),
3310 _fail: *mut c_int,
3311 _abstol: f64,
3312 _intol: f64,
3313 _ex: *mut c_void,
3314 _alpha: f64,
3315 _beta: f64,
3316 _gamma: f64,
3317 _trace: c_int,
3318 _fncount: *mut c_int,
3319 _maxit: c_int,
3320) {
3321 let _ = std::io::Write::write_all(
3322 &mut std::io::stderr(),
3323 b"Warning: nmmin() is a stub in miniR -- results will be incorrect\n",
3324 );
3325}
3326
3327#[no_mangle]
3328pub extern "C" fn vmmin(
3329 _n: c_int,
3330 _x: *mut f64,
3331 _fmin: *mut f64,
3332 _fn_ptr: *const (),
3333 _gr: *const (),
3334 _maxit: c_int,
3335 _trace: c_int,
3336 _mask: *mut c_int,
3337 _abstol: f64,
3338 _reltol: f64,
3339 _nreport: c_int,
3340 _ex: *mut c_void,
3341 _fncount: *mut c_int,
3342 _grcount: *mut c_int,
3343 _fail: *mut c_int,
3344) {
3345 let _ = std::io::Write::write_all(
3346 &mut std::io::stderr(),
3347 b"Warning: vmmin() is a stub in miniR -- results will be incorrect\n",
3348 );
3349}
3350
3351#[no_mangle]
3354pub extern "C" fn R_SetExternalPtrTag(s: Sexp, _tag: Sexp) {
3355 let _ = s;
3357}
3358
3359#[no_mangle]
3360pub extern "C" fn R_SetExternalPtrProtected(s: Sexp, _prot: Sexp) {
3361 let _ = s;
3362}
3363
3364#[no_mangle]
3369pub extern "C" fn R_do_new_object(_class_def: Sexp) -> Sexp {
3370 Rf_allocVector(sexp::VECSXP as c_int, 0)
3372}
3373
3374#[no_mangle]
3375pub extern "C" fn R_getClassDef(_what: *const c_char) -> Sexp {
3376 unsafe { R_NilValue }
3378}
3379
3380#[no_mangle]
3387pub extern "C" fn Rf_fround(x: f64, digits: f64) -> f64 {
3388 let m = 10.0_f64.powf(digits);
3389 (x * m).round() / m
3390}
3391
3392#[no_mangle]
3393pub extern "C" fn Rf_ftrunc(x: f64) -> f64 {
3394 x.trunc()
3395}
3396
3397#[no_mangle]
3398pub extern "C" fn Rf_fprec(x: f64, digits: f64) -> f64 {
3399 if x == 0.0 || !x.is_finite() || digits <= 0.0 {
3400 return x;
3401 }
3402 let digits = digits as i32;
3403 let magnitude = x.abs().log10().floor() as i32 + 1;
3404 let scale = 10.0_f64.powi(digits - magnitude);
3405 (x * scale).round() / scale
3406}
3407
3408#[no_mangle]
3409pub extern "C" fn Rf_sign(x: f64) -> f64 {
3410 if x > 0.0 {
3411 1.0
3412 } else if x < 0.0 {
3413 -1.0
3414 } else {
3415 0.0
3416 }
3417}
3418
3419#[no_mangle]
3421pub extern "C" fn Rf_gammafn(x: f64) -> f64 {
3422 libm::tgamma(x)
3423}
3424
3425#[no_mangle]
3426pub extern "C" fn Rf_lgammafn(x: f64) -> f64 {
3427 libm::lgamma(x)
3428}
3429
3430#[no_mangle]
3431pub extern "C" fn Rf_lgammafn_sign(x: f64, sgn: *mut c_int) -> f64 {
3432 if !sgn.is_null() {
3433 unsafe {
3434 *sgn = if x >= 0.0 { 1 } else { -1 };
3435 }
3436 }
3437 libm::lgamma(x)
3438}
3439
3440#[no_mangle]
3441pub extern "C" fn Rf_digamma(x: f64) -> f64 {
3442 super::rmath::digamma_fn(x)
3443}
3444
3445#[no_mangle]
3446pub extern "C" fn Rf_trigamma(x: f64) -> f64 {
3447 super::rmath::trigamma(x)
3448}
3449
3450#[no_mangle]
3451pub extern "C" fn Rf_tetragamma(x: f64) -> f64 {
3452 super::rmath::tetragamma(x)
3453}
3454
3455#[no_mangle]
3456pub extern "C" fn Rf_pentagamma(x: f64) -> f64 {
3457 super::rmath::pentagamma(x)
3458}
3459
3460#[no_mangle]
3461pub extern "C" fn Rf_psigamma(x: f64, deriv: f64) -> f64 {
3462 super::rmath::psigamma_fn(x, deriv)
3463}
3464
3465#[no_mangle]
3466pub extern "C" fn Rf_beta(a: f64, b: f64) -> f64 {
3467 super::rmath::beta_fn(a, b)
3468}
3469
3470#[no_mangle]
3471pub extern "C" fn Rf_lbeta(a: f64, b: f64) -> f64 {
3472 super::rmath::lbeta_fn(a, b)
3473}
3474
3475#[no_mangle]
3476pub extern "C" fn Rf_choose(n: f64, k: f64) -> f64 {
3477 super::rmath::choose_fn(n, k)
3478}
3479
3480#[no_mangle]
3481pub extern "C" fn Rf_lchoose(n: f64, k: f64) -> f64 {
3482 super::rmath::lchoose_fn(n, k)
3483}
3484
3485#[no_mangle]
3486pub extern "C" fn Rf_log1pmx(x: f64) -> f64 {
3487 super::rmath::log1pmx_fn(x)
3488}
3489
3490#[no_mangle]
3491pub extern "C" fn Rf_lgamma1p(a: f64) -> f64 {
3492 super::rmath::lgamma1p_fn(a)
3493}
3494
3495#[no_mangle]
3496pub extern "C" fn Rf_logspace_add(lx: f64, ly: f64) -> f64 {
3497 super::rmath::logspace_add_fn(lx, ly)
3498}
3499
3500#[no_mangle]
3501pub extern "C" fn Rf_logspace_sub(lx: f64, ly: f64) -> f64 {
3502 super::rmath::logspace_sub_fn(lx, ly)
3503}
3504
3505#[no_mangle]
3506pub extern "C" fn log1pexp(x: f64) -> f64 {
3507 if x <= -37.0 {
3508 x.exp()
3509 } else if x <= 18.0 {
3510 (1.0 + x.exp()).ln()
3511 } else {
3512 x + (-x).exp()
3513 }
3514}
3515
3516#[no_mangle]
3517pub extern "C" fn Rf_dpsifn(
3518 x: f64,
3519 n: c_int,
3520 _kode: c_int,
3521 _m: c_int,
3522 ans: *mut f64,
3523 nz: *mut c_int,
3524 ierr: *mut c_int,
3525) {
3526 if !ans.is_null() {
3527 unsafe {
3528 *ans = super::rmath::psigamma_fn(x, n as f64);
3529 }
3530 }
3531 if !nz.is_null() {
3532 unsafe {
3533 *nz = 0;
3534 }
3535 }
3536 if !ierr.is_null() {
3537 unsafe {
3538 *ierr = 0;
3539 }
3540 }
3541}
3542
3543#[no_mangle]
3547pub extern "C" fn Rf_isS4(x: Sexp) -> c_int {
3548 if x.is_null() {
3549 return 0;
3550 }
3551 let stype = unsafe { (*x).stype };
3553 if stype == 25 {
3554 return 1;
3555 }
3556 Rf_inherits(x, c"refClass".as_ptr())
3557}
3558
3559#[no_mangle]
3561pub extern "C" fn R_has_slot(obj: Sexp, name: Sexp) -> c_int {
3562 if obj.is_null() || name.is_null() {
3563 return 0;
3564 }
3565 let attr = Rf_getAttrib(obj, name);
3566 (!attr.is_null() && attr != unsafe { R_NilValue }) as c_int
3567}
3568
3569#[no_mangle]
3571pub extern "C" fn R_MakeUnwindCont() -> Sexp {
3572 Rf_allocVector(sexp::VECSXP as c_int, 0)
3574}
3575
3576#[no_mangle]
3578pub extern "C" fn R_ContinueUnwind(_cont: Sexp) {
3579 }
3581
3582#[no_mangle]
3584pub extern "C" fn R_UnwindProtect(
3585 fun: Option<extern "C" fn(*mut c_void) -> Sexp>,
3586 data: *mut c_void,
3587 _cleanfun: Option<extern "C" fn(*mut c_void, c_int)>,
3588 _cleandata: *mut c_void,
3589 _cont: Sexp,
3590) -> Sexp {
3591 match fun {
3593 Some(f) => f(data),
3594 None => unsafe { R_NilValue },
3595 }
3596}
3597
3598pub fn free_allocs() {
3605 STATE.with(|state| {
3610 let mut st = state.borrow_mut();
3611 st.alloc_head = ptr::null_mut();
3612 st.protect_stack.clear();
3613 });
3614}
3615
3616