hosted/libc
Hosted targets only.
The C library's declarations beneath the hosted providers, as ordinary extern(c) imports.
hosted/io and hosted/heap reach the operating system only through this module; the compiler links the C library and names none of it. open is declared variadic, as C declares it, and takes its mode as the one unnamed argument. Facts that differ between systems are chosen by compiler.os: the errno accessor, __errno_location on Linux and __error on Darwin and FreeBSD, and the open flags; stat's record follows the system and the C ABI. Read current_errno immediately after a failing call. A malloc result is the allocation union, so the null pointer is no_allocation rather than a pointer.
Items
- allocation type
- file_status type
- timespec type
- no_allocation atom
- eacces value
- eintr value
- enoent value
- eperm value
- erofs value
- file_status_size value
- o_creat value
- o_rdonly value
- o_trunc value
- o_wronly value
- close function
- current_errno function
- errno_cell function
- free function
- malloc function
- open function
- read function
- stat function
- strlen function
- write function
Executable example
This complete program is maintained in the repository runtime tests. View source.
-- C-owned startup uses the library's startup-independent services: the C -- library through hosted/libc and the hosted heap, with no argument root. import core/mem import hosted/heap import hosted/libc -- Private Landin names cannot replace the library's calls into libc. strlen: () -> (result: usize) = result = 99 end strlen malloc: () -> (result: usize) = result = 99 end malloc free: () -> (result: usize) = result = 99 end free public extern(c) l_length: (data: ptr u8) -> (length: usize) = _ = strlen() length = libc.strlen(data) end l_length public extern(c) l_copy: (input: i32, output: i32, buffer: ptr mut u8, length: usize) -> (count: usize) = received := libc.read(input, buffer, length) count = 0 if received == isize(length) then count = usize(libc.write(output, buffer, length)) end if end l_copy public extern(c) l_heap: () -> (ok: bool) = _ = malloc() _ = free() ok = false mut provider: heap.system = heap.host() block: ptr mut u8 = mem.allocate(provider, usize(64), usize(24)) else (problem) _ = problem return end block.val = 42 ok = block.val == 42 and usize(block) % 24 == 0 mem.free(provider, block, usize(64)) end l_heap
allocation type
public allocation: type = no_allocation | ptr mut u8A malloc result: a block, or no_allocation.
file_status type
When compiler.os == freebsd
public file_status: type = struct
device: u64
inode: u64
links: u64
mode: u16
bsdflags: i16
uid: u32
gid: u32
padding: i32
special_device: u64
accessed: timespec
modified: timespec
changed: timespec
born: timespec
bytes: i64
blocks: i64
block_size: i32
flags: u32
generation: u64
revision: u64
spare: [9]u64
end file_statusC's struct stat, as stat fills it on this system.
When not (compiler.os == freebsd) and (compiler.c_sysv_lp64)
public file_status: type = struct
device: u64
inode: u64
links: u64
mode: u32
uid: u32
gid: u32
padding: i32
special_device: u64
bytes: i64
block_size: i64
blocks: i64
accessed: timespec
modified: timespec
changed: timespec
reserved: [3]i64
end file_statusC's struct stat, as stat fills it on this system.
When not (compiler.os == freebsd or compiler.c_sysv_lp64) and (compiler.c_aapcs64_lp64 or compiler.c_riscv_lp64d)
public file_status: type = struct
device: u64
inode: u64
mode: u32
links: u32
uid: u32
gid: u32
special_device: u64
padding1: u64
bytes: i64
block_size: i32
padding2: i32
blocks: i64
accessed: timespec
modified: timespec
changed: timespec
reserved: [2]u32
end file_statusC's struct stat, as stat fills it on this system.
When not (compiler.os == freebsd or compiler.c_sysv_lp64 or compiler.c_aapcs64_lp64 or compiler.c_riscv_lp64d)
public file_status: type = struct
device: i32
mode: u16
links: u16
inode: u64
uid: u32
gid: u32
special_device: i32
accessed: timespec
modified: timespec
changed: timespec
created: timespec
bytes: i64
blocks: i64
block_size: i32
flags: u32
generation: u32
spare: i32
reserved: [2]i64
end file_statusC's struct stat, as stat fills it on this system.
timespec type
public timespec: type = struct
seconds: i64
nanoseconds: i64
end timespecC's struct timespec: whole seconds and the nanoseconds after them.
no_allocation atom
public no_allocation: atomWhat malloc returns when it cannot allocate: C's null pointer.
eacces value
public eacces: i32 = 13errno: permission denied.
eintr value
public eintr: i32 = 4errno: interrupted by a signal before anything was transferred.
enoent value
public enoent: i32 = 2errno: no such file or directory.
eperm value
public eperm: i32 = 1errno: the operation is not permitted. The same on every hosted system.
erofs value
public erofs: i32 = 30errno: the file system is read-only.
file_status_size value
When compiler.os == freebsd
public file_status_size: usize = 224sizeof (struct stat) in the native C headers.
When not (compiler.os == freebsd) and (compiler.c_sysv_lp64)
public file_status_size: usize = 144sizeof (struct stat) in the native C headers.
When not (compiler.os == freebsd or compiler.c_sysv_lp64) and (compiler.c_aapcs64_lp64 or compiler.c_riscv_lp64d)
public file_status_size: usize = 128sizeof (struct stat) in the native C headers.
When not (compiler.os == freebsd or compiler.c_sysv_lp64 or compiler.c_aapcs64_lp64 or compiler.c_riscv_lp64d)
public file_status_size: usize = 144sizeof (struct stat) in the native C headers.
o_creat value
When compiler.os == linux
public o_creat: i32 = 64open flag: create the file if it does not exist. Linux keeps one value on every architecture; Darwin and FreeBSD share the BSD one.
When not (compiler.os == linux)
public o_creat: i32 = 512open flag: create the file if it does not exist. Linux keeps one value on every architecture; Darwin and FreeBSD share the BSD one.
o_rdonly value
public o_rdonly: i32 = 0open flag: read only. The same on every hosted system.
o_trunc value
When compiler.os == linux
public o_trunc: i32 = 512open flag: truncate an existing regular file to length zero.
When not (compiler.os == linux)
public o_trunc: i32 = 1024open flag: truncate an existing regular file to length zero.
o_wronly value
public o_wronly: i32 = 1open flag: write only. The same on every hosted system.
close function
public extern(c) close: (descriptor: i32) -> (status: i32)Close descriptor: 0, or -1 with the reason in errno. The descriptor may be released even when this fails, so a failed close is never retried.
current_errno function
public current_errno: () -> (number: i32)The calling thread's errno: the reason the last failing C call gave. Read it immediately after that call, before any other call that may set it.
errno_cell function
When compiler.os == linux
public extern(c) link(symbol: "__errno_location") errno_cell:
() -> (cell: ptr mut i32)The calling thread's errno cell, __errno_location on Linux and __error on Darwin and FreeBSD. Read it immediately after the failing call, before any other call that may set it.
When not (compiler.os == linux)
public extern(c) link(symbol: "__error") errno_cell:
() -> (cell: ptr mut i32)The calling thread's errno cell, __errno_location on Linux and __error on Darwin and FreeBSD. Read it immediately after the failing call, before any other call that may set it.
free function
public extern(c) free: (block: ptr mut u8) -> noneGive a block from malloc back to the C library.
malloc function
public extern(c) malloc: (size: usize) -> (block: allocation)Allocate size bytes aligned for any C object, or no_allocation. malloc(0) may return either; a caller that needs a distinct block for an empty request asks for a nonzero size.
open function
public extern(c) open: (path: ptr u8, flags: i32, ...) -> (descriptor: i32)Open the file at the NUL-terminated path and return its descriptor, or -1 with the reason in errno. flags is o_rdonly or o_wronly, or'd with o_creat and o_trunc; with o_creat the one variadic argument is the new file's permission bits as an i32, which the process umask filters.
read function
public extern(c) read: (descriptor: i32, data: ptr mut u8, length: usize)
-> (count: isize)Read at most length bytes from descriptor into data. The count read, zero at end of file, or -1 with the reason in errno. EINTR means nothing was transferred.
stat function
public extern(c) stat: (path: ptr u8, result: ptr mut file_status)
-> (status: i32)Fill result with the status of the file path names, following symbolic links: 0, or -1 with the reason in errno.
strlen function
public extern(c) strlen: (text: ptr u8) -> (length: usize)The number of bytes before the first NUL at text.
write function
public extern(c) write: (descriptor: i32, data: ptr u8, length: usize)
-> (count: isize)Write at most length bytes from data to descriptor. The count accepted, which may be short, or -1 with the reason in errno. EINTR means nothing was transferred.