/** * slibc — Yet another C library * Copyright © 2015 Mattias Andrée (maandree@member.fsf.org) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* That's right. No inclusion-guard; we want multiple * headers to be able to define types by including this * header without the need of keeping in mind which * order headers are included. */ #include #include /* TODO [u]int(|_least|_fast)$N_t are compiler-dependent and may even * be compiler-flag-dependent. Some CPP-magic is required to * figure their exact underlaying intrinsic type and existence. */ /* Ensure that dependencies for type are defined. */ #if defined(__NEED_imaxdiv_t) && !defined(__NEED_intmax_t) # define __NEED_intmax_t #endif /** * Returns the maximum value of an unsigned integer type, * in that type. */ #ifndef __MAX_OF # define __MAX_OF(type) \ (((type)1) << sizeof(type)) #endif /** * An integer type for pointers, but not wider than `long int`. */ #ifndef __LIMITED_PTR_INT # if __PTR_BIT == __CHAR_BIT # define __LIMITED_PTR_INT char # elif __PTR_BIT == __SHORT_BIT # define __LIMITED_PTR_INT short int # elif __PTR_BIT == __INT_BIT # define __LIMITED_PTR_INT int # else # define __LIMITED_PTR_INT long int # endif #endif /** * Signed integer type of the result of subtracting two pointers. * May not be greater than the width of type `long int`. * * @since Always. */ #if defined(__NEED_ptrdiff_t) && !defined(__DEFINED_ptrdiff_t) # define __DEFINED_ptrdiff_t typedef signed __LIMITED_PTR_INT ptrdiff_t; #endif /** * Unsigned version of `ptrdiff_t` * * @since Always. */ #if defined(__NEED_uptrdiff_t) && !defined(__DEFINED_uptrdiff_t) # define __DEFINED_uptrdiff_t typedef unsigned __LIMITED_PTR_INT uptrdiff_t; #endif #ifndef __PORTABLE /** * Integer type which can represent any character. * May not be greater than the with of type long. * * Unicode originally had an, inclusive upper limit * of U+FFFF. UTF-8 however had 31-bits (U+7FFFFFFF). * Unicode is now limited to 0x10FFFF. * * 32 bits should be sufficient (long is at least 32 * bits), but why limit further than POSIX does. * * `wchar_t` is not safe for data serialisation/marshalling; * it is implementation specific and may depend on the * libc implementation, the version of the libc implementation, * and the microarchitecture. * * @since Always. */ # if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t) # define __DEFINED_wchar_t # if __WCHAR_BIT == 8 typedef __WCHAR_SIGNNESS __INT8 wchar_t # elif __WCHAR_BIT == 16 typedef __WCHAR_SIGNNESS __INT16 wchar_t # elif __WCHAR_BIT == 32 typedef __WCHAR_SIGNNESS __INT32 wchar_t # elif __WCHAR_BIT == 64 typedef __WCHAR_SIGNNESS __INT64 wchar_t # endif __warning("'wchar_t' is not guaranteed to be defined as expected, use 'int32_t'."); # endif # ifndef __WCHAR_MAX # if __WCHAR_BIT == 8 # define __WCHAR_MAX INT8_MAX # elif __WCHAR_BIT == 16 # define __WCHAR_MAX INT16_MAX # elif __WCHAR_BIT == 32 # define __WCHAR_MAX INT32_MAX # elif __WCHAR_BIT == 64 # define __WCHAR_MAX INT64_MAX # endif # endif /** * Variant of `wchar_t` that can hold the value of `WEOF`. * * `wint_t` is not safe for data serialisation/marshalling; * it is implementation specific and may depend on the * libc implementation, the version of the libc implementation, * and the microarchitecture. * * @since Always. */ # if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t) # define __DEFINED_wint_t typedef wchar_t wint_t __warning("'wint_t' is not guaranteed to be defined as expected, use 'int32_t'."); # endif #endif /** * Unsigned integer type of the result of the * `sizeof` operator. May not be greater than the * width of type `long int`. * * @since Always. */ #if defined(__NEED_size_t) && !defined(__DEFINED_size_t) # define __DEFINED_size_t typedef unsigned __LIMITED_PTR_INT size_t; #endif /** * Signed version of `size_t` * * @since Always. */ #if defined(__NEED_ssize_t) && !defined(__DEFINED_ssize_t) # define __DEFINED_ssize_t typedef signed __LIMITED_PTR_INT ssize_t; #endif /** * A type, of unspecified construct, whose alignment requirement * is at least as strict as that of every scalar type. * * @since Always. */ #if defined(__NEED_max_align_t) && !defined(__DEFINED_max_align_t) # define __DEFINED_max_align_t typedef struct { long long int __lli __attribute__((__aligned__(__alignof__(long long int)))); long double __ld __attribute__((__aligned__(__alignof__(long double)))); } max_align_t; #endif /** * Signed exact-width integer types. * * These types are guaranteed to use two's complement. * * @since Always. */ #if defined(__NEED_intN_t) && !defined(__DEFINED_intN_t) # define __DEFINED_intN_t typedef signed __INT8 int8_t; typedef signed __INT16 int16_t; typedef signed __INT32 int32_t; typedef signed __INT64 int64_t; #endif /** * Unsigned exact-width integer types. * * @since Always. */ #if defined(__NEED_uintN_t) && !defined(__DEFINED_uintN_t) # define __DEFINED_uintN_t typedef unsigned __INT8 uint8_t; typedef unsigned __INT16 uint16_t; typedef unsigned __INT32 uint32_t; typedef unsigned __INT64 uint64_t; #endif /** * Signed integer types with guaranteed minimum length * with otherwise minimal length. * * `int_least8_t`, `int_least16_t`, `int_least32_t`, and * `int_least64_t` are guaranteed to be defined. * * @since Always. */ #if defined(__NEED_int_leastN_t) && !defined(__DEFINED_int_leastN_t) # define __DEFINED_int_leastN_t typedef signed __INT8 int_least8_t; typedef signed __INT16 int_least16_t; typedef signed __INT32 int_least32_t; typedef signed __INT64 int_least64_t; #endif /** * Unsigned integer types with guaranteed minimum length * with otherwise minimal length. * * `uint_least8_t`, `uint_least16_t`, `uint_least32_t`, and * `uint_least64_t` are guaranteed to be defined. * * @since Always. */ #if defined(__NEED_uint_leastN_t) && !defined(__DEFINED_uint_leastN_t) # define __DEFINED_uint_leastN_t typedef unsigned __INT8 uint_least8_t; typedef unsigned __INT16 uint_least16_t; typedef unsigned __INT32 uint_least32_t; typedef unsigned __INT64 uint_least64_t; #endif /** * Signed integer types with guaranteed minimum length * and are thought to be the fastest to in most use-cases. * * `int_fast8_t`, `int_fast16_t`, `int_fast32_t`, and * `int_fast64_t` are guaranteed to be defined. * It is howevr strongly discouraged to uses this types * in serialised/marshalled data, as they may depend * on the C library the program is compiled against * and the version of that library. * * @since Always. */ #if defined(__NEED_int_fastN_t) && !defined(__DEFINED_int_fastN_t) # define __DEFINED_int_fastN_t typedef signed __INT_FAST8 int_fast8_t; typedef signed __INT_FAST16 int_fast16_t; typedef signed __INT_FAST32 int_fast32_t; typedef signed __INT_FAST64 int_fast64_t; #endif /** * Ubsigned integer types with guaranteed minimum length * and are thought to be the fastest to in most use-cases. * * `uint_fast8_t`, `uint_fast16_t`, `uint_fast32_t`, and * `uint_fast64_t` are guaranteed to be defined. * It is howevr strongly discouraged to uses this types * in serialised/marshalled data, as they may depend * on the C library the program is compiled against * and the version of that library. * * @since Always. */ #if defined(__NEED_uint_fastN_t) && !defined(__DEFINED_uint_fastN_t) # define __DEFINED_uint_fastN_t typedef unsigned __INT_FAST8 uint_fast8_t; typedef unsigned __INT_FAST16 uint_fast16_t; typedef unsigned __INT_FAST32 uint_fast32_t; typedef unsigned __INT_FAST64 uint_fast64_t; #endif /** * The widest signed integer type available. * * @since Always. */ #if defined(__NEED_intmax_t) && !defined(__DEFINED_intmax_t) # define __DEFINED_intmax_t typedef signed __INT64 intmax_t; #endif #ifndef __INTMAX_MAX # define __INTMAX_MAX INT64_MAX #endif /** * The widest unsigned integer type available. * * @since Always. */ #if defined(__NEED_uintmax_t) && !defined(__DEFINED_uintmax_t) # define __DEFINED_uintmax_t typedef unsigned __INT64 uintmax_t; #endif #ifndef __UINTMAX_MAX # define __UINTMAX_MAX UINT64_MAX #endif /** * A integer type over which operations are atomic. * It may be defined as volatile, slibc does not do * this however because it is good practice to do * so explcitily when using the `sig_atomic_t` type. * * @since Always. */ #if defined(__NEED_sig_atomic_t) && !defined(__DEFINED_sig_atomic_t) # define __DEFINED_sig_atomic_t typedef int sig_atomic_t; #endif #ifndef __SIG_ATOMIC_BIT # define __SIG_ATOMIC_BIT __INT_BIT #endif /** * A structure than holds both the quotient and * the remainer in an integer division, of * `int` type. * * @since Always. */ #if defined(__NEED_div_t) && !defined(__DEFINED_div_t) # define __DEFINED_div_t typedef struct { /** * Quotient. */ int quot; /** * Remainder. */ int rem; } div_t; #endif /** * A structure than holds both the quotient and * the remainer in an integer division, of * `long int` type. * * @since Always. */ #if defined(__NEED_ldiv_t) && !defined(__DEFINED_ldiv_t) # define __DEFINED_ldiv_t typedef struct { /** * Quotient. */ long int quot; /** * Remainder. */ long int rem; } ldiv_t; #endif /** * A structure than holds both the quotient and * the remainer in an integer division, of * `long long int` type. * * @since Always. */ #if defined(__NEED_lldiv_t) && !defined(__DEFINED_lldiv_t) # define __DEFINED_lldiv_t typedef struct { /** * Quotient. */ long long int quot; /** * Remainder. */ long long int rem; } lldiv_t; #endif /** * A structure than holds both the quotient and * the remainer in an integer division, of * `intmax_t` type. * * @since Always. */ #if defined(__NEED_imaxdiv_t) && !defined(__DEFINED_imaxdiv_t) # define __DEFINED_imaxdiv_t typedef struct { /** * Quotient. */ intmax_t quot; /** * Remainder. */ intmax_t rem; } imaxdiv_t; #endif /** * Locale datatype. * * @since Always. */ #if defined(__NEED_locale_t) && !defined(__DEFINED_locale_t) # define __DEFINED_locale_t typedef int locale_t; /* TODO not implemented */ #endif #ifndef __INTMAX_MAX # define __INTMAX_MAX INT64_MAX #endif /** * State of variadic argument-reading. * * @since Always. */ #define __ONLY_va_list # include #undef __ONLY_va_list /** * Datatype for file permissions and file type. * * @since Always. */ #if defined(__NEED_mode_t) && !defined(__DEFINED_mode_t) # define __DEFINED_mode_t typedef unsigned int mode_t; #endif /** * Datatype for process identifiers. * * @since Always. */ #if defined(__NEED_pid_t) && !defined(__DEFINED_pid_t) # define __DEFINED_pid_t typedef signed int pid_t; #endif /** * Datatype for user identifiers. * * @since Always. */ #if defined(__NEED_uid_t) && !defined(__DEFINED_uid_t) # define __DEFINED_uid_t typedef unsigned int uid_t; #endif /** * Datatype for group identifiers. * * @since Always. */ #if defined(__NEED_gid_t) && !defined(__DEFINED_gid_t) # define __DEFINED_gid_t typedef unsigned int gid_t; #endif /** * Datatype for microseconds. * (The name should be 'µseconds', but we are limited * to ASCII and 'u' looks similar to 'µ'.) * * @since Always. */ #if defined(__NEED_useconds_t) && !defined(__DEFINED_useconds_t) # define __DEFINED_useconds_t typedef signed long useconds_t; #endif /** * Datatype for file offsets. * * @since Always. */ #if defined(__NEED_off_t) && !defined(__DEFINED_off_t) # define __DEFINED_off_t typedef signed __INT64 off_t; #endif /** * Datatype for inode identifiers, the number identifying * a file on a filesystem. * ('inode' is probably a contraction of 'index node'.) * * @since Always. */ #if defined(__NEED_ino_t) && !defined(__DEFINED_ino_t) # define __DEFINED_ino_t typedef unsigned __INT64 ino_t; #endif /** * Datatype for device identifiers. * * @since Always. */ #if defined(__NEED_dev_t) && !defined(__DEFINED_dev_t) # define __DEFINED_dev_t typedef unsigned __INT64 dev_t; #endif /** * Datatype for filesystem block counts. * * @since Always. */ #if defined(__NEED_fsblkcnt_t) && !defined(__DEFINED_fsblkcnt_t) # define __DEFINED_fsblkcnt_t typedef unsigned __INT64 fsblkcnt_t; #endif /** * Datatype for filesystem file counts. * * @since Always. */ #if defined(__NEED_fsfilcnt_t) && !defined(__DEFINED_fsfilcnt_t) # define __DEFINED_fsfilcnt_t typedef unsigned __INT64 fsfilcnt_t; #endif /** * Datatype for block sizes. * * @since Always. */ #if defined(__NEED_blksize_t) && !defined(__DEFINED_blksize_t) # define __DEFINED_blksize_t typedef signed __LIMITED_PTR_INT blksize_t; #endif /** * Datatype for block counts. * * @since Always. */ #if defined(__NEED_blkcnt_t) && !defined(__DEFINED_blkcnt_t) # define __DEFINED_blkcnt_t typedef signed __INT64 blkcnt_t; #endif /* pid_t and suseconds_t may not exceed long int */