Landin library reference source

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

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 u8

hosted/libc/libc.ldn:44

A 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_status

hosted/libc/libc.ldn:121

C'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_status

hosted/libc/libc.ldn:147

C'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_status

hosted/libc/libc.ldn:168

C'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_status

hosted/libc/libc.ldn:190

C's struct stat, as stat fills it on this system.

timespec type

public timespec: type = struct
    seconds: i64
    nanoseconds: i64
end timespec

hosted/libc/libc.ldn:108

C's struct timespec: whole seconds and the nanoseconds after them.

no_allocation atom

public no_allocation: atom

hosted/libc/libc.ldn:41

What malloc returns when it cannot allocate: C's null pointer.

eacces value

public eacces: i32 = 13

hosted/libc/libc.ldn:84

errno: permission denied.

eintr value

public eintr: i32 = 4

hosted/libc/libc.ldn:82

errno: interrupted by a signal before anything was transferred.

enoent value

public enoent: i32 = 2

hosted/libc/libc.ldn:80

errno: no such file or directory.

eperm value

public eperm: i32 = 1

hosted/libc/libc.ldn:78

errno: the operation is not permitted. The same on every hosted system.

erofs value

public erofs: i32 = 30

hosted/libc/libc.ldn:86

errno: the file system is read-only.

file_status_size value

When compiler.os == freebsd

public file_status_size: usize = 224

hosted/libc/libc.ldn:119

sizeof (struct stat) in the native C headers.

When not (compiler.os == freebsd) and (compiler.c_sysv_lp64)

public file_status_size: usize = 144

hosted/libc/libc.ldn:145

sizeof (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 = 128

hosted/libc/libc.ldn:166

sizeof (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 = 144

hosted/libc/libc.ldn:188

sizeof (struct stat) in the native C headers.

o_creat value

When compiler.os == linux

public o_creat: i32 = 64

hosted/libc/libc.ldn:96

open 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 = 512

hosted/libc/libc.ldn:102

open 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 = 0

hosted/libc/libc.ldn:89

open flag: read only. The same on every hosted system.

o_trunc value

When compiler.os == linux

public o_trunc: i32 = 512

hosted/libc/libc.ldn:98

open flag: truncate an existing regular file to length zero.

When not (compiler.os == linux)

public o_trunc: i32 = 1024

hosted/libc/libc.ldn:104

open flag: truncate an existing regular file to length zero.

o_wronly value

public o_wronly: i32 = 1

hosted/libc/libc.ldn:91

open flag: write only. The same on every hosted system.

close function

public extern(c) close: (descriptor: i32) -> (status: i32)

hosted/libc/libc.ldn:35

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)

hosted/libc/libc.ldn:71

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)

hosted/libc/libc.ldn:58

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)

hosted/libc/libc.ldn:64

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) -> none

hosted/libc/libc.ldn:52

Give a block from malloc back to the C library.

malloc function

public extern(c) malloc: (size: usize) -> (block: allocation)

hosted/libc/libc.ldn:49

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)

hosted/libc/libc.ldn:18

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)

hosted/libc/libc.ldn:23

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)

hosted/libc/libc.ldn:214

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)

hosted/libc/libc.ldn:38

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)

hosted/libc/libc.ldn:29

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.