miniextendr_api/sys.rs
1//! Raw FFI bindings to R headers.
2//!
3//! This module mirrors R's C API closely and is intentionally thin. **You
4//! almost never call these directly from user code** — prefer the
5//! higher-level wrappers: `SEXP` (in [`crate::sexp`]), [`SexpExt`] (in
6//! [`crate::sexp_ext`]), the type vocabulary in [`crate::sexp_types`], plus
7//! [`IntoR`], [`TryFromSexp`], [`with_r_thread`], [`with_r_unwind_protect`],
8//! and the `#[miniextendr]` proc-macro. The items here exist so those
9//! wrappers can be written; treat them as the framework's escape hatch.
10//!
11//! [`SexpExt`]: crate::sexp_ext::SexpExt
12//! [`IntoR`]: crate::IntoR
13//! [`TryFromSexp`]: crate::TryFromSexp
14//! [`with_r_thread`]: crate::worker::with_r_thread
15//! [`with_r_unwind_protect`]: crate::unwind_protect::with_r_unwind_protect
16//!
17//! # Checked vs `*_unchecked` variants
18//!
19//! Most non-variadic R API entry points come in two forms thanks to the
20//! [`#[r_ffi_checked]`](miniextendr_macros::r_ffi_checked) proc-macro applied
21//! to the `unsafe extern "C-unwind"` blocks below:
22//!
23//! - **Checked** (default — e.g. `Rf_allocVector`, `Rf_protect`, `INTEGER`):
24//! runs directly on R's main thread, routes through
25//! [`crate::worker::with_r_thread`] from an active miniextendr worker
26//! context, and panics for arbitrary off-main callers. **Use these by
27//! default.**
28//! - **`*_unchecked`** (e.g. `Rf_allocVector_unchecked`): bypass the assertion
29//! and the worker round-trip. Calling one off the R main thread is
30//! undefined behaviour. They exist for three known-safe contexts:
31//! 1. Inside ALTREP callbacks — R is already calling us on the main thread.
32//! 2. Inside a [`crate::unwind_protect::with_r_unwind_protect`] body —
33//! the guard has already established main-thread context.
34//! 3. Inside a [`crate::worker::with_r_thread`] body — the check would be
35//! redundant.
36//!
37//! The build-time lint **MXL301** enforces this: any `*_unchecked` call
38//! outside those contexts is a compile-time error.
39//!
40//! # Don't raise R errors directly
41//!
42//! `Rf_error`, `Rf_errorcall`, and their `_unchecked` siblings longjmp,
43//! which **skips Rust destructors** and leaks resources. The lint **MXL300**
44//! forbids them in user code. Use `panic!()` instead; the framework converts
45//! the panic into a structured R condition with `rust_*` class layering via
46//! the tagged-SEXP transport (see [`crate::error_value`]).
47//!
48//! # Cross references
49//!
50//! - [`crate::ffi_guard`] — guard taxonomy and worker-thread invariants.
51//! - [`crate::thread`] / [`crate::worker`] — worker / main-thread split.
52//! - [`crate::altrep_traits`] / [`crate::altrep_bridge`] — guard modes
53//! inside ALTREP callbacks.
54//! - [`crate::error_value`] / [`mod@crate::condition`] — panic → R condition
55//! transport.
56
57/// Raw ALTREP C API method type aliases.
58pub mod altrep;
59
60// `extern "C-unwind"` signatures below reference the type vocabulary by
61// bare name. Bring it into scope as a private `use` (NOT `pub use`) — the
62// vocab's canonical home is the crate root (`crate::SEXP`, etc.) and
63// `crate::sexp_types` for the niche helpers. Adding these to the public
64// API of `sys::` would re-create the bridge.
65use crate::sexp::SEXP;
66use crate::sexp_types::{R_CFinalizer_t, R_xlen_t, Rboolean, Rbyte, Rcomplex, SEXPTYPE, cetype_t};
67
68// region: Connections types (gated behind `connections` feature)
69// WARNING: R's connection API is explicitly marked as UNSTABLE.
70
71/// Opaque R connection implementation (from R_ext/Connections.h).
72///
73/// This is an opaque type representing R's internal connection structure.
74/// The actual structure is explicitly unstable and may change between R versions.
75#[cfg(feature = "connections")]
76#[repr(C)]
77#[allow(non_camel_case_types)]
78pub struct Rconnection_impl(::std::os::raw::c_void);
79
80/// Pointer to an R connection handle.
81///
82/// This is the typed equivalent of R's `Rconnection` type, which is a pointer
83/// to the opaque `Rconn` struct. Using this instead of `*mut c_void` provides
84/// type safety for connection APIs.
85#[cfg(feature = "connections")]
86#[allow(non_camel_case_types)]
87pub type Rconnection = *mut Rconnection_impl;
88
89/// R connections API version from R's `R_ext/Connections.h` at compile time.
90///
91/// This is a compile-time constant baked into the Rust FFI bindings when they
92/// were generated against a particular R version's headers. It does **not**
93/// dynamically probe the running R session.
94///
95/// From R_ext/Connections.h: "you *must* check the version and proceed only
96/// if it matches what you expect. We explicitly reserve the right to change
97/// the connection implementation without a compatibility layer."
98///
99/// Before using any connection APIs, check that this equals the expected version (1).
100#[cfg(feature = "connections")]
101#[allow(non_upper_case_globals)]
102pub const R_CONNECTIONS_VERSION: ::std::os::raw::c_int = 1;
103
104// endregion
105
106use miniextendr_macros::r_ffi_checked;
107
108// Unchecked variadic functions (internal use only, no thread check)
109#[allow(clashing_extern_declarations)]
110#[allow(varargs_without_pattern)]
111unsafe extern "C-unwind" {
112 /// Unchecked variadic `Rf_error`; call checked wrapper when possible.
113 #[link_name = "Rf_error"]
114 pub fn Rf_error_unchecked(arg1: *const ::std::os::raw::c_char, ...) -> !;
115 /// Unchecked variadic `Rf_errorcall`; call checked wrapper when possible.
116 #[link_name = "Rf_errorcall"]
117 pub fn Rf_errorcall_unchecked(arg1: SEXP, arg2: *const ::std::os::raw::c_char, ...) -> !;
118 /// Unchecked variadic `Rf_warning`; call checked wrapper when possible.
119 #[link_name = "Rf_warning"]
120 pub fn Rf_warning_unchecked(arg1: *const ::std::os::raw::c_char, ...);
121 /// Unchecked variadic `Rprintf`; call checked wrapper when possible.
122 #[link_name = "Rprintf"]
123 pub fn Rprintf_unchecked(arg1: *const ::std::os::raw::c_char, ...);
124 /// Unchecked variadic `REprintf`; call checked wrapper when possible.
125 #[link_name = "REprintf"]
126 pub fn REprintf_unchecked(arg1: *const ::std::os::raw::c_char, ...);
127}
128
129// Error message access (non-API, declared in Rinternals.h but flagged by R CMD check)
130#[cfg(feature = "nonapi")]
131unsafe extern "C-unwind" {
132 /// Get the current R error message buffer.
133 ///
134 /// Returns a pointer to R's internal error message buffer.
135 /// Used by Rserve and other embedding applications.
136 ///
137 /// # Safety
138 ///
139 /// - The returned pointer is only valid until the next R error
140 /// - Must not be modified
141 /// - Should be copied if needed beyond the immediate scope
142 ///
143 /// # Feature Gate
144 ///
145 /// This is a non-API function and requires the `nonapi` feature.
146 #[allow(non_snake_case, dead_code)] // used by worker.rs under worker-thread feature
147 pub(crate) fn R_curErrorBuf() -> *const ::std::os::raw::c_char;
148}
149
150// Console hooks (non-API; declared in Rinterface.h)
151#[cfg(feature = "nonapi")]
152unsafe extern "C-unwind" {
153 #[expect(dead_code, reason = "declared for future use")]
154 pub(crate) static ptr_R_WriteConsoleEx: Option<
155 unsafe extern "C-unwind" fn(
156 *const ::std::os::raw::c_char,
157 ::std::os::raw::c_int,
158 ::std::os::raw::c_int,
159 ),
160 >;
161}
162
163/// Checked wrapper for `Rf_error` - panics if called from non-main thread.
164/// Common usage: `Rf_error(c"%s".as_ptr(), message.as_ptr())`
165///
166/// # Safety
167///
168/// - Must be called from the R main thread
169/// - `fmt` and `arg1` must be valid null-terminated C strings
170#[inline(always)]
171#[allow(non_snake_case)]
172pub unsafe fn Rf_error(
173 fmt: *const ::std::os::raw::c_char,
174 arg1: *const ::std::os::raw::c_char,
175) -> ! {
176 if !crate::worker::is_r_main_thread() {
177 panic!("Rf_error called from non-main thread");
178 }
179 unsafe { Rf_error_unchecked(fmt, arg1) }
180}
181
182/// Checked wrapper for `Rf_errorcall` - panics if called from non-main thread.
183///
184/// # Safety
185///
186/// - Must be called from the R main thread
187/// - `call` must be a valid SEXP or R_NilValue
188/// - `fmt` and `arg1` must be valid null-terminated C strings
189#[inline(always)]
190#[allow(non_snake_case)]
191pub unsafe fn Rf_errorcall(
192 call: SEXP,
193 fmt: *const ::std::os::raw::c_char,
194 arg1: *const ::std::os::raw::c_char,
195) -> ! {
196 if !crate::worker::is_r_main_thread() {
197 panic!("Rf_errorcall called from non-main thread");
198 }
199 unsafe { Rf_errorcall_unchecked(call, fmt, arg1) }
200}
201
202/// Checked wrapper for `Rf_warning` - panics if called from non-main thread.
203///
204/// # Safety
205///
206/// - Must be called from the R main thread
207/// - `fmt` and `arg1` must be valid null-terminated C strings
208#[inline(always)]
209#[allow(non_snake_case)]
210pub unsafe fn Rf_warning(fmt: *const ::std::os::raw::c_char, arg1: *const ::std::os::raw::c_char) {
211 if !crate::worker::is_r_main_thread() {
212 panic!("Rf_warning called from non-main thread");
213 }
214 unsafe { Rf_warning_unchecked(fmt, arg1) }
215}
216
217/// Checked wrapper for `Rprintf` - panics if called from non-main thread.
218///
219/// # Safety
220///
221/// - Must be called from the R main thread
222/// - `fmt` and `arg1` must be valid null-terminated C strings
223#[inline(always)]
224#[allow(non_snake_case)]
225pub unsafe fn Rprintf(fmt: *const ::std::os::raw::c_char, arg1: *const ::std::os::raw::c_char) {
226 if !crate::worker::is_r_main_thread() {
227 panic!("Rprintf called from non-main thread");
228 }
229 unsafe { Rprintf_unchecked(fmt, arg1) }
230}
231
232/// Print to R's stderr (via R_ShowMessage or error console).
233///
234/// # Safety
235///
236/// - Must be called from the R main thread
237/// - `fmt` and `arg1` must be valid null-terminated C strings
238#[inline(always)]
239#[allow(non_snake_case)]
240pub unsafe fn REprintf(fmt: *const ::std::os::raw::c_char, arg1: *const ::std::os::raw::c_char) {
241 if !crate::worker::is_r_main_thread() {
242 panic!("REprintf called from non-main thread");
243 }
244 unsafe { REprintf_unchecked(fmt, arg1) }
245}
246
247// Imported R symbols and functions with runtime thread checks enabled.
248#[allow(missing_docs)]
249#[r_ffi_checked]
250#[allow(clashing_extern_declarations)]
251unsafe extern "C-unwind" {
252 /// The canonical R `NULL` value.
253 pub static R_NilValue: SEXP;
254
255 #[doc(alias = "NA_STRING")]
256 /// Missing string singleton — encapsulated by SEXP::na_string()
257 pub static R_NaString: SEXP;
258 /// Empty string CHARSXP — encapsulated by SEXP::blank_string()
259 pub static R_BlankString: SEXP;
260 /// Symbol for `names` attribute.
261 // Attribute symbols — encapsulated by SexpExt methods and SEXP::*_symbol()
262 pub static R_NamesSymbol: SEXP;
263 pub static R_DimSymbol: SEXP;
264 pub static R_DimNamesSymbol: SEXP;
265 pub static R_ClassSymbol: SEXP;
266 pub static R_RowNamesSymbol: SEXP;
267 pub static R_LevelsSymbol: SEXP;
268 pub static R_TspSymbol: SEXP;
269
270 /// Global environment (`.GlobalEnv`).
271 pub static R_GlobalEnv: SEXP;
272 /// Base package namespace environment.
273 pub static R_BaseEnv: SEXP;
274 /// Empty root environment.
275 pub static R_EmptyEnv: SEXP;
276 /// Base package namespace — encapsulated by SEXP::base_namespace()
277 pub static R_BaseNamespace: SEXP;
278
279 /// The "missing argument" sentinel value.
280 ///
281 /// When an R function is called without providing a value for a formal
282 /// argument, R passes `R_MissingArg` as a placeholder. This is different
283 /// from `R_NilValue` (NULL) - a missing argument means "not provided",
284 /// while NULL is an explicit value.
285 ///
286 /// In R: `f <- function(x) missing(x); f()` returns `TRUE`.
287 /// Encapsulated by SEXP::missing_arg()
288 pub static R_MissingArg: SEXP;
289
290 /// Sentinel returned by `R_getVarEx` (via its `ifnotfound` argument) when
291 /// the symbol has no binding in the searched frame(s).
292 pub static R_UnboundValue: SEXP;
293
294 // Issue #112 cat. 10: kept pub(crate) — single-caller utilities; wrapping adds no value
295 // Rinterface.h
296 pub(crate) fn R_FlushConsole();
297
298 // Special logical values (from internal Defn.h, not public API)
299 // These are gated behind `nonapi` feature as they may change across R versions.
300 #[cfg(feature = "nonapi")]
301 /// Non-API TRUE singleton.
302 pub static R_TrueValue: SEXP;
303 #[cfg(feature = "nonapi")]
304 /// Non-API FALSE singleton.
305 pub static R_FalseValue: SEXP;
306 #[cfg(feature = "nonapi")]
307 /// Non-API NA logical singleton.
308 pub static R_LogicalNAValue: SEXP;
309
310 // Rinternals.h
311 #[doc(alias = "mkChar")]
312 pub fn Rf_mkChar(s: *const ::std::os::raw::c_char) -> SEXP;
313 #[doc(alias = "mkCharLen")]
314 pub fn Rf_mkCharLen(s: *const ::std::os::raw::c_char, len: i32) -> SEXP;
315 #[doc(alias = "mkCharLenCE")]
316 pub fn Rf_mkCharLenCE(
317 x: *const ::std::os::raw::c_char,
318 len: ::std::os::raw::c_int,
319 ce: cetype_t,
320 ) -> SEXP;
321 #[doc(alias = "xlength")]
322 #[doc(alias = "XLENGTH")]
323 pub fn Rf_xlength(x: SEXP) -> R_xlen_t;
324 #[doc(alias = "translateCharUTF8")]
325 pub fn Rf_translateCharUTF8(x: SEXP) -> *const ::std::os::raw::c_char;
326 #[doc(alias = "getCharCE")]
327 pub fn Rf_getCharCE(x: SEXP) -> cetype_t;
328 #[doc(alias = "charIsASCII")]
329 pub fn Rf_charIsASCII(x: SEXP) -> Rboolean;
330 #[doc(alias = "charIsUTF8")]
331 pub fn Rf_charIsUTF8(x: SEXP) -> Rboolean;
332 #[doc(alias = "charIsLatin1")]
333 pub fn Rf_charIsLatin1(x: SEXP) -> Rboolean;
334
335 // Issue #112 cat. 3: kept pub(crate) — only called from unwind_protect.rs; users go through with_r_unwind_protect
336 pub(crate) fn R_MakeUnwindCont() -> SEXP;
337 pub(crate) fn R_ContinueUnwind(cont: SEXP) -> !;
338 pub(crate) fn R_UnwindProtect(
339 fun: ::std::option::Option<
340 unsafe extern "C-unwind" fn(*mut ::std::os::raw::c_void) -> SEXP,
341 >,
342 fun_data: *mut ::std::os::raw::c_void,
343 cleanfun: ::std::option::Option<
344 unsafe extern "C-unwind" fn(*mut ::std::os::raw::c_void, Rboolean),
345 >,
346 cleanfun_data: *mut ::std::os::raw::c_void,
347 cont: SEXP,
348 ) -> SEXP;
349
350 /// Version of `R_UnwindProtect` that accepts `extern "C-unwind"` function pointers
351 #[link_name = "R_UnwindProtect"]
352 pub(crate) fn R_UnwindProtect_C_unwind(
353 fun: ::std::option::Option<
354 unsafe extern "C-unwind" fn(*mut ::std::os::raw::c_void) -> SEXP,
355 >,
356 fun_data: *mut ::std::os::raw::c_void,
357 cleanfun: ::std::option::Option<
358 unsafe extern "C-unwind" fn(*mut ::std::os::raw::c_void, Rboolean),
359 >,
360 cleanfun_data: *mut ::std::os::raw::c_void,
361 cont: SEXP,
362 ) -> SEXP;
363
364 // Rinternals.h
365 // Issue #112 cat. 2: kept pub(crate) — ExternalPtr<T> encapsulates these for users; raw access needed within externalptr.rs
366 #[doc = " External pointer interface"]
367 pub(crate) fn R_MakeExternalPtr(p: *mut ::std::os::raw::c_void, tag: SEXP, prot: SEXP) -> SEXP;
368 pub fn R_ExternalPtrAddr(s: SEXP) -> *mut ::std::os::raw::c_void;
369 pub(crate) fn R_ExternalPtrTag(s: SEXP) -> SEXP;
370 pub(crate) fn R_ExternalPtrProtected(s: SEXP) -> SEXP;
371 pub(crate) fn R_ClearExternalPtr(s: SEXP);
372 pub(crate) fn R_SetExternalPtrAddr(s: SEXP, p: *mut ::std::os::raw::c_void);
373 pub(crate) fn R_SetExternalPtrTag(s: SEXP, tag: SEXP);
374 pub(crate) fn R_SetExternalPtrProtected(s: SEXP, p: SEXP);
375 #[doc = " Added in R 3.4.0"]
376 pub fn R_MakeExternalPtrFn(p: DL_FUNC, tag: SEXP, prot: SEXP) -> SEXP;
377 pub fn R_ExternalPtrAddrFn(s: SEXP) -> DL_FUNC;
378 pub fn R_RegisterFinalizer(s: SEXP, fun: SEXP);
379 pub(crate) fn R_RegisterCFinalizer(s: SEXP, fun: R_CFinalizer_t);
380 pub fn R_RegisterFinalizerEx(s: SEXP, fun: SEXP, onexit: Rboolean);
381 pub(crate) fn R_RegisterCFinalizerEx(s: SEXP, fun: R_CFinalizer_t, onexit: Rboolean);
382
383 // R_ext/Rdynload.h - C-callable interface
384 // Issue #112 cat. 10: kept pub(crate) — cross-package ABI helpers used from mx_abi.rs; wrapping adds no value
385 /// Register a C-callable function for cross-package access.
386 pub(crate) fn R_RegisterCCallable(
387 package: *const ::std::os::raw::c_char,
388 name: *const ::std::os::raw::c_char,
389 fptr: DL_FUNC,
390 );
391 /// Get a C-callable function from another package.
392 pub(crate) fn R_GetCCallable(
393 package: *const ::std::os::raw::c_char,
394 name: *const ::std::os::raw::c_char,
395 ) -> DL_FUNC;
396
397 // region: GC protection
398 //
399 // R has two GC protection mechanisms with very different cost profiles:
400 //
401 // ## Protect stack (`Rf_protect` / `Rf_unprotect`)
402 //
403 // A pre-allocated array (`R_PPStack`) with an integer index (`R_PPStackTop`).
404 // Protect pushes: `R_PPStack[R_PPStackTop++] = s`.
405 // Unprotect pops: `R_PPStackTop -= n`.
406 // **No heap allocation. No GC pressure. Essentially a single memory write.**
407 // Use this for temporary protection within a function.
408 // Requires LIFO discipline — nested scopes are fine, interleaved are not.
409 //
410 // ## Precious list (`R_PreserveObject` / `R_ReleaseObject`)
411 //
412 // A global linked list of CONSXP cells (`R_PreciousList`).
413 // Preserve: `CONS(object, R_PreciousList)` — **allocates a cons cell every call**.
414 // Release: linear scan of the entire list to find and unlink the object — **O(n)**.
415 // (Optional `R_HASH_PRECIOUS` env var enables a 1069-bucket hash table, improving
416 // Release to O(bucket_size), but Preserve still allocates.)
417 // Use this only for long-lived objects that outlive any single protect scope.
418 //
419 // ## Cost summary
420 //
421 // | Operation | Cost | Allocates? |
422 // |----------------------|--------------------|------------|
423 // | `Rf_protect` | array write | no |
424 // | `Rf_unprotect(n)` | integer subtract | no |
425 // | `Rf_unprotect_ptr` | scan + shift | no |
426 // | `R_PreserveObject` | cons cell alloc | **yes** |
427 // | `R_ReleaseObject` | linked list scan | no (O(n)) |
428 // | `R_ProtectWithIndex` | array write + save | no |
429 // | `R_Reprotect` | array index write | no |
430
431 /// Add a SEXP to the protect stack, preventing GC collection.
432 ///
433 /// **Cost: O(1)** — single array write (`R_PPStack[top++] = s`). No allocation.
434 ///
435 /// Must be balanced by a corresponding `Rf_unprotect`. The protect stack is
436 /// LIFO — nested scopes are safe, but interleaved usage from different scopes
437 /// will cause incorrect unprotection.
438 #[doc(alias = "PROTECT")]
439 #[doc(alias = "protect")]
440 pub fn Rf_protect(s: SEXP) -> SEXP;
441
442 /// Pop the top `l` entries from the protect stack.
443 ///
444 /// **Cost: O(1)** — single integer subtract (`R_PPStackTop -= l`). No allocation.
445 ///
446 /// The popped SEXPs become eligible for GC. Must match the number of
447 /// `Rf_protect` calls in the current scope (LIFO order).
448 #[doc(alias = "UNPROTECT")]
449 #[doc(alias = "unprotect")]
450 pub fn Rf_unprotect(l: ::std::os::raw::c_int);
451
452 /// Remove a specific SEXP from anywhere in the protect stack.
453 ///
454 /// **Cost: O(k)** — scans backwards from top (k = distance from top), then
455 /// shifts remaining entries down. No allocation. R source comment:
456 /// *"should be among the top few items"*.
457 ///
458 /// Unlike `Rf_unprotect`, this is order-independent — it finds and removes
459 /// the specific pointer regardless of stack position. Useful when LIFO
460 /// discipline cannot be maintained, but more expensive than `Rf_unprotect`.
461 #[doc(alias = "UNPROTECT_PTR")]
462 pub fn Rf_unprotect_ptr(s: SEXP);
463
464 /// Add a SEXP to the global precious list, preventing GC indefinitely.
465 ///
466 /// **Cost: O(1) but allocates a CONSXP cell** — creates GC pressure on every
467 /// call. The precious list is a global linked list (`R_PreciousList`).
468 ///
469 /// Use only for long-lived objects (e.g., ExternalPtr stored across R calls).
470 /// For temporary protection within a function, prefer `Rf_protect`.
471 pub fn R_PreserveObject(object: SEXP);
472
473 /// Remove a SEXP from the global precious list, allowing GC.
474 ///
475 /// **Cost: O(n)** — linear scan of the entire precious list to find and unlink
476 /// the cons cell. With `R_HASH_PRECIOUS` env var, O(bucket_size) average
477 /// via a 1069-bucket hash table, but this is off by default.
478 pub fn R_ReleaseObject(object: SEXP);
479
480 // endregion
481 // Vector allocation functions
482 #[doc(alias = "allocVector")]
483 pub fn Rf_allocVector(sexptype: SEXPTYPE, length: R_xlen_t) -> SEXP;
484 #[doc(alias = "allocMatrix")]
485 pub fn Rf_allocMatrix(
486 sexptype: SEXPTYPE,
487 nrow: ::std::os::raw::c_int,
488 ncol: ::std::os::raw::c_int,
489 ) -> SEXP;
490 #[doc(alias = "allocArray")]
491 pub fn Rf_allocArray(sexptype: SEXPTYPE, dims: SEXP) -> SEXP;
492 #[doc(alias = "alloc3DArray")]
493 pub fn Rf_alloc3DArray(
494 sexptype: SEXPTYPE,
495 nrow: ::std::os::raw::c_int,
496 ncol: ::std::os::raw::c_int,
497 nface: ::std::os::raw::c_int,
498 ) -> SEXP;
499
500 // Pairlist allocation
501 // Issue #112 cat. 10: kept pub(crate) — 2 callers in expression.rs/dots.rs; wrapping adds no value
502 #[doc(alias = "allocList")]
503 pub(crate) fn Rf_allocList(n: ::std::os::raw::c_int) -> SEXP;
504 #[doc(alias = "allocLang")]
505 pub fn Rf_allocLang(n: ::std::os::raw::c_int) -> SEXP;
506 #[doc(alias = "allocS4Object")]
507 pub fn Rf_allocS4Object() -> SEXP;
508
509 // Pairlist construction — encapsulated by PairListExt trait
510 pub fn Rf_cons(car: SEXP, cdr: SEXP) -> SEXP;
511 pub fn Rf_lcons(car: SEXP, cdr: SEXP) -> SEXP;
512
513 // Attribute manipulation — encapsulated by SexpExt methods
514 #[doc(alias = "setAttrib")]
515 pub fn Rf_setAttrib(vec: SEXP, name: SEXP, val: SEXP) -> SEXP;
516
517 // Rinternals.h — scalar constructors; encapsulated by SEXP::scalar_*() / scalar_*_unchecked()
518 #[doc(alias = "ScalarComplex")]
519 pub fn Rf_ScalarComplex(x: Rcomplex) -> SEXP;
520 #[doc(alias = "ScalarInteger")]
521 pub fn Rf_ScalarInteger(x: ::std::os::raw::c_int) -> SEXP;
522 #[doc(alias = "ScalarLogical")]
523 pub fn Rf_ScalarLogical(x: ::std::os::raw::c_int) -> SEXP;
524 #[doc(alias = "ScalarRaw")]
525 pub fn Rf_ScalarRaw(x: Rbyte) -> SEXP;
526 #[doc(alias = "ScalarReal")]
527 pub fn Rf_ScalarReal(x: f64) -> SEXP;
528 #[doc(alias = "ScalarString")]
529 pub fn Rf_ScalarString(x: SEXP) -> SEXP;
530
531 // Rinternals.h
532 /// Non-API function - use DATAPTR_RO or DATAPTR_OR_NULL instead.
533 /// Only available with `nonapi` feature.
534 #[cfg(feature = "nonapi")]
535 pub(crate) fn DATAPTR(x: SEXP) -> *mut ::std::os::raw::c_void;
536 pub fn DATAPTR_RO(x: SEXP) -> *const ::std::os::raw::c_void;
537 pub fn DATAPTR_OR_NULL(x: SEXP) -> *const ::std::os::raw::c_void;
538
539 // region: Cons Cell (Pairlist) Accessors
540 //
541 // R's pairlists (LISTSXP) are cons cells like in Lisp/Scheme. Each node has:
542 // - CAR: The value/head element
543 // - CDR: The rest/tail of the list (another pairlist or R_NilValue)
544 // - TAG: An optional name (symbol) for named lists/arguments
545 //
546 // Example R pairlist: list(a = 1, b = 2, 3)
547 // - First node: CAR=1, TAG="a", CDR=<next node>
548 // - Second node: CAR=2, TAG="b", CDR=<next node>
549 // - Third node: CAR=3, TAG=NULL, CDR=R_NilValue
550 //
551 // Pairlists are used for:
552 // - Function arguments (formal parameters and actual arguments)
553 // - Language objects (calls)
554 // - Dotted pairs in old-style lists
555 //
556 // The names CAR/CDR come from Lisp:
557 // - CAR = "Contents of Address part of Register"
558 // - CDR = "Contents of Decrement part of Register" (pronounced "could-er")
559 //
560 // Modern R mostly uses generic vectors (VECSXP) instead of pairlists,
561 // but pairlists are still used internally for function calls.
562
563 // Pairlist accessors — basic ops encapsulated by PairListExt trait,
564 // compound accessors (CAAR, CADR, etc.) module-private since no callers exist.
565 pub fn CAR(e: SEXP) -> SEXP;
566 pub fn CDR(e: SEXP) -> SEXP;
567 pub fn CAAR(e: SEXP) -> SEXP;
568 pub fn CDAR(e: SEXP) -> SEXP;
569 pub fn CADR(e: SEXP) -> SEXP;
570 pub fn CDDR(e: SEXP) -> SEXP;
571 pub fn CADDR(e: SEXP) -> SEXP;
572 pub fn CADDDR(e: SEXP) -> SEXP;
573 pub fn CAD4R(e: SEXP) -> SEXP;
574 pub fn TAG(e: SEXP) -> SEXP;
575 pub fn SET_TAG(x: SEXP, y: SEXP);
576 pub fn SETCAR(x: SEXP, y: SEXP) -> SEXP;
577 pub fn SETCDR(x: SEXP, y: SEXP) -> SEXP;
578 pub fn SETCADR(x: SEXP, y: SEXP) -> SEXP;
579 pub fn SETCADDR(x: SEXP, y: SEXP) -> SEXP;
580 pub fn SETCADDDR(x: SEXP, y: SEXP) -> SEXP;
581 pub fn SETCAD4R(e: SEXP, y: SEXP) -> SEXP;
582 pub fn LOGICAL_OR_NULL(x: SEXP) -> *const ::std::os::raw::c_int;
583 pub fn INTEGER_OR_NULL(x: SEXP) -> *const ::std::os::raw::c_int;
584 pub fn REAL_OR_NULL(x: SEXP) -> *const f64;
585 pub fn COMPLEX_OR_NULL(x: SEXP) -> *const Rcomplex;
586 pub fn RAW_OR_NULL(x: SEXP) -> *const Rbyte;
587
588 // Element-wise accessors (ALTREP-aware) — encapsulated by SexpExt methods
589 pub fn INTEGER_ELT(x: SEXP, i: R_xlen_t) -> ::std::os::raw::c_int;
590 pub fn REAL_ELT(x: SEXP, i: R_xlen_t) -> f64;
591 pub fn LOGICAL_ELT(x: SEXP, i: R_xlen_t) -> ::std::os::raw::c_int;
592 pub fn COMPLEX_ELT(x: SEXP, i: R_xlen_t) -> Rcomplex;
593 pub fn RAW_ELT(x: SEXP, i: R_xlen_t) -> Rbyte;
594 pub fn VECTOR_ELT(x: SEXP, i: R_xlen_t) -> SEXP;
595 pub fn STRING_ELT(x: SEXP, i: R_xlen_t) -> SEXP;
596 pub fn SET_STRING_ELT(x: SEXP, i: R_xlen_t, v: SEXP);
597 pub fn SET_LOGICAL_ELT(x: SEXP, i: R_xlen_t, v: ::std::os::raw::c_int);
598 pub fn SET_INTEGER_ELT(x: SEXP, i: R_xlen_t, v: ::std::os::raw::c_int);
599 pub fn SET_REAL_ELT(x: SEXP, i: R_xlen_t, v: f64);
600 pub fn SET_COMPLEX_ELT(x: SEXP, i: R_xlen_t, v: Rcomplex);
601 pub fn SET_RAW_ELT(x: SEXP, i: R_xlen_t, v: Rbyte);
602 pub fn SET_VECTOR_ELT(x: SEXP, i: R_xlen_t, v: SEXP) -> SEXP;
603
604 // endregion
605
606 // region: SEXP metadata accessors
607
608 /// Get the length of a SEXP as `int` (for short vectors < 2^31).
609 ///
610 /// For long vectors, use `Rf_xlength()` instead.
611 /// Returns 0 for R_NilValue.
612 pub fn LENGTH(x: SEXP) -> ::std::os::raw::c_int;
613
614 /// Get the length of a SEXP as `R_xlen_t` (supports long vectors).
615 ///
616 /// ALTREP-aware: will call ALTREP Length method if needed.
617 pub fn XLENGTH(x: SEXP) -> R_xlen_t;
618
619 /// Get the true length (allocated capacity) of a vector.
620 ///
621 /// May be larger than LENGTH for vectors with reserved space.
622 /// ALTREP-aware.
623 pub fn TRUELENGTH(x: SEXP) -> R_xlen_t;
624
625 /// Get the attributes pairlist of a SEXP.
626 ///
627 /// Returns R_NilValue if no attributes.
628 pub fn ATTRIB(x: SEXP) -> SEXP;
629
630 /// Set the attributes pairlist of a SEXP.
631 ///
632 /// # Safety
633 ///
634 /// `v` must be a pairlist or R_NilValue
635 pub fn SET_ATTRIB(x: SEXP, v: SEXP);
636
637 /// Check if SEXP has the "object" bit set (has a class).
638 ///
639 /// Returns non-zero if object has a class attribute.
640 pub fn OBJECT(x: SEXP) -> ::std::os::raw::c_int;
641
642 /// Set the "object" bit.
643 pub fn SET_OBJECT(x: SEXP, v: ::std::os::raw::c_int);
644
645 /// Get the LEVELS field (for factors).
646 pub fn LEVELS(x: SEXP) -> ::std::os::raw::c_int;
647
648 /// Set the LEVELS field (for factors).
649 ///
650 /// Returns the value that was set.
651 pub fn SETLEVELS(x: SEXP, v: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
652
653 // endregion
654
655 // region: ALTREP support — data2 encapsulated by AltrepSexpExt; data1 via standalone helpers
656
657 // Issue #112 cat. 6: pub(crate) — no AltrepSexpExt method yet; available for future callers
658 pub(crate) fn ALTREP_CLASS(x: SEXP) -> SEXP;
659 pub fn R_altrep_data1(x: SEXP) -> SEXP;
660 pub fn R_altrep_data2(x: SEXP) -> SEXP;
661 pub fn R_set_altrep_data1(x: SEXP, v: SEXP);
662 pub fn R_set_altrep_data2(x: SEXP, v: SEXP);
663
664 /// Check if a SEXP is an ALTREP object (returns non-zero if true).
665 ///
666 /// Use `SexpExt::is_altrep()` instead of calling this directly.
667 pub fn ALTREP(x: SEXP) -> ::std::os::raw::c_int;
668
669 // endregion
670
671 // region: Vector data accessors (mutable pointers)
672 // Issue #112 cat. 5: kept pub(crate) — raw pointer access needed in RNativeType impls and scattered callers;
673 // partial migration to SexpExt::as_mut_slice() tracked in follow-up issue
674
675 /// Get mutable pointer to logical vector data.
676 ///
677 /// For ALTREP vectors, this may force materialization.
678 /// Get mutable pointer to logical vector data.
679 ///
680 /// For ALTREP vectors, this may force materialization.
681 /// Prefer `SexpExt::set_logical_elt()` / `SexpExt::logical_elt()`.
682 pub(crate) fn LOGICAL(x: SEXP) -> *mut ::std::os::raw::c_int;
683
684 /// Get mutable pointer to integer vector data.
685 ///
686 /// For ALTREP vectors, this may force materialization.
687 /// Prefer `SexpExt::set_integer_elt()` / `SexpExt::integer_elt()`.
688 pub(crate) fn INTEGER(x: SEXP) -> *mut ::std::os::raw::c_int;
689
690 /// Get mutable pointer to real vector data.
691 ///
692 /// For ALTREP vectors, this may force materialization.
693 /// Prefer `SexpExt::set_real_elt()` / `SexpExt::real_elt()`.
694 pub(crate) fn REAL(x: SEXP) -> *mut f64;
695
696 /// Get mutable pointer to complex vector data.
697 ///
698 /// For ALTREP vectors, this may force materialization.
699 /// Prefer `SexpExt::set_complex_elt()` / `SexpExt::complex_elt()`.
700 pub(crate) fn COMPLEX(x: SEXP) -> *mut Rcomplex;
701
702 /// Get mutable pointer to raw vector data.
703 ///
704 /// For ALTREP vectors, this may force materialization.
705 /// Prefer `SexpExt::set_raw_elt()` / `SexpExt::raw_elt()`.
706 pub(crate) fn RAW(x: SEXP) -> *mut Rbyte;
707
708 // endregion
709
710 // region: User interrupt and utilities
711
712 // utils.h
713 pub fn R_CheckUserInterrupt();
714
715 // endregion
716
717 // region: Type checking — encapsulated by SexpExt::type_of()
718
719 pub fn TYPEOF(x: SEXP) -> SEXPTYPE;
720
721 // endregion
722
723 // Symbol creation and access
724 #[doc(alias = "install")]
725 pub fn Rf_install(name: *const ::std::os::raw::c_char) -> SEXP;
726 /// Get the print name (CHARSXP) of a symbol (SYMSXP)
727 pub fn PRINTNAME(x: SEXP) -> SEXP;
728 /// Get the C string pointer from a CHARSXP — encapsulated by SexpExt::r_char()
729 #[doc(alias = "CHAR")]
730 pub fn R_CHAR(x: SEXP) -> *const ::std::os::raw::c_char;
731
732 // Attribute access
733 // Attribute accessors — encapsulated by SexpExt methods
734 /// Read an attribute from an object by symbol (e.g. `R_NamesSymbol`).
735 ///
736 /// Returns `R_NilValue` if the attribute is not set.
737 #[doc(alias = "getAttrib")]
738 pub fn Rf_getAttrib(vec: SEXP, name: SEXP) -> SEXP;
739 /// Set the `names` attribute; returns the updated object.
740 #[doc(alias = "namesgets")]
741 pub fn Rf_namesgets(vec: SEXP, val: SEXP) -> SEXP;
742 /// Set the `dim` attribute; returns the updated object.
743 #[doc(alias = "dimgets")]
744 pub fn Rf_dimgets(vec: SEXP, val: SEXP) -> SEXP;
745
746 // Duplication
747 #[doc(alias = "duplicate")]
748 pub fn Rf_duplicate(s: SEXP) -> SEXP;
749 #[doc(alias = "shallow_duplicate")]
750 pub fn Rf_shallow_duplicate(s: SEXP) -> SEXP;
751
752 // Object comparison
753 /// Check if two R objects are identical (deep semantic equality).
754 ///
755 /// This is the C implementation of R's `identical()` function.
756 ///
757 /// # Flags
758 ///
759 /// Use the `IDENT_*` constants below. Flags are inverted: set bit = disable that check.
760 ///
761 /// **Default from R**: `IDENT_USE_CLOENV` (16) - ignore closure environments
762 ///
763 /// # Returns
764 ///
765 /// `TRUE` if identical, `FALSE` otherwise.
766 ///
767 /// # Performance
768 ///
769 /// Fast-path: Returns `TRUE` immediately if pointers are equal.
770 pub fn R_compute_identical(x: SEXP, y: SEXP, flags: ::std::os::raw::c_int) -> Rboolean;
771}
772
773/// Flags for `R_compute_identical` (bitmask, inverted logic: set bit = disable check).
774pub const IDENT_NUM_AS_BITS: ::std::os::raw::c_int = 1;
775/// Treat all NAs as identical (ignore NA payload differences).
776pub const IDENT_NA_AS_BITS: ::std::os::raw::c_int = 2;
777/// Compare attributes in order (not as a set).
778pub const IDENT_ATTR_BY_ORDER: ::std::os::raw::c_int = 4;
779/// Include bytecode in comparison.
780pub const IDENT_USE_BYTECODE: ::std::os::raw::c_int = 8;
781/// Include closure environments in comparison.
782pub const IDENT_USE_CLOENV: ::std::os::raw::c_int = 16;
783/// Include source references in comparison.
784pub const IDENT_USE_SRCREF: ::std::os::raw::c_int = 32;
785/// Compare external pointers as references (not by address).
786pub const IDENT_EXTPTR_AS_REF: ::std::os::raw::c_int = 64;
787
788// Additional checked R API declarations used by conversion and reflection code.
789#[allow(missing_docs)]
790#[r_ffi_checked]
791unsafe extern "C-unwind" {
792 // Type coercion — encapsulated by SexpExt methods
793 #[doc(alias = "asLogical")]
794 pub fn Rf_asLogical(x: SEXP) -> ::std::os::raw::c_int;
795 #[doc(alias = "asInteger")]
796 pub fn Rf_asInteger(x: SEXP) -> ::std::os::raw::c_int;
797 #[doc(alias = "asReal")]
798 pub fn Rf_asReal(x: SEXP) -> f64;
799 #[doc(alias = "asChar")]
800 pub fn Rf_asChar(x: SEXP) -> SEXP;
801 #[doc(alias = "coerceVector")]
802 pub fn Rf_coerceVector(v: SEXP, sexptype: SEXPTYPE) -> SEXP;
803
804 // Matrix utilities — no callers outside ffi.rs
805 #[doc(alias = "nrows")]
806 pub fn Rf_nrows(x: SEXP) -> ::std::os::raw::c_int;
807 #[doc(alias = "ncols")]
808 pub fn Rf_ncols(x: SEXP) -> ::std::os::raw::c_int;
809
810 // Inheritance checking — encapsulated by SexpExt::inherits_class()
811 #[doc(alias = "inherits")]
812 pub fn Rf_inherits(x: SEXP, klass: *const ::std::os::raw::c_char) -> Rboolean;
813
814 // Type checking predicates — encapsulated by SexpExt type-check methods
815 #[doc(alias = "isNull")]
816 pub fn Rf_isNull(s: SEXP) -> Rboolean;
817 #[doc(alias = "isSymbol")]
818 pub fn Rf_isSymbol(s: SEXP) -> Rboolean;
819 #[doc(alias = "isLogical")]
820 pub fn Rf_isLogical(s: SEXP) -> Rboolean;
821 #[doc(alias = "isReal")]
822 pub fn Rf_isReal(s: SEXP) -> Rboolean;
823 #[doc(alias = "isComplex")]
824 pub fn Rf_isComplex(s: SEXP) -> Rboolean;
825 #[doc(alias = "isExpression")]
826 pub fn Rf_isExpression(s: SEXP) -> Rboolean;
827 #[doc(alias = "isEnvironment")]
828 pub fn Rf_isEnvironment(s: SEXP) -> Rboolean;
829 #[doc(alias = "isString")]
830 pub fn Rf_isString(s: SEXP) -> Rboolean;
831
832 // Composite type checking (from inline functions)
833 #[doc(alias = "isArray")]
834 pub fn Rf_isArray(s: SEXP) -> Rboolean;
835 #[doc(alias = "isMatrix")]
836 pub fn Rf_isMatrix(s: SEXP) -> Rboolean;
837 #[doc(alias = "isList")]
838 pub fn Rf_isList(s: SEXP) -> Rboolean;
839 #[doc(alias = "isNewList")]
840 pub fn Rf_isNewList(s: SEXP) -> Rboolean;
841 #[doc(alias = "isPairList")]
842 pub fn Rf_isPairList(s: SEXP) -> Rboolean;
843 #[doc(alias = "isFunction")]
844 pub fn Rf_isFunction(s: SEXP) -> Rboolean;
845 #[doc(alias = "isPrimitive")]
846 pub fn Rf_isPrimitive(s: SEXP) -> Rboolean;
847 #[doc(alias = "isLanguage")]
848 pub fn Rf_isLanguage(s: SEXP) -> Rboolean;
849 #[doc(alias = "isDataFrame")]
850 pub fn Rf_isDataFrame(s: SEXP) -> Rboolean;
851 #[doc(alias = "isFactor")]
852 pub fn Rf_isFactor(s: SEXP) -> Rboolean;
853 #[doc(alias = "isInteger")]
854 pub fn Rf_isInteger(s: SEXP) -> Rboolean;
855 #[doc(alias = "isObject")]
856 pub fn Rf_isObject(s: SEXP) -> Rboolean;
857
858 // Pairlist utilities
859 #[doc(alias = "elt")]
860 pub fn Rf_elt(list: SEXP, i: ::std::os::raw::c_int) -> SEXP;
861 #[doc(alias = "lastElt")]
862 pub fn Rf_lastElt(list: SEXP) -> SEXP;
863 #[doc(alias = "nthcdr")]
864 pub fn Rf_nthcdr(list: SEXP, n: ::std::os::raw::c_int) -> SEXP;
865 #[doc(alias = "listAppend")]
866 pub fn Rf_listAppend(s: SEXP, t: SEXP) -> SEXP;
867
868 // More attribute setters (using R's "gets" suffix convention)
869 //
870 // See "Attribute access" section above for explanation of the "gets" suffix.
871 // These are setter functions equivalent to R's `attr(x) <- value` syntax.
872
873 /// Set the class attribute of a vector.
874 ///
875 /// Equivalent to R's `class(vec) <- klass` syntax.
876 /// The "gets" suffix indicates this is a setter function.
877 ///
878 /// # Returns
879 ///
880 /// Returns the modified vector (like all "*gets" functions).
881 #[doc(alias = "classgets")]
882 pub fn Rf_classgets(vec: SEXP, klass: SEXP) -> SEXP;
883
884 /// Set the dimnames attribute of an array/matrix.
885 ///
886 /// Equivalent to R's `dimnames(vec) <- val` syntax.
887 /// The "gets" suffix indicates this is a setter function.
888 ///
889 /// # Returns
890 ///
891 /// Returns the modified vector.
892 #[doc(alias = "dimnamesgets")]
893 pub fn Rf_dimnamesgets(vec: SEXP, val: SEXP) -> SEXP;
894 // Issue #112 cat. 10: kept pub(crate) — 2 callers each in factor.rs/matrix helpers; wrapping adds no value
895 #[doc(alias = "GetRowNames")]
896 pub(crate) fn Rf_GetRowNames(dimnames: SEXP) -> SEXP;
897 #[doc(alias = "GetColNames")]
898 pub(crate) fn Rf_GetColNames(dimnames: SEXP) -> SEXP;
899
900 // Environment operations
901 /// Single-frame (`inherits = FALSE`) or inherited variable lookup with an
902 /// `ifnotfound` default — the API-blessed replacement for
903 /// `Rf_findVarInFrame` (R-exts; added in R 4.5.0, hence
904 /// `Depends: R (>= 4.5)`). **Longjmps** if `rho` is not an environment or
905 /// the binding is `R_MissingArg`; forces promises.
906 #[doc(alias = "getVarEx")]
907 pub fn R_getVarEx(sym: SEXP, rho: SEXP, inherits: Rboolean, ifnotfound: SEXP) -> SEXP;
908 #[doc(alias = "defineVar")]
909 pub fn Rf_defineVar(symbol: SEXP, value: SEXP, rho: SEXP);
910 #[doc(alias = "setVar")]
911 pub fn Rf_setVar(symbol: SEXP, value: SEXP, rho: SEXP);
912 #[doc(alias = "findFun")]
913 pub fn Rf_findFun(symbol: SEXP, rho: SEXP) -> SEXP;
914
915 /// Find a registered namespace by name. **Longjmps on error** — prefer
916 /// `REnv::package_namespace()` which wraps this safely.
917 #[doc(alias = "FindNamespace")]
918 pub fn R_FindNamespace(info: SEXP) -> SEXP;
919
920 // Issue #112 cat. 9: kept pub(crate) — R_GetCurrentEnv used from s4_helpers.rs; R_tryEvalSilent from expression.rs
921 /// Return the current execution environment (innermost closure on call
922 /// stack, or `R_GlobalEnv` if none).
923 #[doc(alias = "GetCurrentEnv")]
924 pub(crate) fn R_GetCurrentEnv() -> SEXP;
925
926 // Evaluation
927 #[doc(alias = "eval")]
928 pub fn Rf_eval(expr: SEXP, rho: SEXP) -> SEXP;
929 #[doc(alias = "applyClosure")]
930 pub fn Rf_applyClosure(
931 call: SEXP,
932 op: SEXP,
933 args: SEXP,
934 rho: SEXP,
935 suppliedvars: SEXP,
936 check: Rboolean,
937 ) -> SEXP;
938 pub fn R_tryEval(expr: SEXP, env: SEXP, error_occurred: *mut ::std::os::raw::c_int) -> SEXP;
939 pub(crate) fn R_tryEvalSilent(
940 expr: SEXP,
941 env: SEXP,
942 error_occurred: *mut ::std::os::raw::c_int,
943 ) -> SEXP;
944 pub fn R_forceAndCall(e: SEXP, n: ::std::os::raw::c_int, rho: SEXP) -> SEXP;
945
946 /// Parse R source text into an EXPRSXP (a list of parsed expressions).
947 ///
948 /// `text` is a STRSXP holding the source, `n` is the number of expressions
949 /// to parse (`-1` for all), `status` receives the [`ParseStatus`] outcome,
950 /// and `srcfile` is a srcref/`R_NilValue`. Allocates; protect the result.
951 ///
952 /// Prefer the safe [`crate::expression::r_eval_str`] wrapper, which does the
953 /// STRSXP construction, status check, and protection bookkeeping for you.
954 #[doc(alias = "ParseVector")]
955 pub fn R_ParseVector(
956 text: SEXP,
957 n: ::std::os::raw::c_int,
958 status: *mut ParseStatus,
959 srcfile: SEXP,
960 ) -> SEXP;
961}
962
963/// Outcome of [`R_ParseVector`] (from `R_ext/Parse.h`).
964///
965/// `PARSE_NULL` is never returned by `R_ParseVector`; the meaningful success
966/// value is [`ParseStatus::PARSE_OK`]. The remaining variants indicate parse
967/// failures (`PARSE_ERROR`), incomplete input (`PARSE_INCOMPLETE`), or
968/// end-of-input (`PARSE_EOF`).
969#[allow(non_camel_case_types)]
970#[repr(i32)]
971#[derive(Debug, Clone, Copy, PartialEq, Eq)]
972pub enum ParseStatus {
973 /// Never returned by `R_ParseVector`; the default-initialized sentinel.
974 PARSE_NULL,
975 /// Parse succeeded.
976 PARSE_OK,
977 /// Input ended mid-expression (e.g. an unbalanced delimiter).
978 PARSE_INCOMPLETE,
979 /// A syntax error was encountered.
980 PARSE_ERROR,
981 /// End of input reached with no further expressions.
982 PARSE_EOF,
983}
984
985// region: Connections API (R_ext/Connections.h)
986//
987// Gated behind `connections` feature because R's connection API is explicitly UNSTABLE.
988// From R_ext/Connections.h:
989// "IMPORTANT: we do not expect future connection APIs to be
990// backward-compatible so if you use this, you *must* check the
991// version and proceeds only if it matches what you expect.
992//
993// We explicitly reserve the right to change the connection
994// implementation without a compatibility layer."
995//
996// Use with caution and always check R_CONNECTIONS_VERSION.
997// Issue #112 cat. 8: kept pub(crate) — feature-gated behind `connections`; behind Connection type for users
998#[r_ffi_checked]
999#[cfg(feature = "connections")]
1000unsafe extern "C-unwind" {
1001 /// Create a new custom connection.
1002 ///
1003 /// # WARNING
1004 ///
1005 /// This API is UNSTABLE. Check `R_CONNECTIONS_VERSION` before use.
1006 /// The connection implementation may change without notice.
1007 ///
1008 /// # Safety
1009 ///
1010 /// - `description`, `mode`, and `class_name` must be valid C strings
1011 /// - `ptr` must be a valid pointer to store the connection handle
1012 pub(crate) fn R_new_custom_connection(
1013 description: *const ::std::os::raw::c_char,
1014 mode: *const ::std::os::raw::c_char,
1015 class_name: *const ::std::os::raw::c_char,
1016 ptr: *mut Rconnection,
1017 ) -> SEXP;
1018
1019 /// Read from a connection.
1020 ///
1021 /// # WARNING
1022 ///
1023 /// This API is UNSTABLE and may change.
1024 ///
1025 /// # Safety
1026 ///
1027 /// - `con` must be a valid Rconnection handle
1028 /// - `buf` must be a valid buffer with at least `n` bytes
1029 pub(crate) fn R_ReadConnection(
1030 con: Rconnection,
1031 buf: *mut ::std::os::raw::c_void,
1032 n: usize,
1033 ) -> usize;
1034
1035 /// Write to a connection.
1036 ///
1037 /// # WARNING
1038 ///
1039 /// This API is UNSTABLE and may change.
1040 ///
1041 /// # Safety
1042 ///
1043 /// - `con` must be a valid Rconnection handle
1044 /// - `buf` must contain at least `n` valid bytes
1045 pub(crate) fn R_WriteConnection(
1046 con: Rconnection,
1047 buf: *const ::std::os::raw::c_void,
1048 n: usize,
1049 ) -> usize;
1050
1051 /// Get a connection from a SEXP.
1052 ///
1053 /// # WARNING
1054 ///
1055 /// This API is UNSTABLE and may change.
1056 /// Added in R 3.3.0.
1057 ///
1058 /// # Safety
1059 ///
1060 /// - `sConn` must be a valid connection SEXP
1061 pub(crate) fn R_GetConnection(sConn: SEXP) -> Rconnection;
1062}
1063// endregion: Connections API
1064
1065/// Check if a SEXP is an S4 object.
1066///
1067/// # Safety
1068///
1069/// - `arg1` must be a valid SEXP
1070#[allow(non_snake_case)]
1071pub unsafe fn Rf_isS4(arg1: SEXP) -> Rboolean {
1072 unsafe extern "C-unwind" {
1073 #[link_name = "Rf_isS4"]
1074 pub fn Rf_isS4_original(arg1: SEXP) -> u32;
1075 }
1076
1077 unsafe {
1078 if Rf_isS4_original(arg1) == 0 {
1079 Rboolean::FALSE
1080 } else {
1081 Rboolean::TRUE
1082 }
1083 }
1084}
1085
1086// region: registration!
1087
1088#[repr(C)]
1089#[derive(Debug)]
1090/// Opaque dynamic library descriptor from R.
1091pub struct DllInfo(::std::os::raw::c_void);
1092
1093/// Generic dynamic library function pointer.
1094///
1095/// R defines this as `void *(*)(void)` - a function taking no arguments and
1096/// returning `void*`. This is used for method registration and external pointer
1097/// functions. The actual function signatures vary; callers cast to the appropriate
1098/// concrete function type before calling.
1099///
1100/// We use `fn() -> *mut c_void` to match R's signature. The function pointer is
1101/// stored generically and cast to the appropriate type when called by R.
1102#[allow(non_camel_case_types)]
1103pub type DL_FUNC =
1104 ::std::option::Option<unsafe extern "C-unwind" fn() -> *mut ::std::os::raw::c_void>;
1105
1106/// Type descriptor for native primitive arguments in .C/.Fortran calls.
1107///
1108/// This is used in `R_CMethodDef` and `R_FortranMethodDef` to specify
1109/// argument types for type checking.
1110#[allow(non_camel_case_types)]
1111pub type R_NativePrimitiveArgType = ::std::os::raw::c_uint;
1112
1113/// Method definition for .C interface routines.
1114///
1115/// Used to register C functions callable via `.C()` from R.
1116#[repr(C)]
1117#[derive(Debug, Copy, Clone)]
1118#[allow(non_camel_case_types)]
1119#[allow(non_snake_case)]
1120pub struct R_CMethodDef {
1121 /// Exported symbol name.
1122 pub name: *const ::std::os::raw::c_char,
1123 /// Function pointer implementing the routine.
1124 pub fun: DL_FUNC,
1125 /// Declared arity.
1126 pub numArgs: ::std::os::raw::c_int,
1127 /// Optional array of argument types for type checking. May be null.
1128 pub types: *const R_NativePrimitiveArgType,
1129}
1130
1131/// Method definition for .Fortran interface routines.
1132///
1133/// Structurally identical to `R_CMethodDef`.
1134#[allow(non_camel_case_types)]
1135pub type R_FortranMethodDef = R_CMethodDef;
1136
1137/// Method definition for .Call interface routines.
1138///
1139/// Used to register C functions callable via `.Call()` from R.
1140/// Unlike `.C()` routines, `.Call()` functions receive and return SEXP values directly.
1141#[repr(C)]
1142#[derive(Debug, Copy, Clone)]
1143#[allow(non_camel_case_types)]
1144#[allow(non_snake_case)]
1145pub struct R_CallMethodDef {
1146 /// Exported symbol name.
1147 pub name: *const ::std::os::raw::c_char,
1148 /// Function pointer implementing the routine.
1149 pub fun: DL_FUNC,
1150 /// Declared arity.
1151 pub numArgs: ::std::os::raw::c_int,
1152}
1153
1154// SAFETY: `name` points to a static CStr literal, `fun` is a function pointer.
1155// Both are valid for program lifetime and safe to read from any thread.
1156unsafe impl Sync for R_CallMethodDef {}
1157unsafe impl Send for R_CallMethodDef {}
1158
1159/// Method definition for .External interface routines.
1160///
1161/// Structurally identical to `R_CallMethodDef`.
1162#[allow(non_camel_case_types)]
1163pub type R_ExternalMethodDef = R_CallMethodDef;
1164
1165// Checked routine registration API declarations.
1166// Issue #112 cat. 7: kept pub(crate) — only called from init.rs during package init; not worth a wrapper type
1167#[allow(missing_docs)]
1168#[r_ffi_checked]
1169#[allow(clashing_extern_declarations)]
1170unsafe extern "C-unwind" {
1171 pub(crate) fn R_registerRoutines(
1172 info: *mut DllInfo,
1173 croutines: *const R_CMethodDef,
1174 callRoutines: *const R_CallMethodDef,
1175 fortranRoutines: *const R_FortranMethodDef,
1176 externalRoutines: *const R_ExternalMethodDef,
1177 ) -> ::std::os::raw::c_int;
1178
1179 pub(crate) fn R_useDynamicSymbols(info: *mut DllInfo, value: Rboolean) -> Rboolean;
1180 pub(crate) fn R_forceSymbols(info: *mut DllInfo, value: Rboolean) -> Rboolean;
1181}
1182
1183// endregion
1184
1185// region: Non-API encoding/locale state (Defn.h)
1186
1187/// Non-API encoding / locale helpers from R's `Defn.h`.
1188///
1189/// These are not part of the stable R API and may break across R versions.
1190///
1191/// Only symbols R's shared library actually **exports** may be declared here.
1192/// `Defn.h` marks most locale globals `extern0` (= `attribute_hidden`) —
1193/// referencing one of those (e.g. `known_to_be_utf8`, `latin1locale`,
1194/// `R_nativeEncoding`) compiles fine but aborts `dyn.load` of any binary that
1195/// carries the reference: data relocations resolve eagerly at load, whether or
1196/// not the code path ever runs. That made every `nonapi` build un-loadable
1197/// (caught by the feature-legs CI, audit A5). `utf8locale`, `mbcslocale`, and
1198/// `known_to_be_latin1` are plain `extern` and exported (verified against
1199/// R 4.6's libR).
1200#[cfg(feature = "nonapi")]
1201pub mod nonapi_encoding {
1202 use super::r_ffi_checked;
1203
1204 // Issue #112 cat. 10: kept pub(crate) — nonapi encoding helpers; single-caller utilities in encoding.rs
1205 #[r_ffi_checked]
1206 #[allow(clashing_extern_declarations)]
1207 unsafe extern "C-unwind" {
1208 // Locale flags (exported, non-hidden)
1209 pub(crate) static utf8locale: super::Rboolean;
1210 pub(crate) static mbcslocale: super::Rboolean;
1211 pub(crate) static known_to_be_latin1: super::Rboolean;
1212 }
1213}
1214
1215// endregion
1216
1217// region: Non-API stack checking variables (Rinterface.h)
1218
1219/// Non-API stack checking variables from `Rinterface.h`.
1220///
1221/// R uses these to detect stack overflow. On a different thread the values do
1222/// not describe the current stack, so a stack check can fail spuriously.
1223///
1224/// # Not a package thread-safety mechanism
1225///
1226/// Setting `R_CStackLimit` to `usize::MAX` disables only R's stack-address
1227/// check. It does not make the R API, GC, global state, or error signaling safe
1228/// on a secondary thread. R packages must keep R API calls on the main thread
1229/// and must not rewrite these globals for off-main calls. The higher-level
1230/// [`StackCheckGuard`](crate::thread::StackCheckGuard) has the same limitation;
1231/// removal or relocation of this surface is tracked in #1352.
1232#[cfg(feature = "nonapi")]
1233pub mod nonapi_stack {
1234 unsafe extern "C" {
1235 /// Top of the stack (set during `Rf_initialize_R` for main thread).
1236 ///
1237 /// On Unix, determined via `__libc_stack_end`, `KERN_USRSTACK`, or
1238 /// `thr_stksegment`. On Windows, via `VirtualQuery`.
1239 #[allow(non_upper_case_globals)]
1240 pub(crate) static R_CStackStart: usize;
1241
1242 /// Stack size limit. Set to `usize::MAX` to disable stack checking.
1243 ///
1244 /// From R source: `if(R_CStackStart == -1) R_CStackLimit = -1; /* never set */`
1245 #[allow(non_upper_case_globals)]
1246 pub static R_CStackLimit: usize;
1247
1248 /// Stack growth direction: 1 = grows up, -1 = grows down.
1249 ///
1250 /// Most systems (x86, ARM) grow down (-1).
1251 #[allow(non_upper_case_globals)]
1252 pub(crate) static R_CStackDir: ::std::os::raw::c_int;
1253 }
1254
1255 /// Write to `R_CStackLimit`.
1256 ///
1257 /// # Safety
1258 /// Must be called from R's main thread.
1259 #[inline]
1260 pub unsafe fn set_r_cstack_limit(value: usize) {
1261 unsafe {
1262 let ptr = (&raw const R_CStackLimit).cast_mut();
1263 ptr.write(value);
1264 }
1265 }
1266
1267 // Issue #112 cat. 10: kept pub(crate) — nonapi stack helpers; used from thread.rs; wrapping adds no value
1268 /// Read `R_CStackLimit`.
1269 #[inline]
1270 pub(crate) fn get_r_cstack_limit() -> usize {
1271 unsafe { R_CStackLimit }
1272 }
1273
1274 /// Read `R_CStackStart`.
1275 #[inline]
1276 pub(crate) fn get_r_cstack_start() -> usize {
1277 unsafe { R_CStackStart }
1278 }
1279
1280 /// Read `R_CStackDir`.
1281 #[inline]
1282 pub(crate) fn get_r_cstack_dir() -> ::std::os::raw::c_int {
1283 unsafe { R_CStackDir }
1284 }
1285}
1286
1287// endregion
1288
1289// region: Inline Helper Functions (Rust implementations of R's inline functions)
1290
1291/// Create a length-1 string vector from a C string.
1292///
1293/// Rust equivalent of R's inline `Rf_mkString(s)`, which is
1294/// shorthand for `ScalarString(mkChar(s))`.
1295///
1296/// # Safety
1297///
1298/// - `s` must be a valid null-terminated C string
1299/// - Must be called from R's main thread
1300/// - Result must be protected from GC
1301#[doc(alias = "mkString")]
1302#[allow(non_snake_case)]
1303#[inline]
1304pub unsafe fn Rf_mkString(s: *const ::std::os::raw::c_char) -> SEXP {
1305 unsafe {
1306 let charsxp = Rf_mkChar(s);
1307 let protected = Rf_protect(charsxp);
1308 let result = Rf_ScalarString(protected);
1309 Rf_unprotect(1);
1310 result
1311 }
1312}
1313
1314/// Build a pairlist with 1 element.
1315///
1316/// Rust equivalent of R's inline `Rf_list1(s)`.
1317///
1318/// # Safety
1319///
1320/// - `s` must be a valid SEXP
1321/// - Must be called from R's main thread
1322/// - Result must be protected from GC
1323#[doc(alias = "list1")]
1324#[allow(non_snake_case)]
1325#[inline]
1326pub unsafe fn Rf_list1(s: SEXP) -> SEXP {
1327 unsafe { Rf_cons(s, R_NilValue) }
1328}
1329
1330/// Build a pairlist with 2 elements.
1331///
1332/// Rust equivalent of R's inline `Rf_list2(s, t)`.
1333///
1334/// # Safety
1335///
1336/// - Both SEXPs must be valid
1337/// - Must be called from R's main thread
1338/// - Result must be protected from GC
1339#[doc(alias = "list2")]
1340#[allow(non_snake_case)]
1341#[inline]
1342pub unsafe fn Rf_list2(s: SEXP, t: SEXP) -> SEXP {
1343 unsafe { Rf_cons(s, Rf_cons(t, R_NilValue)) }
1344}
1345
1346/// Build a pairlist with 3 elements.
1347///
1348/// Rust equivalent of R's inline `Rf_list3(s, t, u)`.
1349///
1350/// # Safety
1351///
1352/// - All SEXPs must be valid
1353/// - Must be called from R's main thread
1354/// - Result must be protected from GC
1355#[doc(alias = "list3")]
1356#[allow(non_snake_case)]
1357#[inline]
1358pub unsafe fn Rf_list3(s: SEXP, t: SEXP, u: SEXP) -> SEXP {
1359 unsafe { Rf_cons(s, Rf_cons(t, Rf_cons(u, R_NilValue))) }
1360}
1361
1362/// Build a pairlist with 4 elements.
1363///
1364/// Rust equivalent of R's inline `Rf_list4(s, t, u, v)`.
1365///
1366/// # Safety
1367///
1368/// - All SEXPs must be valid
1369/// - Must be called from R's main thread
1370/// - Result must be protected from GC
1371#[doc(alias = "list4")]
1372#[allow(non_snake_case)]
1373#[inline]
1374pub unsafe fn Rf_list4(s: SEXP, t: SEXP, u: SEXP, v: SEXP) -> SEXP {
1375 unsafe { Rf_cons(s, Rf_cons(t, Rf_cons(u, Rf_cons(v, R_NilValue)))) }
1376}
1377
1378/// Build a language object (call) with 1 element (the function).
1379///
1380/// Rust equivalent of R's inline `Rf_lang1(s)`.
1381/// Creates a call like `f()` where `s` is the function.
1382///
1383/// # Safety
1384///
1385/// - `s` must be a valid SEXP (typically a symbol or closure)
1386/// - Must be called from R's main thread
1387/// - Result must be protected from GC
1388#[doc(alias = "lang1")]
1389#[allow(non_snake_case)]
1390#[inline]
1391pub unsafe fn Rf_lang1(s: SEXP) -> SEXP {
1392 unsafe { Rf_lcons(s, R_NilValue) }
1393}
1394
1395/// Build a language object (call) with function and 1 argument.
1396///
1397/// Rust equivalent of R's inline `Rf_lang2(s, t)`.
1398/// Creates a call like `f(arg)` where `s` is the function and `t` is the argument.
1399///
1400/// # Safety
1401///
1402/// - Both SEXPs must be valid
1403/// - Must be called from R's main thread
1404/// - Result must be protected from GC
1405#[doc(alias = "lang2")]
1406#[allow(non_snake_case)]
1407#[inline]
1408pub unsafe fn Rf_lang2(s: SEXP, t: SEXP) -> SEXP {
1409 unsafe { Rf_lcons(s, Rf_list1(t)) }
1410}
1411
1412/// Build a language object (call) with function and 2 arguments.
1413///
1414/// Rust equivalent of R's inline `Rf_lang3(s, t, u)`.
1415/// Creates a call like `f(arg1, arg2)`.
1416///
1417/// # Safety
1418///
1419/// - All SEXPs must be valid
1420/// - Must be called from R's main thread
1421/// - Result must be protected from GC
1422#[doc(alias = "lang3")]
1423#[allow(non_snake_case)]
1424#[inline]
1425pub unsafe fn Rf_lang3(s: SEXP, t: SEXP, u: SEXP) -> SEXP {
1426 unsafe { Rf_lcons(s, Rf_list2(t, u)) }
1427}
1428
1429/// Build a language object (call) with function and 3 arguments.
1430///
1431/// Rust equivalent of R's inline `Rf_lang4(s, t, u, v)`.
1432/// Creates a call like `f(arg1, arg2, arg3)`.
1433///
1434/// # Safety
1435///
1436/// - All SEXPs must be valid
1437/// - Must be called from R's main thread
1438/// - Result must be protected from GC
1439#[doc(alias = "lang4")]
1440#[allow(non_snake_case)]
1441#[inline]
1442pub unsafe fn Rf_lang4(s: SEXP, t: SEXP, u: SEXP, v: SEXP) -> SEXP {
1443 unsafe { Rf_lcons(s, Rf_list3(t, u, v)) }
1444}
1445
1446/// Build a language object (call) with function and 4 arguments.
1447///
1448/// Rust equivalent of R's inline `Rf_lang5(s, t, u, v, w)`.
1449/// Creates a call like `f(arg1, arg2, arg3, arg4)`.
1450///
1451/// # Safety
1452///
1453/// - All SEXPs must be valid
1454/// - Must be called from R's main thread
1455/// - Result must be protected from GC
1456#[doc(alias = "lang5")]
1457#[allow(non_snake_case)]
1458#[inline]
1459pub unsafe fn Rf_lang5(s: SEXP, t: SEXP, u: SEXP, v: SEXP, w: SEXP) -> SEXP {
1460 unsafe { Rf_lcons(s, Rf_list4(t, u, v, w)) }
1461}
1462
1463/// Build a language object (call) with function and 5 arguments.
1464///
1465/// Rust equivalent of R's inline `Rf_lang6(s, t, u, v, w, x)`.
1466/// Creates a call like `f(arg1, arg2, arg3, arg4, arg5)`.
1467///
1468/// # Safety
1469///
1470/// - All SEXPs must be valid
1471/// - Must be called from R's main thread
1472/// - Result must be protected from GC
1473#[doc(alias = "lang6")]
1474#[allow(non_snake_case)]
1475#[inline]
1476pub unsafe fn Rf_lang6(s: SEXP, t: SEXP, u: SEXP, v: SEXP, w: SEXP, x: SEXP) -> SEXP {
1477 unsafe {
1478 let protected = Rf_protect(s);
1479 let list = Rf_cons(t, Rf_list4(u, v, w, x));
1480 let result = Rf_lcons(protected, list);
1481 Rf_unprotect(1);
1482 result
1483 }
1484}
1485
1486// endregion
1487
1488// region: RNG functions (R_ext/Random.h)
1489
1490/// RNG type enum from R_ext/Random.h
1491#[repr(u32)]
1492#[non_exhaustive]
1493#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
1494#[allow(non_camel_case_types)]
1495pub enum RNGtype {
1496 /// Wichmann-Hill generator.
1497 WICHMANN_HILL = 0,
1498 /// Marsaglia-Multicarry generator.
1499 MARSAGLIA_MULTICARRY = 1,
1500 /// Super-Duper generator.
1501 SUPER_DUPER = 2,
1502 /// Mersenne Twister generator.
1503 MERSENNE_TWISTER = 3,
1504 /// Knuth TAOCP generator.
1505 KNUTH_TAOCP = 4,
1506 /// User-supplied uniform generator.
1507 USER_UNIF = 5,
1508 /// Knuth TAOCP 2002 variant.
1509 KNUTH_TAOCP2 = 6,
1510 /// L'Ecuyer-CMRG generator.
1511 LECUYER_CMRG = 7,
1512}
1513
1514/// Normal distribution generator type enum from R_ext/Random.h
1515#[repr(u32)]
1516#[non_exhaustive]
1517#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
1518#[allow(non_camel_case_types)]
1519pub enum N01type {
1520 /// Legacy buggy Kinderman-Ramage method.
1521 BUGGY_KINDERMAN_RAMAGE = 0,
1522 /// Ahrens-Dieter method.
1523 AHRENS_DIETER = 1,
1524 /// Box-Muller transform.
1525 BOX_MULLER = 2,
1526 /// User-supplied normal generator.
1527 USER_NORM = 3,
1528 /// Inversion method.
1529 INVERSION = 4,
1530 /// Fixed Kinderman-Ramage method.
1531 KINDERMAN_RAMAGE = 5,
1532}
1533
1534/// Discrete uniform sample method enum from R_ext/Random.h
1535#[repr(u32)]
1536#[non_exhaustive]
1537#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
1538#[allow(non_camel_case_types)]
1539pub enum Sampletype {
1540 /// Rounding method for integer sampling.
1541 ROUNDING = 0,
1542 /// Rejection sampling method.
1543 REJECTION = 1,
1544}
1545
1546#[r_ffi_checked]
1547unsafe extern "C-unwind" {
1548 /// Save the current RNG state from R's global state.
1549 ///
1550 /// Must be called before using `unif_rand()`, `norm_rand()`, etc.
1551 /// The state is restored with `PutRNGstate()`.
1552 ///
1553 /// # Example
1554 ///
1555 /// ```ignore
1556 /// unsafe {
1557 /// GetRNGstate();
1558 /// let x = unif_rand();
1559 /// let y = norm_rand();
1560 /// PutRNGstate();
1561 /// }
1562 /// ```
1563 pub fn GetRNGstate();
1564
1565 /// Restore the RNG state to R's global state.
1566 ///
1567 /// Must be called after using `unif_rand()`, `norm_rand()`, etc.
1568 /// to ensure R's `.Random.seed` is updated.
1569 pub fn PutRNGstate();
1570
1571 /// Generate a uniform random number in (0, 1).
1572 ///
1573 /// # Important
1574 ///
1575 /// Must call `GetRNGstate()` before and `PutRNGstate()` after.
1576 pub fn unif_rand() -> f64;
1577
1578 /// Generate a standard normal random number (mean 0, sd 1).
1579 ///
1580 /// # Important
1581 ///
1582 /// Must call `GetRNGstate()` before and `PutRNGstate()` after.
1583 pub fn norm_rand() -> f64;
1584
1585 /// Generate an exponential random number with rate 1.
1586 ///
1587 /// # Important
1588 ///
1589 /// Must call `GetRNGstate()` before and `PutRNGstate()` after.
1590 pub fn exp_rand() -> f64;
1591
1592 /// Generate a uniform random index in [0, dn).
1593 ///
1594 /// Used for sampling without bias for large n.
1595 ///
1596 /// # Important
1597 ///
1598 /// Must call `GetRNGstate()` before and `PutRNGstate()` after.
1599 pub fn R_unif_index(dn: f64) -> f64;
1600
1601 /// Get the current discrete uniform sample method.
1602 pub fn R_sample_kind() -> Sampletype;
1603}
1604
1605// endregion
1606
1607// region: Memory allocation (R_ext/Memory.h)
1608
1609#[r_ffi_checked]
1610unsafe extern "C-unwind" {
1611 /// Get the current R memory stack watermark.
1612 ///
1613 /// Use with `vmaxset()` to restore memory stack state.
1614 /// Memory allocated with `R_alloc()` between `vmaxget()` and `vmaxset()`
1615 /// will be freed when `vmaxset()` is called.
1616 ///
1617 /// # Example
1618 ///
1619 /// ```ignore
1620 /// unsafe {
1621 /// let watermark = vmaxget();
1622 /// let buf = R_alloc(100, 1);
1623 /// // ... use buf ...
1624 /// vmaxset(watermark); // frees buf
1625 /// }
1626 /// ```
1627 pub fn vmaxget() -> *mut ::std::os::raw::c_void;
1628
1629 /// Set the R memory stack watermark, freeing memory allocated since the mark.
1630 ///
1631 /// # Safety
1632 ///
1633 /// `ovmax` must be a value returned by `vmaxget()` called earlier in the
1634 /// same R evaluation context.
1635 pub fn vmaxset(ovmax: *const ::std::os::raw::c_void);
1636
1637 /// Run the R garbage collector.
1638 ///
1639 /// Forces a full garbage collection cycle.
1640 pub fn R_gc();
1641
1642 /// Check if the garbage collector is currently running.
1643 ///
1644 /// Returns non-zero if GC is in progress.
1645 pub fn R_gc_running() -> ::std::os::raw::c_int;
1646
1647 /// Allocate memory on R's memory stack.
1648 ///
1649 /// This memory is automatically freed when the calling R function returns,
1650 /// or can be freed earlier with `vmaxset()`.
1651 ///
1652 /// # Parameters
1653 ///
1654 /// - `nelem`: Number of elements to allocate
1655 /// - `eltsize`: Size of each element in bytes
1656 ///
1657 /// # Returns
1658 ///
1659 /// Pointer to allocated memory (as `char*` for compatibility with S).
1660 pub fn R_alloc(nelem: usize, eltsize: ::std::os::raw::c_int) -> *mut ::std::os::raw::c_char;
1661
1662 /// Allocate an array of long doubles on R's memory stack.
1663 ///
1664 /// # Parameters
1665 ///
1666 /// - `nelem`: Number of long double elements to allocate
1667 pub fn R_allocLD(nelem: usize) -> *mut f64; // Note: f64 is close enough for most uses
1668
1669 /// S compatibility: allocate zeroed memory on R's memory stack.
1670 ///
1671 /// # Parameters
1672 ///
1673 /// - `nelem`: Number of elements
1674 /// - `eltsize`: Size of each element
1675 pub fn S_alloc(
1676 nelem: ::std::os::raw::c_long,
1677 eltsize: ::std::os::raw::c_int,
1678 ) -> *mut ::std::os::raw::c_char;
1679
1680 /// S compatibility: reallocate memory on R's memory stack.
1681 ///
1682 /// # Safety
1683 ///
1684 /// `ptr` must have been allocated by `S_alloc`.
1685 pub fn S_realloc(
1686 ptr: *mut ::std::os::raw::c_char,
1687 newsize: ::std::os::raw::c_long,
1688 oldsize: ::std::os::raw::c_long,
1689 eltsize: ::std::os::raw::c_int,
1690 ) -> *mut ::std::os::raw::c_char;
1691
1692 /// GC-aware malloc.
1693 ///
1694 /// Triggers GC if allocation fails, then retries.
1695 /// Memory must be freed with `free()`.
1696 pub fn R_malloc_gc(size: usize) -> *mut ::std::os::raw::c_void;
1697
1698 /// GC-aware calloc.
1699 ///
1700 /// Triggers GC if allocation fails, then retries.
1701 /// Memory must be freed with `free()`.
1702 pub fn R_calloc_gc(nelem: usize, eltsize: usize) -> *mut ::std::os::raw::c_void;
1703
1704 /// GC-aware realloc.
1705 ///
1706 /// Triggers GC if allocation fails, then retries.
1707 /// Memory must be freed with `free()`.
1708 pub fn R_realloc_gc(
1709 ptr: *mut ::std::os::raw::c_void,
1710 size: usize,
1711 ) -> *mut ::std::os::raw::c_void;
1712}
1713
1714// endregion
1715
1716// region: Sorting and utility functions (R_ext/Utils.h)
1717
1718#[r_ffi_checked]
1719unsafe extern "C-unwind" {
1720 /// Sort an integer vector in place (ascending order).
1721 ///
1722 /// # Parameters
1723 ///
1724 /// - `x`: Pointer to integer array
1725 /// - `n`: Number of elements
1726 pub fn R_isort(x: *mut ::std::os::raw::c_int, n: ::std::os::raw::c_int);
1727
1728 /// Sort a double vector in place (ascending order).
1729 ///
1730 /// # Parameters
1731 ///
1732 /// - `x`: Pointer to double array
1733 /// - `n`: Number of elements
1734 pub fn R_rsort(x: *mut f64, n: ::std::os::raw::c_int);
1735
1736 /// Sort a complex vector in place.
1737 ///
1738 /// # Parameters
1739 ///
1740 /// - `x`: Pointer to Rcomplex array
1741 /// - `n`: Number of elements
1742 pub fn R_csort(x: *mut Rcomplex, n: ::std::os::raw::c_int);
1743
1744 /// Sort doubles in descending order, carrying along an index array.
1745 ///
1746 /// # Parameters
1747 ///
1748 /// - `a`: Pointer to double array (sorted in place, descending)
1749 /// - `ib`: Pointer to integer array (permuted alongside `a`)
1750 /// - `n`: Number of elements
1751 #[doc(alias = "Rf_revsort")]
1752 pub fn revsort(a: *mut f64, ib: *mut ::std::os::raw::c_int, n: ::std::os::raw::c_int);
1753
1754 /// Sort doubles with index array.
1755 ///
1756 /// # Parameters
1757 ///
1758 /// - `x`: Pointer to double array (sorted in place)
1759 /// - `indx`: Pointer to integer array (permuted alongside `x`)
1760 /// - `n`: Number of elements
1761 pub fn rsort_with_index(
1762 x: *mut f64,
1763 indx: *mut ::std::os::raw::c_int,
1764 n: ::std::os::raw::c_int,
1765 );
1766
1767 /// Partial sort integers (moves k-th smallest to position k).
1768 ///
1769 /// # Parameters
1770 ///
1771 /// - `x`: Pointer to integer array
1772 /// - `n`: Number of elements
1773 /// - `k`: Target position (0-indexed)
1774 #[doc(alias = "Rf_iPsort")]
1775 pub fn iPsort(
1776 x: *mut ::std::os::raw::c_int,
1777 n: ::std::os::raw::c_int,
1778 k: ::std::os::raw::c_int,
1779 );
1780
1781 /// Partial sort doubles (moves k-th smallest to position k).
1782 ///
1783 /// # Parameters
1784 ///
1785 /// - `x`: Pointer to double array
1786 /// - `n`: Number of elements
1787 /// - `k`: Target position (0-indexed)
1788 #[doc(alias = "Rf_rPsort")]
1789 pub fn rPsort(x: *mut f64, n: ::std::os::raw::c_int, k: ::std::os::raw::c_int);
1790
1791 /// Partial sort complex numbers.
1792 ///
1793 /// # Parameters
1794 ///
1795 /// - `x`: Pointer to Rcomplex array
1796 /// - `n`: Number of elements
1797 /// - `k`: Target position (0-indexed)
1798 #[doc(alias = "Rf_cPsort")]
1799 pub fn cPsort(x: *mut Rcomplex, n: ::std::os::raw::c_int, k: ::std::os::raw::c_int);
1800
1801 /// Quicksort doubles in place.
1802 ///
1803 /// # Parameters
1804 ///
1805 /// - `v`: Pointer to double array
1806 /// - `i`: Start index (1-indexed for R compatibility)
1807 /// - `j`: End index (1-indexed)
1808 pub fn R_qsort(v: *mut f64, i: usize, j: usize);
1809
1810 /// Quicksort doubles with index array.
1811 ///
1812 /// # Parameters
1813 ///
1814 /// - `v`: Pointer to double array
1815 /// - `indx`: Pointer to index array (permuted alongside v)
1816 /// - `i`: Start index (1-indexed)
1817 /// - `j`: End index (1-indexed)
1818 pub fn R_qsort_I(
1819 v: *mut f64,
1820 indx: *mut ::std::os::raw::c_int,
1821 i: ::std::os::raw::c_int,
1822 j: ::std::os::raw::c_int,
1823 );
1824
1825 /// Quicksort integers in place.
1826 ///
1827 /// # Parameters
1828 ///
1829 /// - `iv`: Pointer to integer array
1830 /// - `i`: Start index (1-indexed)
1831 /// - `j`: End index (1-indexed)
1832 pub fn R_qsort_int(iv: *mut ::std::os::raw::c_int, i: usize, j: usize);
1833
1834 /// Quicksort integers with index array.
1835 ///
1836 /// # Parameters
1837 ///
1838 /// - `iv`: Pointer to integer array
1839 /// - `indx`: Pointer to index array
1840 /// - `i`: Start index (1-indexed)
1841 /// - `j`: End index (1-indexed)
1842 pub fn R_qsort_int_I(
1843 iv: *mut ::std::os::raw::c_int,
1844 indx: *mut ::std::os::raw::c_int,
1845 i: ::std::os::raw::c_int,
1846 j: ::std::os::raw::c_int,
1847 );
1848
1849 /// Expand a filename, resolving `~` and environment variables.
1850 ///
1851 /// # Returns
1852 ///
1853 /// Pointer to expanded path (in R's internal buffer, do not free).
1854 pub fn R_ExpandFileName(s: *const ::std::os::raw::c_char) -> *const ::std::os::raw::c_char;
1855
1856 /// Convert string to double, always using '.' as decimal point.
1857 ///
1858 /// Also accepts "NA" as input, returning NA_REAL.
1859 pub fn R_atof(str: *const ::std::os::raw::c_char) -> f64;
1860
1861 /// Convert string to double with end pointer, using '.' as decimal point.
1862 ///
1863 /// Like `strtod()` but locale-independent.
1864 pub fn R_strtod(c: *const ::std::os::raw::c_char, end: *mut *mut ::std::os::raw::c_char)
1865 -> f64;
1866
1867 /// Generate a temporary filename.
1868 ///
1869 /// # Parameters
1870 ///
1871 /// - `prefix`: Filename prefix
1872 /// - `tempdir`: Directory for temp file
1873 ///
1874 /// # Returns
1875 ///
1876 /// Newly allocated string (must be freed with `R_free_tmpnam`).
1877 pub fn R_tmpnam(
1878 prefix: *const ::std::os::raw::c_char,
1879 tempdir: *const ::std::os::raw::c_char,
1880 ) -> *mut ::std::os::raw::c_char;
1881
1882 /// Generate a temporary filename with extension.
1883 ///
1884 /// # Parameters
1885 ///
1886 /// - `prefix`: Filename prefix
1887 /// - `tempdir`: Directory for temp file
1888 /// - `fileext`: File extension (e.g., ".txt")
1889 ///
1890 /// # Returns
1891 ///
1892 /// Newly allocated string (must be freed with `R_free_tmpnam`).
1893 pub fn R_tmpnam2(
1894 prefix: *const ::std::os::raw::c_char,
1895 tempdir: *const ::std::os::raw::c_char,
1896 fileext: *const ::std::os::raw::c_char,
1897 ) -> *mut ::std::os::raw::c_char;
1898
1899 /// Free a temporary filename allocated by `R_tmpnam` or `R_tmpnam2`.
1900 pub fn R_free_tmpnam(name: *mut ::std::os::raw::c_char);
1901
1902 /// Check for R stack overflow.
1903 ///
1904 /// Throws an R error if stack is nearly exhausted.
1905 pub fn R_CheckStack();
1906
1907 /// Check for R stack overflow with extra space requirement.
1908 ///
1909 /// # Parameters
1910 ///
1911 /// - `extra`: Additional bytes needed
1912 pub fn R_CheckStack2(extra: usize);
1913
1914 /// Find the interval containing a value (binary search).
1915 ///
1916 /// Used for interpolation and binning.
1917 ///
1918 /// # Parameters
1919 ///
1920 /// - `xt`: Sorted breakpoints array
1921 /// - `n`: Number of breakpoints
1922 /// - `x`: Value to find
1923 /// - `rightmost_closed`: If TRUE, rightmost interval is closed
1924 /// - `all_inside`: If TRUE, out-of-bounds values map to endpoints
1925 /// - `ilo`: Initial guess for interval (1-indexed)
1926 /// - `mflag`: Output flag (see R documentation)
1927 ///
1928 /// # Returns
1929 ///
1930 /// Interval index (1-indexed).
1931 pub fn findInterval(
1932 xt: *const f64,
1933 n: ::std::os::raw::c_int,
1934 x: f64,
1935 rightmost_closed: Rboolean,
1936 all_inside: Rboolean,
1937 ilo: ::std::os::raw::c_int,
1938 mflag: *mut ::std::os::raw::c_int,
1939 ) -> ::std::os::raw::c_int;
1940
1941 /// Extended interval finding with left-open option.
1942 #[allow(clippy::too_many_arguments)]
1943 pub fn findInterval2(
1944 xt: *const f64,
1945 n: ::std::os::raw::c_int,
1946 x: f64,
1947 rightmost_closed: Rboolean,
1948 all_inside: Rboolean,
1949 left_open: Rboolean,
1950 ilo: ::std::os::raw::c_int,
1951 mflag: *mut ::std::os::raw::c_int,
1952 ) -> ::std::os::raw::c_int;
1953
1954 /// Find column maxima in a matrix.
1955 ///
1956 /// # Parameters
1957 ///
1958 /// - `matrix`: Column-major matrix data
1959 /// - `nr`: Number of rows
1960 /// - `nc`: Number of columns
1961 /// - `maxes`: Output array for column maxima indices (1-indexed)
1962 /// - `ties_meth`: How to handle ties (1=first, 2=random, 3=last)
1963 pub fn R_max_col(
1964 matrix: *const f64,
1965 nr: *const ::std::os::raw::c_int,
1966 nc: *const ::std::os::raw::c_int,
1967 maxes: *mut ::std::os::raw::c_int,
1968 ties_meth: *const ::std::os::raw::c_int,
1969 );
1970
1971 /// Check if a string represents FALSE in R.
1972 ///
1973 /// Recognizes "FALSE", "false", "False", "F", "f", etc.
1974 #[doc(alias = "Rf_StringFalse")]
1975 pub fn StringFalse(s: *const ::std::os::raw::c_char) -> Rboolean;
1976
1977 /// Check if a string represents TRUE in R.
1978 ///
1979 /// Recognizes "TRUE", "true", "True", "T", "t", etc.
1980 #[doc(alias = "Rf_StringTrue")]
1981 pub fn StringTrue(s: *const ::std::os::raw::c_char) -> Rboolean;
1982
1983 /// Check if a string is blank (empty or only whitespace).
1984 #[doc(alias = "Rf_isBlankString")]
1985 pub fn isBlankString(s: *const ::std::os::raw::c_char) -> Rboolean;
1986}
1987
1988// endregion
1989
1990// region: Additional Rinternals.h functions
1991
1992#[r_ffi_checked]
1993unsafe extern "C-unwind" {
1994 // String/character functions
1995
1996 /// Create a CHARSXP with specified encoding.
1997 ///
1998 /// # Parameters
1999 ///
2000 /// - `s`: C string
2001 /// - `encoding`: Character encoding (CE_UTF8, CE_LATIN1, etc.)
2002 // Issue #112 cat. 10: kept pub(crate) — 2 callers in encoding.rs; wrapping adds no value
2003 #[doc(alias = "mkCharCE")]
2004 pub(crate) fn Rf_mkCharCE(s: *const ::std::os::raw::c_char, encoding: cetype_t) -> SEXP;
2005
2006 /// Get the number of characters in a string/character.
2007 ///
2008 /// # Parameters
2009 ///
2010 /// - `x`: A string SEXP
2011 /// - `ntype`: Type of count (0=bytes, 1=chars, 2=width)
2012 /// - `allowNA`: Whether to allow NA values
2013 /// - `keepNA`: Whether to keep NA in result
2014 /// - `msg_name`: Name for error messages
2015 ///
2016 /// # Returns
2017 ///
2018 /// Character count or -1 on error.
2019 pub fn R_nchar(
2020 x: SEXP,
2021 ntype: ::std::os::raw::c_int,
2022 allowNA: Rboolean,
2023 keepNA: Rboolean,
2024 msg_name: *const ::std::os::raw::c_char,
2025 ) -> ::std::os::raw::c_int;
2026
2027 /// Convert SEXPTYPE to C string name.
2028 ///
2029 /// Returns a string like "INTSXP", "REALSXP", etc.
2030 #[doc(alias = "type2char")]
2031 pub fn Rf_type2char(sexptype: SEXPTYPE) -> *const ::std::os::raw::c_char;
2032
2033 /// Print an R value to the console.
2034 ///
2035 /// Uses R's standard print method for the object.
2036 #[doc(alias = "PrintValue")]
2037 pub fn Rf_PrintValue(x: SEXP);
2038
2039 // Environment functions
2040
2041 /// Create a new environment.
2042 ///
2043 /// # Parameters
2044 ///
2045 /// - `enclos`: Enclosing environment
2046 /// - `hash`: Whether to use a hash table
2047 /// - `size`: Initial hash table size (if hash is TRUE)
2048 // Issue #112 cat. 10: kept pub(crate) — 2 callers in environment.rs; wrapping adds no value
2049 pub(crate) fn R_NewEnv(enclos: SEXP, hash: Rboolean, size: ::std::os::raw::c_int) -> SEXP;
2050
2051 /// Check if a variable exists in an environment frame.
2052 ///
2053 /// Does not search enclosing environments.
2054 pub fn R_existsVarInFrame(rho: SEXP, symbol: SEXP) -> Rboolean;
2055
2056 /// Remove a variable from an environment frame.
2057 ///
2058 /// # Returns
2059 ///
2060 /// The removed value, or R_NilValue if not found.
2061 pub fn R_removeVarFromFrame(symbol: SEXP, env: SEXP) -> SEXP;
2062
2063 /// Get the top-level environment.
2064 ///
2065 /// Walks up enclosing environments until reaching a top-level env
2066 /// (global, namespace, or base).
2067 #[doc(alias = "topenv")]
2068 pub fn Rf_topenv(target: SEXP, envir: SEXP) -> SEXP;
2069
2070 // Matching functions
2071
2072 /// Match elements of first vector in second vector.
2073 ///
2074 /// Like R's `match()` function.
2075 ///
2076 /// # Parameters
2077 ///
2078 /// - `x`: Vector of values to match
2079 /// - `table`: Vector to match against
2080 /// - `nomatch`: Value to return for non-matches
2081 ///
2082 /// # Returns
2083 ///
2084 /// Integer vector of match positions (1-indexed, nomatch for non-matches).
2085 #[doc(alias = "match")]
2086 pub fn Rf_match(x: SEXP, table: SEXP, nomatch: ::std::os::raw::c_int) -> SEXP;
2087
2088 // Duplication and copying
2089
2090 /// Copy most attributes from source to target.
2091 ///
2092 /// Copies all attributes except names, dim, and dimnames.
2093 #[doc(alias = "copyMostAttrib")]
2094 pub fn Rf_copyMostAttrib(source: SEXP, target: SEXP);
2095
2096 /// Find first duplicated element.
2097 ///
2098 /// # Parameters
2099 ///
2100 /// - `x`: Vector to search
2101 /// - `fromLast`: If TRUE, search from end
2102 ///
2103 /// # Returns
2104 ///
2105 /// 0 if no duplicates, otherwise 1-indexed position of first duplicate.
2106 #[doc(alias = "any_duplicated")]
2107 pub fn Rf_any_duplicated(x: SEXP, fromLast: Rboolean) -> R_xlen_t;
2108
2109 // S4 functions
2110
2111 /// Convert to an S4 object.
2112 ///
2113 /// # Parameters
2114 ///
2115 /// - `object`: Object to convert
2116 /// - `flag`: Conversion flag
2117 #[doc(alias = "asS4")]
2118 pub fn Rf_asS4(object: SEXP, flag: Rboolean, complete: ::std::os::raw::c_int) -> SEXP;
2119
2120 /// Get the S3 class of an S4 object.
2121 #[doc(alias = "S3Class")]
2122 pub fn Rf_S3Class(object: SEXP) -> SEXP;
2123
2124 // Option access
2125
2126 /// Get an R option value.
2127 ///
2128 /// Equivalent to `getOption("name")` in R.
2129 ///
2130 /// # Parameters
2131 ///
2132 /// - `tag`: Symbol for option name
2133 #[doc(alias = "GetOption1")]
2134 pub fn Rf_GetOption1(tag: SEXP) -> SEXP;
2135
2136 /// Get the `digits` option.
2137 ///
2138 /// Returns the value of `getOption("digits")`.
2139 #[doc(alias = "GetOptionDigits")]
2140 pub fn Rf_GetOptionDigits() -> ::std::os::raw::c_int;
2141
2142 /// Get the `width` option.
2143 ///
2144 /// Returns the value of `getOption("width")`.
2145 #[doc(alias = "GetOptionWidth")]
2146 pub(crate) fn Rf_GetOptionWidth() -> ::std::os::raw::c_int;
2147
2148 // Factor functions
2149
2150 /// Check if a factor is ordered.
2151 #[doc(alias = "isOrdered")]
2152 pub fn Rf_isOrdered(s: SEXP) -> Rboolean;
2153
2154 /// Check if a factor is unordered.
2155 #[doc(alias = "isUnordered")]
2156 pub fn Rf_isUnordered(s: SEXP) -> Rboolean;
2157
2158 /// Check if a vector is unsorted.
2159 ///
2160 /// # Parameters
2161 ///
2162 /// - `x`: Vector to check
2163 /// - `strictly`: If TRUE, check for strictly increasing
2164 #[doc(alias = "isUnsorted")]
2165 pub fn Rf_isUnsorted(x: SEXP, strictly: Rboolean) -> ::std::os::raw::c_int;
2166
2167 // Expression and evaluation
2168
2169 /// Substitute in an expression.
2170 ///
2171 /// Like R's `substitute()` function.
2172 #[doc(alias = "substitute")]
2173 pub fn Rf_substitute(lang: SEXP, rho: SEXP) -> SEXP;
2174
2175 /// Set vector length.
2176 ///
2177 /// For short vectors (length < 2^31).
2178 #[doc(alias = "lengthgets")]
2179 pub fn Rf_lengthgets(x: SEXP, newlen: R_xlen_t) -> SEXP;
2180
2181 /// Set vector length (long vector version).
2182 #[doc(alias = "xlengthgets")]
2183 pub fn Rf_xlengthgets(x: SEXP, newlen: R_xlen_t) -> SEXP;
2184
2185 // Protection (indexed — see cost table in the "GC protection" region above)
2186
2187 /// Protect a SEXP and record its stack index for later `R_Reprotect`.
2188 ///
2189 /// **Cost: O(1)** — same array write as `Rf_protect`, plus stores the index.
2190 /// No allocation. Use when you need to replace a protected value in-place
2191 /// (e.g., inside a loop that allocates) without unprotect/re-protect churn.
2192 #[doc(alias = "PROTECT_WITH_INDEX")]
2193 pub fn R_ProtectWithIndex(s: SEXP, index: *mut ::std::os::raw::c_int);
2194
2195 /// Replace the SEXP at a previously recorded protect stack index.
2196 ///
2197 /// **Cost: O(1)** — direct array write (`R_PPStack[index] = s`). No allocation.
2198 ///
2199 /// # Safety
2200 ///
2201 /// `index` must be from a previous `R_ProtectWithIndex` call and the
2202 /// stack must not have been unprotected past that index.
2203 #[doc(alias = "REPROTECT")]
2204 pub fn R_Reprotect(s: SEXP, index: ::std::os::raw::c_int);
2205
2206 // Weak references
2207
2208 /// Create a weak reference.
2209 ///
2210 /// # Parameters
2211 ///
2212 /// - `key`: The key object (weak reference target)
2213 /// - `val`: The value to associate
2214 /// - `fin`: Finalizer function (or R_NilValue)
2215 /// - `onexit`: Whether to run finalizer on R exit
2216 pub fn R_MakeWeakRef(key: SEXP, val: SEXP, fin: SEXP, onexit: Rboolean) -> SEXP;
2217
2218 /// Create a weak reference with C finalizer.
2219 pub fn R_MakeWeakRefC(key: SEXP, val: SEXP, fin: R_CFinalizer_t, onexit: Rboolean) -> SEXP;
2220
2221 /// Get the key from a weak reference.
2222 pub fn R_WeakRefKey(w: SEXP) -> SEXP;
2223
2224 /// Get the value from a weak reference.
2225 pub fn R_WeakRefValue(w: SEXP) -> SEXP;
2226
2227 /// Run pending finalizers.
2228 pub fn R_RunPendingFinalizers();
2229
2230 // Conversion list/vector
2231
2232 /// Convert a pairlist to a generic vector (list).
2233 #[doc(alias = "PairToVectorList")]
2234 pub fn Rf_PairToVectorList(x: SEXP) -> SEXP;
2235
2236 /// Convert a generic vector (list) to a pairlist.
2237 #[doc(alias = "VectorToPairList")]
2238 pub fn Rf_VectorToPairList(x: SEXP) -> SEXP;
2239
2240 // Install with CHARSXP
2241
2242 /// Install a symbol from a CHARSXP.
2243 ///
2244 /// Like `Rf_install()` but takes a CHARSXP instead of C string.
2245 #[doc(alias = "installChar")]
2246 pub fn Rf_installChar(x: SEXP) -> SEXP;
2247}
2248
2249// endregion