x-engine-c v0.2.13
The C engine for x-lang
Loading...
Searching...
No Matches
ffi.c File Reference

Foreign Function Interface primitives for x-lang. More...

#include "x-prim.h"
#include "x-stdlib.h"
#include "x-sys.h"
#include "x-eval.h"
#include "x-type/int.h"
#include "x-type/prim.h"
#include "x-type/ptr.h"
#include "x-type/str.h"
#include "x-type/symbol.h"
#include <string.h>
#include <stdio.h>
#include <dlfcn.h>

Functions

static x_obj_tx_prim_dlopen (x_obj_t *p_base, x_obj_t *p_args)
 Open a dynamic shared library.
 
static x_obj_tx_prim_dlsym (x_obj_t *p_base, x_obj_t *p_args)
 Look up a symbol in a dynamic library.
 
static void * x_ffi_fptr (x_obj_t *p_base, x_obj_t *p_fptr, const char *who)
 Unwrap a function pointer, raising on nil.
 
static x_obj_tx_prim_ffi_call (x_obj_t *p_base, x_obj_t *p_args)
 Call a foreign function using a convention string.
 
static x_obj_tx_prim_ptr_call (x_obj_t *p_base, x_obj_t *p_args)
 Call a raw function pointer with up to 7 long-typed arguments.
 
static x_obj_tx_prim_int_to_ptr (x_obj_t *p_base, x_obj_t *p_args)
 Cast an integer to a pointer object.
 
static x_obj_tx_prim_ptr_to_int (x_obj_t *p_base, x_obj_t *p_args)
 Cast a pointer object to an integer.
 
static x_obj_tx_prim_mem_alloc (x_obj_t *p_base, x_obj_t *p_args)
 Allocate a raw, UNMANAGED byte region.
 
static x_obj_tx_prim_mem_copy (x_obj_t *p_base, x_obj_t *p_args)
 Block copy: the machine's rep-movs instruction.
 
static x_obj_tx_prim_mem_cmp (x_obj_t *p_base, x_obj_t *p_args)
 Block compare: the machine's rep-cmps instruction.
 
static x_obj_tx_prim_mem_set (x_obj_t *p_base, x_obj_t *p_args)
 Block fill: the machine's rep-stos instruction.
 
static x_obj_tx_prim_mem_free (x_obj_t *p_base, x_obj_t *p_args)
 Release a region obtained from (mem alloc).
 
static x_obj_tx_prim_ptr_set (x_obj_t *p_base, x_obj_t *p_args)
 Write nbytes of an integer value into raw memory at ptr+offset.
 
static x_obj_tx_prim_ptr_ref (x_obj_t *p_base, x_obj_t *p_args)
 Read nbytes from raw memory at ptr+offset as an integer.
 
static x_obj_tx_prim_ptr_alloc (x_obj_t *p_base, x_obj_t *p_args)
 Allocate n bytes of raw memory. x-lang: (ptr alloc n)
 
static x_obj_tx_prim_ptr_free (x_obj_t *p_base, x_obj_t *p_args)
 Release memory from (ptr alloc). x-lang: (ptr free! p)
 
static x_obj_tx_prim_ptr_copy (x_obj_t *p_base, x_obj_t *p_args)
 Copy n bytes between raw regions. x-lang: (ptr copy! dst src n)
 
static x_obj_tx_prim_ptr_fill (x_obj_t *p_base, x_obj_t *p_args)
 Set n bytes to byte. x-lang: (ptr fill! p byte n)
 
static x_obj_tx_prim_ptr_set_word (x_obj_t *p_base, x_obj_t *p_args)
 Write a machine-word-sized value into raw memory at ptr+offset.
 
static x_obj_tx_prim_string_to_ptr (x_obj_t *p_base, x_obj_t *p_args)
 Get the raw C string pointer from a string object.
 
static x_obj_tx_prim_ptr_to_string (x_obj_t *p_base, x_obj_t *p_args)
 Copy a C string from a pointer into a new string object.
 
static x_obj_tx_prim_obj_to_ptr (x_obj_t *p_base, x_obj_t *p_args)
 Get the raw C pointer to an x-lang object.
 
static x_obj_tx_prim_ptr_to_obj (x_obj_t *p_base, x_obj_t *p_args)
 Materialize an object reference from a raw pointer.
 
static x_obj_tx_prim_ptr_ref_word (x_obj_t *p_base, x_obj_t *p_args)
 Read a machine-word-sized value from raw memory at ptr+offset.
 
static x_obj_tx_prim_make_callable (x_obj_t *p_base, x_obj_t *p_args)
 Create a callable primitive from a raw function pointer.
 
x_obj_tx_prim_ffi_register (x_obj_t *p_base, x_obj_t *p_args)
 Register all FFI primitives and platform constants.
 
Double Bit-Pattern Helpers

IEEE 754 doubles are passed through the FFI as raw bit patterns stored in integers. On 64-bit platforms a single x_int_t holds the full 8-byte pattern; on 32-bit platforms two integers (a pair) carry the low and high halves.

static void x_ffi_to_double (x_obj_t *p_base, x_obj_t *p_bits, double *out)
 Convert a pair of integers to a C double (32-bit path).
 
static x_obj_tx_ffi_from_double (x_obj_t *p_base, double *in)
 Convert a C double to a pair of integers (32-bit path).
 
The engine's own C library, reachable from X

x-stdlib.h and x-sys.h in full.

The engine carries its own memcpy, memset, strlen, strcmp and allocator, and its own read/write/open/close, precisely so it need not assume a C library on the machine that runs it. None of it was reachable from X, so X code that wanted any of it reached dlopen/dlsym for libc's – borrowing exactly the dependency the engine went to the trouble of avoiding.

These operate on RAW MEMORY, not on x-lang strings: a char* here is a pointer object, which is why they are filed under ptr rather than str.

static x_obj_tx_prim_ptr_strlen (x_obj_t *p_base, x_obj_t *p_args)
 Length of the NUL-terminated string at p. x-lang: (ptr strlen p)
 
static x_obj_tx_prim_ptr_strcmp (x_obj_t *p_base, x_obj_t *p_args)
 Compare two NUL-terminated strings. x-lang: (ptr strcmp a b)
 
static x_obj_tx_prim_ptr_strncmp (x_obj_t *p_base, x_obj_t *p_args)
 Compare at most n bytes. x-lang: (ptr strncmp a b n)
 
static x_obj_tx_prim_ptr_strchr (x_obj_t *p_base, x_obj_t *p_args)
 First occurrence of byte c, or nil. x-lang: (ptr strchr p c)
 
static x_obj_tx_prim_ptr_strndup (x_obj_t *p_base, x_obj_t *p_args)
 Duplicate at most n bytes; the caller owns it. x-lang: (ptr strndup p n)
 
static x_obj_tx_prim_int_abs (x_obj_t *p_base, x_obj_t *p_args)
 Absolute value. x-lang: (int abs n)
 
static x_obj_tx_prim_sys_read (x_obj_t *p_base, x_obj_t *p_args)
 Read up to n bytes into raw memory. x-lang: (sys read fd p n)
 
static x_obj_tx_prim_sys_write (x_obj_t *p_base, x_obj_t *p_args)
 Write n bytes from raw memory. x-lang: (sys write fd p n)
 
static x_obj_tx_prim_sys_open (x_obj_t *p_base, x_obj_t *p_args)
 Open path with raw flags. x-lang: (sys open path flags)
 
static x_obj_tx_prim_sys_close (x_obj_t *p_base, x_obj_t *p_args)
 Close a descriptor. x-lang: (sys close fd)
 
static x_obj_tx_prim_sys_read_char (x_obj_t *p_base, x_obj_t *p_args)
 One byte from a descriptor, or -1. x-lang: (sys read-char fd)
 
static x_obj_tx_prim_sys_exit (x_obj_t *p_base, x_obj_t *p_args)
 Terminate the process. x-lang: (sys exit status)
 

Detailed Description

Foreign Function Interface primitives for x-lang.

Provides dynamic library loading (dlopen, dlsym), typed foreign calls (ffi-call with convention strings), raw pointer calls (ptr-call), pointer/integer/string/object conversions (int->ptr, ptr->int, str->ptr, ptr->str, obj->ptr, ptr->obj), raw memory access (ptr-ref, ptr-set!, ptr-ref-word, ptr-set-word!), and callable construction (make-callable). (The obj-meta-* accessors are pure x-lang now: boot/reflect.x files reflective implementations into the catalog over the layout contracts.)

Author
Jon Ruttan (jonru.nosp@m.ttan.nosp@m.@gmai.nosp@m.l.co.nosp@m.m)

Function Documentation

◆ x_ffi_fptr()

static void * x_ffi_fptr ( x_obj_t p_base,
x_obj_t p_fptr,
const char *  who 
)
static

Unwrap a function pointer, raising on nil.

Parameters
p_baseBase (execution context).
p_fptrEvaluated fptr argument (a POINTER object, or nil).
whoPrim name for the error message.
Returns
The raw function pointer, never NULL.
Note
A nil here is almost always a dlsym MISS handed straight to a call – the v0.5.0 release run died exactly this way, on a Linux runner where sqrt is not reachable from a self-handle (the engine links no libm; macOS bundles the math functions, which is why the crash never showed there). Calling through NULL is not catchable; this raise is.

◆ x_ffi_from_double()

static x_obj_t * x_ffi_from_double ( x_obj_t p_base,
double *  in 
)
static

Convert a C double to a pair of integers (32-bit path).

Parameters
p_baseBase (execution context) for allocation.
[in]inPointer to the source double.
Returns
Pair of two integers (low . high) holding the raw bits.

◆ x_ffi_to_double()

static void x_ffi_to_double ( x_obj_t p_base,
x_obj_t p_bits,
double *  out 
)
static

Convert a pair of integers to a C double (32-bit path).

Parameters
p_baseUnused.
p_bitsPair whose first/rest are the low/high 32-bit halves.
[out]outDestination double.

◆ x_prim_dlopen()

static x_obj_t * x_prim_dlopen ( x_obj_t p_base,
x_obj_t p_args 
)
static

Open a dynamic shared library.

x-lang form:

(dlopen path flags)

Wraps POSIX dlopen(3). If path is nil, opens the main program handle.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self path-string flags-int).
Returns
Pointer object wrapping the library handle, or NULL on failure.
Note
FFI: calls dlopen(3) directly.

◆ x_prim_dlsym()

static x_obj_t * x_prim_dlsym ( x_obj_t p_base,
x_obj_t p_args 
)
static

Look up a symbol in a dynamic library.

x-lang form:

(dlsym handle name)

Wraps POSIX dlsym(3).

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self handle-ptr name-string).
Returns
Pointer object wrapping the symbol address, or NULL if not found.
Note
FFI: calls dlsym(3) directly.

◆ x_prim_ffi_call()

static x_obj_t * x_prim_ffi_call ( x_obj_t p_base,
x_obj_t p_args 
)
static

Call a foreign function using a convention string.

x-lang form:

(ffi-call convention fptr args...)

The convention string selects the calling convention and type coercions:

  • Function calls: "d->d" (double->double), "dd->d" (double,double->double)
  • Arithmetic: "d+d", "d-d", "d*d", "d/d" (inline double ops; no fptr needed). Float %% is NOT here: fmod goes through "dd->d" with a dlsym'd pointer (float.x's %libm handle), keeping this binary free of any link-time libm reference.
  • Comparisons: "d<d", "d>d", "d=d", "d<=d", "d>=d" (return t/f)
  • Casts: "i->d" (int to double bits), "d->i" (double bits to int)
  • String: "s0->d" (string,NULL->double via fptr), "d->s" (double to string)

Doubles are represented as raw IEEE 754 bit patterns in integers.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self convention-string fptr args...).
Returns
Result of the foreign call, or NULL for unknown convention.
Note
FFI: double bit-patterns are platform-dependent (64-bit vs 32-bit pair).
See also
x_ffi_to_double, x_ffi_from_double

◆ x_prim_ffi_register()

x_obj_t * x_prim_ffi_register ( x_obj_t p_base,
x_obj_t p_args 
)

Register all FFI primitives and platform constants.

Binds: dlopen, dlsym, ffi-call, ptr-call, int->ptr, ptr->int, ptr->obj, ptr-set!, ptr-ref, ptr-ref-word, ptr-set-word!, obj->ptr, str->ptr, ptr->str, make-callable. (The obj-meta-* accessors are pure x-lang now: boot/reflect.x files reflective implementations into the catalog over tools/contract/obj-layout.x and tools/contract/base-paths.x.)

Platform constants live in X, not here: word size is probed by boot/data.x, and the O_* open flags come from the per-OS tables in x/platform/syscall.x.

Parameters
p_baseBase (execution context) to bind primitives into.
p_argsUnused.
Returns
p_base.

◆ x_prim_int_abs()

static x_obj_t * x_prim_int_abs ( x_obj_t p_base,
x_obj_t p_args 
)
static

Absolute value. x-lang: (int abs n)

◆ x_prim_int_to_ptr()

static x_obj_t * x_prim_int_to_ptr ( x_obj_t p_base,
x_obj_t p_args 
)
static

Cast an integer to a pointer object.

x-lang form:

(int->ptr n)
Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self n).
Returns
Pointer object wrapping (void *)n.

◆ x_prim_make_callable()

static x_obj_t * x_prim_make_callable ( x_obj_t p_base,
x_obj_t p_args 
)
static

Create a callable primitive from a raw function pointer.

x-lang form:

(make-callable fn-ptr)

Wraps a PTR object's address as an x_fn_t in a new prim object, making it callable from x-lang as an operative.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self fn-ptr).
Returns
New callable prim object.
Note
FFI: the function pointer must follow the x_fn_t signature (x_obj_t *p_base, x_obj_t *p_args) -> x_obj_t *.

◆ x_prim_mem_alloc()

static x_obj_t * x_prim_mem_alloc ( x_obj_t p_base,
x_obj_t p_args 
)
static

Allocate a raw, UNMANAGED byte region.

x-lang form:

(mem-alloc n)

The region is zeroed (calloc semantics – deterministic contents) and returned as a POINTER object that does NOT own it: the caller must release it with (mem free), or it leaks. Prefer (str make) – a GC-owned region – unless a header-less block is required (FFI structs, alignment-sensitive out-params). UNCHECKED like first/rest: n is trusted.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self n).
Returns
Pointer object addressing the fresh region.

◆ x_prim_mem_cmp()

static x_obj_t * x_prim_mem_cmp ( x_obj_t p_base,
x_obj_t p_args 
)
static

Block compare: the machine's rep-cmps instruction.

x-lang form:

(mem-cmp a b n)

TRUE memcmp semantics (NUL bytes do not terminate – strncmp would be wrong for raw regions), implemented as a local byte loop so x-lib needs no new entry. Returns 0 on equality, else the sign of the first differing byte pair (-1/1). UNCHECKED.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self a b n).
Returns
Integer 0, -1, or 1.

◆ x_prim_mem_copy()

static x_obj_t * x_prim_mem_copy ( x_obj_t p_base,
x_obj_t p_args 
)
static

Block copy: the machine's rep-movs instruction.

x-lang form:

(mem-copy dst src n)

Copies n bytes from src to dst (x_lib_memcpy; regions must not overlap). UNCHECKED like first/rest: pointers and n are trusted. Side-effect prim: returns NULL.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self dst src n).
Returns
NULL.

◆ x_prim_mem_free()

static x_obj_t * x_prim_mem_free ( x_obj_t p_base,
x_obj_t p_args 
)
static

Release a region obtained from (mem alloc).

x-lang form:

(mem-free ptr)

UNCHECKED: freeing anything not returned by (mem alloc), or freeing twice, is UB exactly as in C. Side-effect prim: returns NULL.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr).
Returns
NULL.

◆ x_prim_mem_set()

static x_obj_t * x_prim_mem_set ( x_obj_t p_base,
x_obj_t p_args 
)
static

Block fill: the machine's rep-stos instruction.

x-lang form:

(mem-set p byte n)

Fills n bytes at p with byte (x_lib_memset). UNCHECKED. Side-effect prim: returns NULL.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self p byte n).
Returns
NULL.

◆ x_prim_obj_to_ptr()

static x_obj_t * x_prim_obj_to_ptr ( x_obj_t p_base,
x_obj_t p_args 
)
static

Get the raw C pointer to an x-lang object.

x-lang form:

(obj->ptr obj)

Returns the object's address as a pointer. The pointer is invalidated if GC relocates the object.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self obj).
Returns
Pointer object wrapping the object's address.
Note
The returned pointer may be invalidated by garbage collection.

◆ x_prim_ptr_alloc()

static x_obj_t * x_prim_ptr_alloc ( x_obj_t p_base,
x_obj_t p_args 
)
static

Allocate n bytes of raw memory. x-lang: (ptr alloc n)

x_sys_malloc is the engine's own allocator – x-cli.c, callcc.c, buffer.c and string.c all use it – and it was not reachable from X, so X code that wanted a scratch buffer reached dlopen/dlsym for libc's malloc instead. A runtime cannot assume a C library is on the machine that runs it.

The alternative already in X is (obj make), which allocates through the collector – right for a value, wrong for a scratch buffer, because such a buffer is then an object in the heap: a state-image writer's own workspace would land inside the image it is writing.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self n).
Returns
A pointer object, or nil when the allocation fails.
Note
The caller owns it; (ptr free!) releases it.

◆ x_prim_ptr_call()

static x_obj_t * x_prim_ptr_call ( x_obj_t p_base,
x_obj_t p_args 
)
static

Call a raw function pointer with up to 7 long-typed arguments.

x-lang form:

(ptr-call fptr args...)

Arguments are evaluated and coerced: integers become long, strings and pointers pass their raw C pointer. The function is called with the C calling convention (long, long, ...) -> long.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self fptr arg0 ... arg6).
Returns
Integer wrapping the long return value.
Note
FFI: maximum 7 arguments; excess arguments are silently ignored.

◆ x_prim_ptr_copy()

static x_obj_t * x_prim_ptr_copy ( x_obj_t p_base,
x_obj_t p_args 
)
static

Copy n bytes between raw regions. x-lang: (ptr copy! dst src n)

The engine has its own memcpy (x_lib_memcpy); reaching dlopen/dlsym for libc's is borrowing a system library a runtime cannot assume is present. The alternative in X is a per-byte loop, which costs hundreds of evals a byte – so without this coordinate the only options were a hack or a pathology.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self dst src n).
Returns
The destination pointer object.
Note
No bounds checking: the C layer is a CPU.

◆ x_prim_ptr_fill()

static x_obj_t * x_prim_ptr_fill ( x_obj_t p_base,
x_obj_t p_args 
)
static

Set n bytes to byte. x-lang: (ptr fill! p byte n)

The zeroing half of the same argument: a buffer wanted zeroed had to come from libc's calloc for want of this.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr byte n).
Returns
The pointer object.
Note
No bounds checking: the C layer is a CPU.

◆ x_prim_ptr_free()

static x_obj_t * x_prim_ptr_free ( x_obj_t p_base,
x_obj_t p_args 
)
static

Release memory from (ptr alloc). x-lang: (ptr free! p)

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr).
Returns
nil.
Note
Frees what the caller allocated; the collector knows nothing about it.

◆ x_prim_ptr_ref()

static x_obj_t * x_prim_ptr_ref ( x_obj_t p_base,
x_obj_t p_args 
)
static

Read nbytes from raw memory at ptr+offset as an integer.

x-lang form:

(ptr-ref ptr offset nbytes)

Copies nbytes from the memory at the pointer plus byte offset into a zero-initialized integer value via memcpy.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr offset nbytes).
Returns
Integer holding the read value.
Note
FFI: no bounds checking; caller must ensure valid memory region.

◆ x_prim_ptr_ref_word()

static x_obj_t * x_prim_ptr_ref_word ( x_obj_t p_base,
x_obj_t p_args 
)
static

Read a machine-word-sized value from raw memory at ptr+offset.

x-lang form:

(ptr-ref-word ptr offset)

Reads sizeof(long) bytes from memory at ptr+offset via memcpy.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr offset).
Returns
Integer holding the machine-word value.
Note
FFI: word size is sizeof(long); no bounds checking.

◆ x_prim_ptr_set()

static x_obj_t * x_prim_ptr_set ( x_obj_t p_base,
x_obj_t p_args 
)
static

Write nbytes of an integer value into raw memory at ptr+offset.

x-lang form:

(ptr-set! ptr offset value nbytes)

Copies the low nbytes of value via memcpy into the memory at the given pointer plus byte offset.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr offset value nbytes).
Returns
The original pointer object.
Note
FFI: no bounds checking; caller must ensure valid memory region.

◆ x_prim_ptr_set_word()

static x_obj_t * x_prim_ptr_set_word ( x_obj_t p_base,
x_obj_t p_args 
)
static

Write a machine-word-sized value into raw memory at ptr+offset.

x-lang form:

(ptr-set-word! ptr offset value)

Writes sizeof(long) bytes of value into memory at ptr+offset.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr offset value).
Returns
The original pointer object.
Note
FFI: word size is sizeof(long); no bounds checking.

◆ x_prim_ptr_strchr()

static x_obj_t * x_prim_ptr_strchr ( x_obj_t p_base,
x_obj_t p_args 
)
static

First occurrence of byte c, or nil. x-lang: (ptr strchr p c)

◆ x_prim_ptr_strcmp()

static x_obj_t * x_prim_ptr_strcmp ( x_obj_t p_base,
x_obj_t p_args 
)
static

Compare two NUL-terminated strings. x-lang: (ptr strcmp a b)

◆ x_prim_ptr_strlen()

static x_obj_t * x_prim_ptr_strlen ( x_obj_t p_base,
x_obj_t p_args 
)
static

Length of the NUL-terminated string at p. x-lang: (ptr strlen p)

◆ x_prim_ptr_strncmp()

static x_obj_t * x_prim_ptr_strncmp ( x_obj_t p_base,
x_obj_t p_args 
)
static

Compare at most n bytes. x-lang: (ptr strncmp a b n)

◆ x_prim_ptr_strndup()

static x_obj_t * x_prim_ptr_strndup ( x_obj_t p_base,
x_obj_t p_args 
)
static

Duplicate at most n bytes; the caller owns it. x-lang: (ptr strndup p n)

◆ x_prim_ptr_to_int()

static x_obj_t * x_prim_ptr_to_int ( x_obj_t p_base,
x_obj_t p_args 
)
static

Cast a pointer object to an integer.

x-lang form:

(ptr->int p)
Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr).
Returns
Integer wrapping the pointer's numeric address.

◆ x_prim_ptr_to_obj()

static x_obj_t * x_prim_ptr_to_obj ( x_obj_t p_base,
x_obj_t p_args 
)
static

Materialize an object reference from a raw pointer.

x-lang form:

(ptr->obj p)

The inverse of obj->ptr and the reflective ISA's load-word-as-reference instruction: it lets X read a word (e.g. an object's data or type slot via ptr-ref-word) and treat it as the object it addresses, which is what makes the reflective accessors in lib/x/boot/reflect.x able to RETURN objects, not just integers.

UNCHECKED, like first/rest: an address that is not a live object is undefined behaviour. Safe under the explicit-only GC (allocation never relocates), same argument as holding obj->ptr across an expression.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr).
Returns
The object at the pointer's address (nil for a NULL pointer).

◆ x_prim_ptr_to_string()

static x_obj_t * x_prim_ptr_to_string ( x_obj_t p_base,
x_obj_t p_args 
)
static

Copy a C string from a pointer into a new string object.

x-lang form:

(ptr->str ptr)

Reads a NUL-terminated string from the pointer address and duplicates it into a new owned string object.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self ptr).
Returns
New string object containing a copy of the C string.

◆ x_prim_string_to_ptr()

static x_obj_t * x_prim_string_to_ptr ( x_obj_t p_base,
x_obj_t p_args 
)
static

Get the raw C string pointer from a string object.

x-lang form:

(str->ptr str)

Returns a pointer to the string's internal character buffer. The pointer is only valid while the string is not garbage collected.

Parameters
p_baseBase (execution context).
p_argsUnevaluated: (self str).
Returns
Pointer object wrapping the string's char buffer.

◆ x_prim_sys_close()

static x_obj_t * x_prim_sys_close ( x_obj_t p_base,
x_obj_t p_args 
)
static

Close a descriptor. x-lang: (sys close fd)

◆ x_prim_sys_exit()

static x_obj_t * x_prim_sys_exit ( x_obj_t p_base,
x_obj_t p_args 
)
static

Terminate the process. x-lang: (sys exit status)

◆ x_prim_sys_open()

static x_obj_t * x_prim_sys_open ( x_obj_t p_base,
x_obj_t p_args 
)
static

Open path with raw flags. x-lang: (sys open path flags)

◆ x_prim_sys_read()

static x_obj_t * x_prim_sys_read ( x_obj_t p_base,
x_obj_t p_args 
)
static

Read up to n bytes into raw memory. x-lang: (sys read fd p n)

◆ x_prim_sys_read_char()

static x_obj_t * x_prim_sys_read_char ( x_obj_t p_base,
x_obj_t p_args 
)
static

One byte from a descriptor, or -1. x-lang: (sys read-char fd)

◆ x_prim_sys_write()

static x_obj_t * x_prim_sys_write ( x_obj_t p_base,
x_obj_t p_args 
)
static

Write n bytes from raw memory. x-lang: (sys write fd p n)

The door an image writer needed and did not have: (Sys fd-write) takes a STRING, and an image is binary, NULs included.