#ifndef VLIBC_STDLIB_H #define VLIBC_STDLIB_H /* * vlibc — . * * 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 itself, so the gates below always * see the configured VLIBC_LEVEL even when the caller included no vlibc * header first, and for size_t. */ #include #include #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) */ #ifdef __cplusplus } #endif #endif /* VLIBC_STDLIB_H */