diff options
| author | Laytan Laats <laytanlaats@hotmail.com> | 2024-07-27 04:20:03 +0200 |
|---|---|---|
| committer | Laytan Laats <laytanlaats@hotmail.com> | 2024-08-14 01:44:35 +0200 |
| commit | efe68c2e24e0a38e591f146822ed93904e4193d7 (patch) | |
| tree | c2ac0ed3d08746495aa6adcd7a1c1ab052a7ee76 /core/sys/posix/stdlib.odin | |
| parent | ac68a9d52c3a9edc587e1ccab747613baf6f89de (diff) | |
posix: add package
Diffstat (limited to 'core/sys/posix/stdlib.odin')
| -rw-r--r-- | core/sys/posix/stdlib.odin | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/core/sys/posix/stdlib.odin b/core/sys/posix/stdlib.odin new file mode 100644 index 000000000..a1e2eab50 --- /dev/null +++ b/core/sys/posix/stdlib.odin @@ -0,0 +1,450 @@ +package posix + +import "base:intrinsics" + +import "core:c" +import "core:c/libc" + +when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +// stdlib.h - standard library definitions + +atof :: libc.atof +atoi :: libc.atoi +atol :: libc.atol +atoll :: libc.atoll +strtod :: libc.strtod +strtof :: libc.strtof +strtol :: libc.strtol +strtoll :: libc.strtoll +strtoul :: libc.strtoul +strtoull :: libc.strtoull + +rand :: libc.rand +srand :: libc.srand + +calloc :: libc.calloc +malloc :: libc.malloc +realloc :: libc.realloc + +abort :: libc.abort +atexit :: libc.atexit +at_quick_exit :: libc.at_quick_exit +exit :: libc.exit +_Exit :: libc._Exit +getenv :: libc.getenv +quick_exit :: libc.quick_exit +system :: libc.system + +bsearch :: libc.bsearch +qsort :: libc.qsort + +abs :: libc.abs +labs :: libc.labs +llabs :: libc.llabs +div :: libc.div +ldiv :: libc.ldiv +lldiv :: libc.lldiv + +mblen :: libc.mblen +mbtowc :: libc.mbtowc +wctomb :: libc.wctomb + +mbstowcs :: libc.mbstowcs +wcstombs :: libc.wcstombs + +free :: #force_inline proc(ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring { + libc.free(rawptr(ptr)) +} + +foreign lib { + /* + Takes a pointer to a radix-64 representation, in which the first digit is the least significant, + and return the corresponding long value. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/a64l.html ]] + */ + a64l :: proc(s: cstring) -> c.long --- + + /* + The l64a() function shall take a long argument and return a pointer to the corresponding + radix-64 representation. + + Returns: a string that may be invalidated by subsequent calls + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/a64l.html ]] + */ + l64a :: proc(value: c.long) -> cstring --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + Returns: non-negative, double-precision, floating-point values, uniformly distributed over the interval [0.0,1.0) + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + drand48 :: proc() -> c.double --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + Returns: non-negative, double-precision, floating-point values, uniformly distributed over the interval [0.0,1.0) + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + erand48 :: proc(xsubi: ^[3]c.ushort) -> c.double --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + Returns: return signed long integers uniformly distributed over the interval [-231,231) + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + mrand48 :: proc() -> c.long --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + Returns: return signed long integers uniformly distributed over the interval [-231,231) + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + jrand48 :: proc(xsubi: ^[3]c.ushort) -> c.long --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + Returns: non-negative, long integers, uniformly distributed over the interval [0,231) + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + lrand48 :: proc() -> c.long --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + Returns: non-negative, long integers, uniformly distributed over the interval [0,231) + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + nrand48 :: proc(xsubi: ^[3]c.ushort) -> c.long --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + The srand48(), seed48(), and lcong48() functions are initialization entry points, one of which should be invoked before either drand48(), lrand48(), or mrand48() is called. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + srand48 :: proc(seedval: c.long) --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + The srand48(), seed48(), and lcong48() functions are initialization entry points, one of which should be invoked before either drand48(), lrand48(), or mrand48() is called. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + lcong48 :: proc(param: ^[7]c.ushort) --- + + /* + This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic. + + The srand48(), seed48(), and lcong48() functions are initialization entry points, one of which should be invoked before either drand48(), lrand48(), or mrand48() is called. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html ]] + */ + seed48 :: proc(seed16v: ^[3]c.ushort) -> ^[3]c.ushort --- + + /* + Parses suboption arguments in a flag argument. + + Returns: the index of the matched token string, or -1 if no token strings were matched + + Example: + args := runtime.args__ + + Opt :: enum { + RO, + RW, + NAME, + NIL, + } + token := [Opt]cstring{ + .RO = "ro", + .RW = "rw", + .NAME = "name", + .NIL = nil, + } + + Options :: struct { + readonly, readwrite: bool, + name: cstring, + + } + opts: Options + + errfnd: bool + for { + opt := posix.getopt(i32(len(args)), raw_data(args), "o:") + if opt == -1 { + break + } + + switch opt { + case 'o': + subopt := posix.optarg + value: cstring + for subopt != "" && !errfnd { + o := posix.getsubopt(&subopt, &token[.RO], &value) + switch Opt(o) { + case .RO: opts.readonly = true + case .RW: opts.readwrite = true + case .NAME: + if value == nil { + fmt.eprintfln("missing value for suboption %s", token[.NAME]) + errfnd = true + continue + } + + opts.name = value + case .NIL: + fallthrough + case: + fmt.eprintfln("no match found for token: %s", value) + errfnd = true + } + } + if opts.readwrite && opts.readonly { + fmt.eprintfln("Only one of %s and %s can be specified", token[.RO], token[.RW]) + errfnd = true + } + case: + errfnd = true + } + } + + if errfnd || len(args) == 1 { + fmt.eprintfln("\nUsage: %s -o <suboptstring>", args[0]) + fmt.eprintfln("suboptions are 'ro', 'rw', and 'name=<value>'") + posix.exit(1) + } + + fmt.println(opts) + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsubopt.html ]] + */ + getsubopt :: proc(optionp: ^cstring, keylistp: [^]cstring, valuep: ^cstring) -> c.int --- + + /* + Changes the mode and ownership of the slave pseudo-terminal device associated with its master pseudo-terminal counterpart. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html ]] + */ + grantpt :: proc(fildes: FD) -> result --- + + /* + Allows a state array, pointed to by the state argument, to be initialized for future use. + + Returns: the previous state array or nil on failure + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html ]] + */ + @(link_name=LINITSTATE) + initstate :: proc(seed: c.uint, state: [^]byte, size: c.size_t) -> [^]byte --- + + /* + Sets the state array of the random number generator. + + Returns: the previous state array or nil on failure + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html ]] + */ + setstate :: proc(state: [^]byte) -> [^]byte --- + + /* + Use a non-linear additive feedback random-number generator employing a default state array + size of 31 long integers to return successive pseudo-random numbers in the range from 0 to 231-1. + The period of this random-number generator is approximately 16 x (231-1). + The size of the state array determines the period of the random-number generator. + Increasing the state array size shall increase the period. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html ]] + */ + random :: proc() -> c.long --- + + /* + Initializes the current state array using the value of seed. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html ]] + */ + @(link_name=LSRANDOM) + srandom :: proc(seed: c.uint) --- + + /* + Creates a directory with a unique name derived from template. + The application shall ensure that the string provided in template is a pathname ending + with at least six trailing 'X' characters. + + Returns: nil (setting errno) on failure, template on success + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html ]] + */ + mkdtemp :: proc(template: [^]byte) -> cstring --- + + /* + Creates a regular file with a unique name derived from template and return a file descriptor + for the file open for reading and writing. + The application shall ensure that the string provided in template is a pathname ending with + at least six trailing 'X' characters. + + Returns: -1 (setting errno) on failure, an open file descriptor on success + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html ]] + */ + mkstemp :: proc(template: cstring) -> FD --- + + /* + Allocates size bytes aligned on a boundary specified by alignment, and shall return a pointer + to the allocated memory in memptr. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_memalign.html ]] + */ + posix_memalign :: proc(memptr: ^[^]byte, alignment: c.size_t, size: c.size_t) -> Errno --- + + /* + Establishes a connection between a master device for a pseudo-terminal and a file descriptor. + + Returns: -1 (setting errno) on failure, an open file descriptor otherwise + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html ]] + */ + posix_openpt :: proc(oflag: O_Flags) -> FD --- + + /* + Returns the name of the slave pseudo-terminal device associated with a master pseudo-terminal device. + + Returns: nil (setting errno) on failure, the name on success, which may be invalidated on subsequent calls + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/ptsname.html ]] + */ + ptsname :: proc(fildes: FD) -> cstring --- + + /* + Unlocks the slave pseudo-terminal device associated with the master to which fildes refers. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html ]] + */ + unlockpt :: proc(fildes: FD) -> result --- + + /* + Uses the string argument to set environment variable values. + + Returns: 0 on success, non-zero (setting errno) on failure + + Example: + if posix.putenv("HOME=/usr/home") != 0 { + fmt.panicf("putenv failure: %v", posix.strerror(posix.errno())) + } + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/putenv.html ]] + */ + @(link_name=LPUTENV) + putenv :: proc(string: cstring) -> c.int --- + + /* + Updates or add a variable in the environment of the calling process. + + Example: + if posix.setenv("HOME", "/usr/home") != .OK { + fmt.panicf("putenv failure: %v", posix.strerror(posix.errno())) + } + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setenv.html ]] + */ + setenv :: proc(envname: cstring, envval: cstring, overwrite: b32) -> result --- + + /* + Removes an environment variable from the environment of the calling process. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/unsetenv.html ]] + */ + @(link_name=LUNSETENV) + unsetenv :: proc(name: cstring) -> result --- + + /* + Computes a sequence of pseudo-random integers in the range [0, {RAND_MAX}]. + (The value of the {RAND_MAX} macro shall be at least 32767.) + + If rand_r() is called with the same initial value for the object pointed to by seed and that object is not modified between successive returns and calls to rand_r(), the same sequence shall be generated. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand_r.html ]] + */ + rand_r :: proc(seed: ^c.uint) -> c.int --- + + /* + Derive, from the pathname file_name, an absolute pathname that resolves to the same directory entry, + whose resolution does not involve '.', '..', or symbolic links. + + If resolved_name is not `nil` it should be larger than `PATH_MAX` and the result will use it as a backing buffer. + If resolved_name is `nil` the returned string is allocated by `malloc`. + + Returns: `nil` (setting errno) on failure, the "real path" otherwise + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html ]] + */ + realpath :: proc(file_name: cstring, resolved_name: [^]byte = nil) -> cstring --- + + /* + Provides access to an implementation-defined encoding algorithm. + The argument of setkey() is an array of length 64 bytes containing only the bytes with numerical + value of 0 and 1. + + If this string is divided into groups of 8, the low-order bit in each group is ignored; this gives a 56-bit key which is used by the algorithm. + This is the key that shall be used with the algorithm to encode a string block passed to encrypt(). + + The setkey() function shall not change the setting of errno if successful. + An application wishing to check for error situations should set errno to 0 before calling setkey(). + If errno is non-zero on return, an error has occurred. + + Example: + key: [64]byte + // set key bytes... + + posix.set_errno(.NONE) + posix.setkey(raw_data(key)) + if errno := posix.errno(); errno != .NONE { + fmt.panicf("setkey failure: %s", posix.strerror(errno)) + } + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/setkey.html ]] + */ + setkey :: proc(key: [^]byte) --- +} + +EXIT_FAILURE :: libc.EXIT_FAILURE +EXIT_SUCCESS :: libc.EXIT_SUCCESS + +RAND_MAX :: libc.RAND_MAX +MB_CUR_MAX :: libc.MB_CUR_MAX + +div_t :: libc.div_t +ldiv_t :: libc.ldiv_t +lldiv_t :: libc.lldiv_t + +when ODIN_OS == .NetBSD { + @(private) LPUTENV :: "__putenv50" + @(private) LINITSTATE :: "__initstate60" + @(private) LSRANDOM :: "__srandom60" + @(private) LUNSETENV :: "__unsetenv13" +} else { + @(private) LPUTENV :: "putenv" + @(private) LINITSTATE :: "initstate" + @(private) LSRANDOM :: "srandom" + @(private) LUNSETENV :: "unsetenv" +} |