552 lines
17 KiB
C
552 lines
17 KiB
C
#ifndef VLIBC_STDLIB_H
|
|
#define VLIBC_STDLIB_H
|
|
|
|
/*
|
|
* vlibc — <stdlib.h>.
|
|
*
|
|
* This header is the shared home for the stdlib declarations; it currently
|
|
* holds only the memory-management family (todo 7). Later todos extend it
|
|
* in place: todo 11 adds the numeric conversions (atoi/strtol/strtod/...),
|
|
* todo 12 the pseudo-random and search/divide functions
|
|
* (rand/srand/qsort/bsearch/abs/div/...), and todo 13 the environment and
|
|
* multibyte helpers (getenv/setenv/mblen/mbtowc/...).
|
|
*
|
|
* Memory management functions, gated by the active compatibility profile
|
|
* (see include/vlibc/features.h). Levels are cumulative:
|
|
*
|
|
* Level 1 (onlyposix): ISO C core + POSIX base — malloc, free, calloc,
|
|
* realloc, aligned_alloc, posix_memalign.
|
|
* Level 2 (muslmimic): malloc_usable_size (BSD/musl).
|
|
*
|
|
* This header includes <vlibc/features.h> itself, so the gates below always
|
|
* see the configured VLIBC_LEVEL even when the caller included no vlibc
|
|
* header first, and <stddef.h> for size_t.
|
|
*/
|
|
|
|
#include <vlibc/features.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Level 1: memory management (always present). */
|
|
|
|
/*
|
|
* Allocate size bytes, 16-byte aligned. The memory is uninitialized.
|
|
* malloc(0) returns a unique minimum-size block (never NULL on success).
|
|
* NULL + errno ENOMEM on failure.
|
|
* malloc: the result does not alias any other pointer and has size bytes.
|
|
*/
|
|
__attribute__((malloc, alloc_size(1))) void *
|
|
malloc(size_t size);
|
|
|
|
/*
|
|
* Release the block at ptr, which must be NULL or a value returned by an
|
|
* earlier allocation in this family. free(NULL) is a no-op.
|
|
*/
|
|
void
|
|
free(void *ptr);
|
|
|
|
/*
|
|
* Allocate an array of nmemb elements of size bytes each, all bits zero.
|
|
* The product is overflow-checked: on overflow NULL + errno ENOMEM.
|
|
* calloc with a zero product returns a unique zeroed minimum-size block.
|
|
* malloc: the result does not alias any other pointer and has nmemb*size
|
|
* bytes.
|
|
*/
|
|
__attribute__((malloc, alloc_size(1, 2))) void *
|
|
calloc(size_t nmemb, size_t size);
|
|
|
|
/*
|
|
* Resize the block at ptr to size bytes, preserving the first min(old,
|
|
* size) bytes. realloc(NULL, size) behaves as malloc(size); realloc(ptr, 0)
|
|
* frees ptr and returns NULL. The old block is freed on success and left
|
|
* untouched on failure (NULL + errno ENOMEM).
|
|
* alloc_size(2): the result has size bytes.
|
|
*/
|
|
__attribute__((alloc_size(2))) void *
|
|
realloc(void *ptr, size_t size);
|
|
|
|
/*
|
|
* Allocate size bytes aligned to alignment. alignment must be a power of
|
|
* two that is a multiple of sizeof(void *), and size must be a multiple of
|
|
* alignment; a violation fails with NULL + errno EINVAL (a non-power-of-two
|
|
* alignment is undefined behavior in C23, so only well-formed arguments
|
|
* reach the allocator). size 0 returns NULL. The result is released with
|
|
* free.
|
|
* malloc + alloc_align(1): the result does not alias any other pointer and
|
|
* is aligned to alignment.
|
|
*/
|
|
__attribute__((malloc, alloc_size(2), alloc_align(1))) void *
|
|
aligned_alloc(size_t alignment, size_t size);
|
|
|
|
/*
|
|
* Allocate size bytes at address alignment and store the result in
|
|
* *memptr. alignment must be a power of two and a multiple of
|
|
* sizeof(void *). Returns 0 on success, EINVAL for a bad alignment, ENOMEM
|
|
* on allocation failure. Never sets errno itself, and never modifies
|
|
* *memptr on failure. size 0 returns a unique minimum-size block.
|
|
*/
|
|
__attribute__((access(write_only, 1))) int
|
|
posix_memalign(void **memptr, size_t alignment, size_t size);
|
|
|
|
#if VLIBC_LEVEL_GE(2)
|
|
/* Level 2 (muslmimic): BSD/musl extensions. */
|
|
|
|
/*
|
|
* Return the number of bytes actually available in the block at ptr,
|
|
* including any internal padding; at least as large as the requested size.
|
|
* ptr may be any block returned by the allocator family; NULL returns 0.
|
|
* pure: reads memory, no side effects.
|
|
*/
|
|
__attribute__((pure)) size_t
|
|
malloc_usable_size(void *ptr);
|
|
#endif /* VLIBC_LEVEL_GE(2) */
|
|
|
|
/* numeric conversions (todo 11) */
|
|
|
|
/*
|
|
* String-to-number conversions (C23 7.24.1). All are ISO C core / POSIX
|
|
* base and present in every profile.
|
|
*
|
|
* The ato* wrappers carry no error reporting: their behavior is undefined
|
|
* if the converted value cannot be represented (C23 7.24.1.1-2), so they
|
|
* read their input and nothing else — hence pure.
|
|
*
|
|
* The strto* functions report range errors through errno and store the
|
|
* scan position through endptr; both are real side effects, so they carry
|
|
* no intent attribute. errno behavior follows C23 7.24.1.4-5: ERANGE when
|
|
* the subject sequence is outside the representable range (the clamped
|
|
* maximum/minimum is returned); EINVAL when base is not 0 and not in
|
|
* [2, 36] (endptr left at nptr, 0 returned); endptr points at nptr when
|
|
* no subject sequence is present.
|
|
*/
|
|
|
|
/*
|
|
* Convert the initial decimal digits of nptr to int, discarding leading
|
|
* whitespace and an optional sign. Equivalent to (int)strtol(nptr, 0, 10).
|
|
* pure: reads memory, no side effects.
|
|
*/
|
|
__attribute__((pure)) int
|
|
atoi(const char *nptr);
|
|
|
|
/*
|
|
* As atoi, converted to long: strtol(nptr, 0, 10).
|
|
* pure: reads memory, no side effects.
|
|
*/
|
|
__attribute__((pure)) long
|
|
atol(const char *nptr);
|
|
|
|
/*
|
|
* As atoi, converted to long long: strtoll(nptr, 0, 10).
|
|
* pure: reads memory, no side effects.
|
|
*/
|
|
__attribute__((pure)) long long
|
|
atoll(const char *nptr);
|
|
|
|
/*
|
|
* As atoi, converted to double: strtod(nptr, 0).
|
|
* pure: reads memory, no side effects.
|
|
*/
|
|
__attribute__((pure)) double
|
|
atof(const char *nptr);
|
|
|
|
/*
|
|
* Convert the initial portion of nptr to long, stopping at the first
|
|
* character that is not part of the subject sequence and storing its
|
|
* position in *endptr (if endptr is not NULL). See the family comment for
|
|
* base, errno, and endptr semantics.
|
|
*/
|
|
long
|
|
strtol(const char *restrict nptr, char **restrict endptr, int base);
|
|
|
|
/*
|
|
* As strtol, converted to unsigned long. A subject sequence with a minus
|
|
* sign yields the negated value computed in the return type (modulo
|
|
* ULONG_MAX + 1) without a range error (C23 7.24.1.4p8).
|
|
*/
|
|
unsigned long
|
|
strtoul(const char *restrict nptr, char **restrict endptr, int base);
|
|
|
|
/*
|
|
* As strtol, converted to long long.
|
|
*/
|
|
long long
|
|
strtoll(const char *restrict nptr, char **restrict endptr, int base);
|
|
|
|
/*
|
|
* As strtol, converted to unsigned long long. Negative subject sequences
|
|
* wrap modulo ULLONG_MAX + 1 as for strtoul.
|
|
*/
|
|
unsigned long long
|
|
strtoull(const char *restrict nptr, char **restrict endptr, int base);
|
|
|
|
/*
|
|
* Convert the initial portion of nptr to float, double, or long double
|
|
* (C23 7.24.1.3): optional whitespace, optional sign, then either an
|
|
* "inf"/"infinity" or "nan"/"nan(n-char-sequence)" subject (case-
|
|
* insensitive), a hexadecimal floating subject ("0x1.8p1"), or a decimal
|
|
* floating subject with optional exponent. Overflow returns ±HUGE_VAL*
|
|
* with errno ERANGE; results too small to represent return a subnormal or
|
|
* zero value with errno ERANGE. no-conversion stores nptr in *endptr.
|
|
*/
|
|
double
|
|
strtod(const char *restrict nptr, char **restrict endptr);
|
|
|
|
float
|
|
strtof(const char *restrict nptr, char **restrict endptr);
|
|
|
|
long double
|
|
strtold(const char *restrict nptr, char **restrict endptr);
|
|
|
|
/* pseudo-random numbers, search, and integer arithmetic (todo 12) */
|
|
|
|
/*
|
|
* C23 7.22.2/7.22.5/7.22.6: rand/srand, qsort/bsearch, the abs family, and
|
|
* the div family are ISO C core and present in every profile. The abs and
|
|
* div functions compute a pure function of their arguments, so they are
|
|
* declared const (the compiler folds and eliminates the calls in static
|
|
* links; GCC's own builtin declarations of abs/labs/llabs are const, and
|
|
* the attribute here matches them). rand and srand carry state, and
|
|
* qsort/bsearch call a caller-supplied comparator, so none of those four
|
|
* carries an intent attribute.
|
|
*/
|
|
|
|
/*
|
|
* The largest value rand() returns: 2^31 - 1, the largest int.
|
|
*/
|
|
#define RAND_MAX 2147483647
|
|
|
|
/*
|
|
* Quotient/remainder pair from div/ldiv/lldiv: quot is the algebraic
|
|
* quotient truncated toward zero, rem the remainder of the same sign as
|
|
* the dividend, and quot*denom + rem == num.
|
|
*/
|
|
typedef struct
|
|
{
|
|
int quot;
|
|
int rem;
|
|
} div_t;
|
|
|
|
typedef struct
|
|
{
|
|
long quot;
|
|
long rem;
|
|
} ldiv_t;
|
|
|
|
typedef struct
|
|
{
|
|
long long quot;
|
|
long long rem;
|
|
} lldiv_t;
|
|
|
|
/*
|
|
* Absolute value of n. The most-negative value returns itself: the
|
|
* negation happens in the unsigned type, which wraps, so the result is
|
|
* never undefined behavior and errno is never set.
|
|
*/
|
|
__attribute__((const)) int
|
|
abs(int n);
|
|
|
|
__attribute__((const)) long
|
|
labs(long n);
|
|
|
|
__attribute__((const)) long long
|
|
llabs(long long n);
|
|
|
|
/*
|
|
* Quotient and remainder of num/denom, truncated toward zero.
|
|
*/
|
|
__attribute__((const)) div_t
|
|
div(int num, int denom);
|
|
|
|
__attribute__((const)) ldiv_t
|
|
ldiv(long num, long denom);
|
|
|
|
__attribute__((const)) lldiv_t
|
|
lldiv(long long num, long long denom);
|
|
|
|
/*
|
|
* Pseudo-random integer in [0, RAND_MAX], deterministic for a given
|
|
* srand seed.
|
|
*/
|
|
int
|
|
rand(void);
|
|
|
|
/*
|
|
* Seed the rand() sequence with seed.
|
|
*/
|
|
void
|
|
srand(unsigned int seed);
|
|
|
|
/*
|
|
* Sort the array of nmemb elements of size bytes at base into ascending
|
|
* order according to compar (C23 7.22.5.2). compar receives two pointers
|
|
* to distinct elements and returns negative/zero/positive. The sort is
|
|
* not stable.
|
|
*/
|
|
void
|
|
qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
|
|
|
|
/*
|
|
* Binary-search the array of nmemb sorted elements of size bytes at base
|
|
* for *key, calling compar(key, element) (C23 7.22.5.1). Returns a
|
|
* pointer to the matching element, or NULL when there is none.
|
|
*/
|
|
void *
|
|
bsearch(const void *key, const void *base, size_t nmemb, size_t size,
|
|
int (*compar)(const void *, const void *));
|
|
|
|
#if VLIBC_LEVEL_GE(2)
|
|
/* Level 2 (muslmimic): XSI and obsolescent extensions. */
|
|
|
|
/*
|
|
* Reentrant rand: the state lives in the caller's *seedp, which is
|
|
* updated on every call, so the sequence is independent of rand()'s own
|
|
* global state.
|
|
*/
|
|
int
|
|
rand_r(unsigned int *seedp);
|
|
|
|
/*
|
|
* random/srandom family (XSI): a 31-bit pseudo-random sequence in
|
|
* [0, 2^31). initstate installs state (size bytes, at least
|
|
* sizeof(long)) as the current state buffer, seeds it, and returns the
|
|
* previous buffer; setstate installs the buffer and returns the previous
|
|
* one. srandom reseeds the current buffer.
|
|
*/
|
|
long
|
|
random(void);
|
|
|
|
void
|
|
srandom(unsigned int seed);
|
|
|
|
char *
|
|
initstate(unsigned int seed, char *state, size_t size);
|
|
|
|
char *
|
|
setstate(char *state);
|
|
|
|
/*
|
|
* drand48 family (XSI): a 48-bit linear congruential sequence carried in
|
|
* three unsigned shorts, least-significant first. drand48/erand48 return
|
|
* the current value divided by 2^48 as a double in [0, 1); lrand48/
|
|
* nrand48 return the high 31 bits; mrand48/jrand48 the high 32 bits
|
|
* sign-extended. The erand48/nrand48/jrand48 forms step the caller's
|
|
* xsubi in place; srand48/seed48/lcong48 manage the shared state and the
|
|
* multiplier/addend.
|
|
*/
|
|
double
|
|
drand48(void);
|
|
|
|
double
|
|
erand48(unsigned short xsubi[3]);
|
|
|
|
long
|
|
lrand48(void);
|
|
|
|
long
|
|
nrand48(unsigned short xsubi[3]);
|
|
|
|
long
|
|
mrand48(void);
|
|
|
|
long
|
|
jrand48(unsigned short xsubi[3]);
|
|
|
|
void
|
|
srand48(long seedval);
|
|
|
|
unsigned short *
|
|
seed48(unsigned short seed16v[3]);
|
|
|
|
void
|
|
lcong48(unsigned short param[7]);
|
|
|
|
#endif /* VLIBC_LEVEL_GE(2) */
|
|
|
|
/* environment, multibyte characters, and temporary files (todo 13) */
|
|
|
|
/*
|
|
* getenv/setenv/unsetenv (POSIX base), the C-locale multibyte conversions
|
|
* (C23 7.24.7), and mkstemp/mkdtemp are level 1. The XSI/BSD extras —
|
|
* putenv, clearenv, mktemp, the PTY helpers, and getsubopt — are level 2.
|
|
*
|
|
* None of these functions carries an intent attribute. getenv and the
|
|
* environment mutators all read or write the shared global environ, so
|
|
* pure/const would let the compiler hoist a stale getenv result across a
|
|
* setenv call. The multibyte conversions are locale-stateful in general,
|
|
* the temporary-file functions create filesystem entries, and ptsname
|
|
* writes a shared static buffer — none of them is side-effect-free.
|
|
*/
|
|
|
|
/*
|
|
* The process environment: a NULL-terminated array of "name=value"
|
|
* strings. The array is installed by the startup code before main; the
|
|
* functions below mutate it (setenv/unsetenv copy strings into malloc'd
|
|
* storage). Reassigning environ directly is permitted by POSIX, but
|
|
* calling setenv/unsetenv/putenv/clearenv afterwards is undefined, as it
|
|
* is everywhere (the array is then no longer guaranteed to be owned by
|
|
* the library).
|
|
*/
|
|
extern char **environ;
|
|
|
|
/*
|
|
* Return a pointer to the value part (the bytes after '=') of the
|
|
* environment entry whose name matches name, or NULL when the variable
|
|
* is not set. The pointer is valid until the next setenv, unsetenv,
|
|
* putenv, or clearenv call. No intent attribute: the result depends on
|
|
* the mutable global environ.
|
|
*/
|
|
char *
|
|
getenv(const char *name);
|
|
|
|
/*
|
|
* Set name to value. A copy of "name=value" is made, so the caller may
|
|
* reuse or free its buffers once the call returns. With overwrite
|
|
* nonzero an existing entry is replaced; with overwrite zero an existing
|
|
* entry is left unchanged and 0 is returned. Returns -1 with errno
|
|
* EINVAL when name is NULL, empty, or contains '=', and -1 with errno
|
|
* ENOMEM on allocation failure. A NULL value is treated as the empty
|
|
* string.
|
|
*/
|
|
int
|
|
setenv(const char *name, const char *value, int overwrite);
|
|
|
|
/*
|
|
* Remove every entry whose name is name, compacting the array. Returns
|
|
* -1 with errno EINVAL when name is NULL, empty, or contains '='.
|
|
*/
|
|
int
|
|
unsetenv(const char *name);
|
|
|
|
/*
|
|
* C-locale multibyte conversions (C23 7.24.7). Only the "C" locale
|
|
* exists today (locale support is a later todo), where every multibyte
|
|
* character is a single byte: byte c corresponds to the wide character
|
|
* (unsigned char)c. The encoding is therefore stateless — the s == NULL
|
|
* and NULL-destination forms all report "state-independent" — and no
|
|
* mbstate_t variant is needed. mbtowc never fails in this locale (every
|
|
* byte, including 0x80..0xFF, is a valid character); wctomb fails with
|
|
* -1 + errno EILSEQ for any wchar_t outside 0..255.
|
|
*/
|
|
int
|
|
mblen(const char *s, size_t n);
|
|
|
|
int
|
|
mbtowc(wchar_t *restrict pwc, const char *restrict s, size_t n);
|
|
|
|
int
|
|
wctomb(char *s, wchar_t wc);
|
|
|
|
size_t
|
|
mbstowcs(wchar_t *restrict pwcs, const char *restrict s, size_t n);
|
|
|
|
size_t
|
|
wcstombs(char *restrict s, const wchar_t *restrict pwcs, size_t n);
|
|
|
|
/*
|
|
* Temporary files and directories. mkstemp replaces the trailing
|
|
* "XXXXXX" of the template with random characters, creates the file
|
|
* with mode 0600, and returns an open file descriptor (-1 with errno
|
|
* EINVAL when the template has no "XXXXXX" suffix). mkdtemp does the
|
|
* same replacement, creates a directory with mode 0700, and returns the
|
|
* template (NULL on failure). The parameter is unnamed in these
|
|
* declarations because POSIX's `template` is a C++ keyword and this
|
|
* header is compiled by C++ consumers too.
|
|
*/
|
|
int
|
|
mkstemp(char *);
|
|
|
|
char *
|
|
mkdtemp(char *);
|
|
|
|
/* process control (todo 20) */
|
|
|
|
/*
|
|
* Pass string to the command language interpreter: "sh -c string".
|
|
* Returns the shell's wait status (e.g. 768 for "exit 3"), 1 when
|
|
* string is NULL (a shell is always available), or -1 with errno set
|
|
* when the child cannot be created or reaped. During the run, SIGCHLD
|
|
* is blocked and SIGINT/SIGQUIT are ignored in the caller, as POSIX
|
|
* requires.
|
|
*/
|
|
int
|
|
system(const char *string);
|
|
|
|
#if VLIBC_LEVEL_GE(2)
|
|
/* Level 2 (muslmimic): XSI and BSD environment extras. */
|
|
|
|
/*
|
|
* Add string — a "name=value" pair in CALLER-OWNED storage — to the
|
|
* environment: the caller's buffer becomes part of the environment and
|
|
* must remain valid for the life of the process. An existing variable of
|
|
* the same name is replaced (the old pointer is dropped); a string
|
|
* without '=' removes the variable instead (glibc/musl behavior).
|
|
* Returns 0, or -1 with errno ENOMEM.
|
|
*/
|
|
int
|
|
putenv(char *string);
|
|
|
|
/*
|
|
* Empty the environment, leaving environ as a fresh valid empty array
|
|
* (never NULL) so later setenv calls keep working. The previous array
|
|
* and its entries are deliberately not freed — entries may be putenv'd
|
|
* caller storage or initial-stack strings. Returns 0, or -1 with errno
|
|
* ENOMEM.
|
|
*/
|
|
int
|
|
clearenv(void);
|
|
|
|
/*
|
|
* Obsolescent mkstemp without the file: fills in the trailing "XXXXXX"
|
|
* and returns the template, creating nothing. The name is not guaranteed
|
|
* unique — nothing exists to race on. NULL with errno EINVAL when the
|
|
* template has no "XXXXXX" suffix.
|
|
*/
|
|
char *
|
|
mktemp(char *);
|
|
|
|
/*
|
|
* XSI PTY helpers. posix_openpt opens the master side of a
|
|
* pseudo-terminal via /dev/ptmx (flags, plus O_NOCTTY, are passed to
|
|
* open) and returns the fd. grantpt returns 0 without doing anything:
|
|
* modern kernels grant the slave when the master is opened. unlockpt
|
|
* releases the slave-side lock. ptsname formats the slave path
|
|
* "/dev/pts/N" into a shared static buffer — the result is valid until
|
|
* the next ptsname call and is not thread-safe.
|
|
*/
|
|
int
|
|
posix_openpt(int flags);
|
|
|
|
char *
|
|
ptsname(int fd);
|
|
|
|
int
|
|
grantpt(int fd);
|
|
|
|
int
|
|
unlockpt(int fd);
|
|
|
|
/*
|
|
* Parse one comma-separated suboption out of *optionp (POSIX XSI). On
|
|
* success the index of the matching token is returned and *valuep points
|
|
* to the "=value" part (or is NULL when the suboption has no '='); for
|
|
* an unrecognized suboption -1 is returned and *valuep points to the
|
|
* whole suboption string; at the end of the list -1 is returned and
|
|
* *valuep is NULL. *optionp always advances past the comma, which is
|
|
* overwritten with NUL (the string is modified in place).
|
|
*/
|
|
int
|
|
getsubopt(char **optionp, char *const *tokens, char **valuep);
|
|
|
|
#endif /* VLIBC_LEVEL_GE(2) */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* VLIBC_STDLIB_H */
|