makefile: move pdlibc to extlib, add C++ stub standard headers

It now kind of compiles with x86_64-elf gcc (does not link though)
This commit is contained in:
2021-11-04 20:15:58 +08:00
parent 964893b14a
commit 98f92a9958
48 changed files with 134 additions and 28 deletions

11
extlib/pdlibc/README Normal file
View File

@ -0,0 +1,11 @@
The C library code here mostly comes from The Public Domain C Library (pdclib).
Get it here: https://rootdirectory.de/doku.php?id=pdclib:start
and here's the repo: https://github.com/DevSolar/pdclib
The original code is licensed under CC0 (Public Domain), and I'm really having a hard time
keeping track which file has been modified and how, etc.

9
extlib/pdlibc/abs.c Normal file
View File

@ -0,0 +1,9 @@
#include <stdint.h>
int abs(int val) {
if (val < 0)
return -val;
else
return val;
}

View File

@ -0,0 +1,50 @@
/* Diagnostics <assert.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_internal.h"
#ifndef _PDCLIB_ASSERT_H
#define _PDCLIB_ASSERT_H _PDCLIB_ASSERT_H
_PDCLIB_PUBLIC void _PDCLIB_assert99( const char * const, const char * const, const char * const );
_PDCLIB_PUBLIC void _PDCLIB_assert89( const char * const );
#endif
/* If NDEBUG is set, assert() is a null operation. */
#undef assert
#ifdef NDEBUG
#define assert( ignore ) ( (void) 0 )
#else
#if __STDC_VERSION__ >= 199901L
#define assert( expression ) ( ( expression ) ? (void) 0 \
: _PDCLIB_assert99( "Assertion failed: " #expression \
", function ", __func__, \
", file " __FILE__ \
", line " _PDCLIB_value2string( __LINE__ ) \
".\n" ) )
#else
#define assert( expression ) ( ( expression ) ? (void) 0 \
: _PDCLIB_assert89( "Assertion failed: " #expression \
", file " __FILE__ \
", line " _PDCLIB_value2string( __LINE__ ) \
".\n" ) )
#endif
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_ASSERT_H
#include _PDCLIB_EXTEND_ASSERT_H
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,110 @@
/* Character handling <ctype.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_CTYPE_H
#define _PDCLIB_CTYPE_H _PDCLIB_CTYPE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_internal.h"
/* Character classification functions */
/* Note that there is a difference between "whitespace" (any printing, non-
graph character, like horizontal and vertical tab), and "blank" (the literal
' ' space character).
There will be masking macros for each of these later on, but right now I
focus on the functions only.
*/
/* Returns isalpha( c ) || isdigit( c ) */
_PDCLIB_PUBLIC int isalnum( int c );
/* Returns isupper( c ) || islower( c ) in the "C" locale.
In any other locale, also returns true for a locale-specific set of
alphabetic characters which are neither control characters, digits,
punctation, or whitespace.
*/
_PDCLIB_PUBLIC int isalpha( int c );
/* Returns true if the character isspace() and used for separating words within
a line of text. In the "C" locale, only ' ' and '\t' are considered blanks.
*/
_PDCLIB_PUBLIC int isblank( int c );
/* Returns true if the character is a control character. */
_PDCLIB_PUBLIC int iscntrl( int c );
/* Returns true if the character is a decimal digit. Locale-independent. */
_PDCLIB_PUBLIC int isdigit( int c );
/* Returns true for every printing character except space (' ').
NOTE: This definition differs from that of iswgraph() in <wctype.h>,
which considers any iswspace() character, not only ' '.
*/
_PDCLIB_PUBLIC int isgraph( int c );
/* Returns true for lowercase letters in the "C" locale.
In any other locale, also returns true for a locale-specific set of
characters which are neither control characters, digits, punctation, or
space (' '). In a locale other than the "C" locale, a character might test
true for both islower() and isupper().
*/
_PDCLIB_PUBLIC int islower( int c );
/* Returns true for every printing character including space (' '). */
_PDCLIB_PUBLIC int isprint( int c );
/* Returns true for a locale-specific set of punctuation charcters; these
may not be whitespace or alphanumeric. In the "C" locale, returns true
for every printing character that is not whitespace or alphanumeric.
*/
_PDCLIB_PUBLIC int ispunct( int c );
/* Returns true for every standard whitespace character (' ', '\f', '\n', '\r',
'\t', '\v') in the "C" locale. In any other locale, also returns true for a
locale-specific set of characters for which isalnum() is false.
*/
_PDCLIB_PUBLIC int isspace( int c );
/* Returns true for uppercase letters in the "C" locale.
In any other locale, also returns true for a locale-specific set of
characters which are neither control characters, digits, punctation, or
space (' '). In a locale other than the "C" locale, a character might test
true for both islower() and isupper().
*/
_PDCLIB_PUBLIC int isupper( int c );
/* Returns true for any hexadecimal-digit character. Locale-independent. */
_PDCLIB_PUBLIC int isxdigit( int c );
/* Character case mapping functions */
/* Converts an uppercase letter to a corresponding lowercase letter. Input that
is not an uppercase letter remains unchanged.
*/
_PDCLIB_PUBLIC int tolower( int c );
/* Converts a lowercase letter to a corresponding uppercase letter. Input that
is not a lowercase letter remains unchanged.
*/
_PDCLIB_PUBLIC int toupper( int c );
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_CTYPE_H
#include _PDCLIB_EXTEND_CTYPE_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,202 @@
/* Errors <errno.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_ERRNO_H
#define _PDCLIB_ERRNO_H _PDCLIB_ERRNO_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_lib_ext1.h"
#include "pdclib/_PDCLIB_internal.h"
/* FIXME: With <threads.h>, this needs to be in thread-specific storage. */
#define errno (*_PDCLIB_errno_func())
/* C only requires the following three */
/* Result too large */
#define ERANGE _PDCLIB_ERANGE
/* Mathematics argument out of domain of function */
#define EDOM _PDCLIB_EDOM
/* Illegal byte sequence */
#define EILSEQ _PDCLIB_EILSEQ
/* C++ additionally requires the folloing */
/* Argument list too long */
#define E2BIG _PDCLIB_E2BIG
/* Permission denied */
#define EACCES _PDCLIB_EACCES
/* Address in use */
#define EADDRINUSE _PDCLIB_EADDRINUSE
/* Address not available */
#define EADDRNOTAVAIL _PDCLIB_EADDRNOTAVAIL
/* Address family not supported */
#define EAFNOSUPPORT _PDCLIB_EAFNOSUPPORT
/* Resource unavailable, try again */
#define EAGAIN _PDCLIB_EAGAIN
/* Connection already in progress */
#define EALREADY _PDCLIB_EALREADY
/* Bad file descriptor */
#define EBADF _PDCLIB_EBADF
/* Bad message */
#define EBADMSG _PDCLIB_EBADMSG
/* Device or resource busy */
#define EBUSY _PDCLIB_EBUSY
/* Operation canceled */
#define ECANCELED _PDCLIB_ECANCELED
/* No child processes */
#define ECHILD _PDCLIB_ECHILD
/* Connection aborted */
#define ECONNABORTED _PDCLIB_ECONNABORTED
/* Connection refused */
#define ECONNREFUSED _PDCLIB_ECONNREFUSED
/* Connection reset */
#define ECONNRESET _PDCLIB_ECONNRESET
/* Resource deadlock would occur */
#define EDEADLK _PDCLIB_EDEADLK
/* Destination address required */
#define EDESTADDRREQ _PDCLIB_EDESTADDRREQ
/* File exists */
#define EEXIST _PDCLIB_EEXIST
/* Bad address */
#define EFAULT _PDCLIB_EFAULT
/* File too large */
#define EFBIG _PDCLIB_EFBIG
/* Host is unreachable */
#define EHOSTUNREACH _PDCLIB_EHOSTUNREACH
/* Identifier removed */
#define EIDRM _PDCLIB_EIDRM
/* Operation in progress */
#define EINPROGRESS _PDCLIB_EINPROGRESS
/* Interrupted function */
#define EINTR _PDCLIB_EINTR
/* Invalid argument */
#define EINVAL _PDCLIB_EINVAL
/* I/O error */
#define EIO _PDCLIB_EIO
/* Socket is connected */
#define EISCONN _PDCLIB_EISCONN
/* Is a directory */
#define EISDIR _PDCLIB_EISDIR
/* Too many levels of symbolic links */
#define ELOOP _PDCLIB_ELOOP
/* File descriptor value too large */
#define EMFILE _PDCLIB_EMFILE
/* Too many links */
#define EMLINK _PDCLIB_EMLINK
/* Message too large */
#define EMSGSIZE _PDCLIB_EMSGSIZE
/* Filename too long */
#define ENAMETOOLONG _PDCLIB_ENAMETOOLONG
/* Network is down */
#define ENETDOWN _PDCLIB_ENETDOWN
/* Connection aborted by network */
#define ENETRESET _PDCLIB_ENETRESET
/* Network unreachable */
#define ENETUNREACH _PDCLIB_ENETUNREACH
/* Too many files open in system */
#define ENFILE _PDCLIB_ENFILE
/* No buffer space available */
#define ENOBUFS _PDCLIB_ENOBUFS
/* No message is available on the STREAM head read queue */
#define ENODATA _PDCLIB_ENODATA
/* No such device */
#define ENODEV _PDCLIB_ENODEV
/* No such file or directory */
#define ENOENT _PDCLIB_ENOENT
/* Executable file format error */
#define ENOEXEC _PDCLIB_ENOEXEC
/* No locks available */
#define ENOLCK _PDCLIB_ENOLCK
/* Link has been severed */
#define ENOLINK _PDCLIB_ENOLINK
/* Not enough space */
#define ENOMEM _PDCLIB_ENOMEM
/* No message of the desired type */
#define ENOMSG _PDCLIB_ENOMSG
/* Protocol not available */
#define ENOPROTOOPT _PDCLIB_ENOPROTOOPT
/* No space left on device */
#define ENOSPC _PDCLIB_ENOSPC
/* No STREAM resources */
#define ENOSR _PDCLIB_ENOSR
/* Not a STREAM */
#define ENOSTR _PDCLIB_ENOSTR
/* Function not supported */
#define ENOSYS _PDCLIB_ENOSYS
/* The socket is not connected */
#define ENOTCONN _PDCLIB_ENOTCONN
/* Not a directory */
#define ENOTDIR _PDCLIB_ENOTDIR
/* Directory not empty */
#define ENOTEMPTY _PDCLIB_ENOTEMPTY
/* State not recoverable */
#define ENOTRECOVERABLE _PDCLIB_ENOTRECOVERABLE
/* Not a socket */
#define ENOTSOCK _PDCLIB_ENOTSOCK
/* Not supported */
#define ENOTSUP _PDCLIB_ENOTSUP
/* Inappropriate I/O control operation */
#define ENOTTY _PDCLIB_ENOTTY
/* No such device or address */
#define ENXIO _PDCLIB_ENXIO
/* Operation not supported on socket */
#define EOPNOTSUPP _PDCLIB_EOPNOTSUPP
/* Value too large to be stored in data type */
#define EOVERFLOW _PDCLIB_EOVERFLOW
/* Previous owner died */
#define EOWNERDEAD _PDCLIB_EOWNERDEAD
/* Operation not permitted */
#define EPERM _PDCLIB_EPERM
/* Broken pipe */
#define EPIPE _PDCLIB_EPIPE
/* Protocol error */
#define EPROTO _PDCLIB_EPROTO
/* Protocol not supported */
#define EPROTONOSUPPORT _PDCLIB_EPROTONOSUPPORT
/* Protocol wrong type for socket */
#define EPROTOTYPE _PDCLIB_EPROTOTYPE
/* Read-only file system */
#define EROFS _PDCLIB_EROFS
/* Invalid seek */
#define ESPIPE _PDCLIB_ESPIPE
/* No such process */
#define ESRCH _PDCLIB_ESRCH
/* Stream ioctl() timeout */
#define ETIME _PDCLIB_ETIME
/* Connection timed out */
#define ETIMEDOUT _PDCLIB_ETIMEDOUT
/* Text file busy */
#define ETXTBSY _PDCLIB_ETXTBSY
/* Operation would block */
#define EWOULDBLOCK _PDCLIB_EWOULDBLOCK
/* Cross-device link */
#define EXDEV _PDCLIB_EXDEV
/* Annex K -- Bounds-checking interfaces */
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0
#ifndef _PDCLIB_ERRNO_T_DEFINED
#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED
typedef int errno_t;
#endif
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_ERRNO_H
#include _PDCLIB_EXTEND_ERRNO_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,153 @@
/* Characteristics of floating types <float.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_FLOAT_H
#define _PDCLIB_FLOAT_H _PDCLIB_FLOAT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_internal.h"
/* The following parameters are used to define the model for each
floating-point type:
s sign (±1)
b base or radix of exponent representation (an integer > 1)
e exponent (an integer between a minimum eₘₙ and a maximum eₘₓ)
p precision (the number of base-b digits in the significand)
ƒₖ nonnegative integers less than b (the significand digits)
A floating-point number (x) is defined by the following model:
x = sbᵉ ₖ₌₁∑ᵖ ƒₖb⁻ᵏ, eₘₙ ≤ e ≤ eₘₓ
In addition to normalized floating-point numbers (ƒ₁ > 0 if x ≠ 0),
floating types may be able to contain other kinds of floating-point
numbers, such as subnormal floating-point numbers (x ≠ 0, e = eₘₙ,
ƒ₁ = 0) and unnormalized floating-point numbers (x ≠ 0, e > eₘₙ,
ƒ₁ = 0), and values that are not floating-point numbers, such as
infinities and NaNs.
*/
/* Whether rounding toward zero (0), to nearest (1), toward positive
infinity (2), toward negative infinity (3), or indeterminate (-1).
FLT_ROUNDS is not a compile-time constant, and may change due to
calls to fesetround() (in <fenv.h>).
*/
#define FLT_ROUNDS _PDCLIB_FLT_ROUNDS
/* Whether operations are done in the given type (0), float is
evaluated as double (1), float and double are evaluated as
long double (2), or evaluation method is indeterminate (-1).
*/
#define FLT_EVAL_METHOD _PDCLIB_FLT_EVAL_METHOD
/* Whether the type supports subnormal numbers (1), does not support
them (0), or support is indeterminate (-1).
*/
#define FLT_HAS_SUBNORM _PDCLIB_FLT_HAS_SUBNORM
#define DBL_HAS_SUBNORM _PDCLIB_DBL_HAS_SUBNORM
#define LDBL_HAS_SUBNORM _PDCLIB_LDBL_HAS_SUBNORM
/* Radix of exponent representation, b */
#define FLT_RADIX _PDCLIB_FLT_RADIX
/* Number of base-b digits in the floating point significand, p */
#define FLT_MANT_DIG _PDCLIB_FLT_MANT_DIG
#define DBL_MANT_DIG _PDCLIB_DBL_MANT_DIG
#define LDBL_MANT_DIG _PDCLIB_LDBL_MANT_DIG
/* Number of decimal digits, n, so that any floating point number with
p radix b digits can be rounded to a floating point number with n
decimal digits and back without changing the value
pₘₓlog₁₀b if b is a power of 10,
⌈1 + pₘₓlog₁₀b⌉ otherwise.
*/
#define FLT_DECIMAL_DIG _PDCLIB_FLT_DECIMAL_DIG
#define DBL_DECIMAL_DIG _PDCLIB_DBL_DECIMAL_DIG
#define LDBL_DECIMAL_DIG _PDCLIB_LDBL_DECIMAL_DIG
/* As above, for the widest supported type. */
#define DECIMAL_DIG _PDCLIB_DECIMAL_DIG
/* Number of decimal digits, q, so that any floating point number with
q decimal digits can be rounded to a floating point number with p
radix b digits and back without changing the value of the q decimal
digits.
p log₁₀b if b is a power of 10,
⌊(p - 1)log₁₀b⌋ otherwise.
*/
#define FLT_DIG _PDCLIB_FLT_DIG
#define DBL_DIG _PDCLIB_DBL_DIG
#define LDBL_DIG _PDCLIB_LDBL_DIG
/* Minimum negative integer such that FLT_RADIX raised to one less
than that power is a normalized floating point number, eₘₙ
*/
#define FLT_MIN_EXP _PDCLIB_FLT_MIN_EXP
#define DBL_MIN_EXP _PDCLIB_DBL_MIN_EXP
#define LDBL_MIN_EXP _PDCLIB_LDBL_MIN_EXP
/* Minimum negative integer such that 10 raised to one less than that
power is in the range of normalized floating point numbers,
⌈log₁₀b^{eₘₙ⁻¹}⌉
*/
#define FLT_MIN_10_EXP _PDCLIB_FLT_MIN_10_EXP
#define DBL_MIN_10_EXP _PDCLIB_DBL_MIN_10_EXP
#define LDBL_MIN_10_EXP _PDCLIB_LDBL_MIN_10_EXP
/* Maximum integer such that FLT_RADIX raised to one less than that
power is a representable finite floating point number, eₘₓ
*/
#define FLT_MAX_EXP _PDCLIB_FLT_MAX_EXP
#define DBL_MAX_EXP _PDCLIB_DBL_MAX_EXP
#define LDBL_MAX_EXP _PDCLIB_LDBL_MAX_EXP
/* Maximum integer such that 10 raised to that power is in the range
of representable finite floating-point numbers,
⌊log₁₀((1-b⁻ᵖ)b^{eₘₓ})⌋
*/
#define FLT_MAX_10_EXP _PDCLIB_FLT_MAX_10_EXP
#define DBL_MAX_10_EXP _PDCLIB_DBL_MAX_10_EXP
#define LDBL_MAX_10_EXP _PDCLIB_LDBL_MAX_10_EXP
/* Maximum representable finite floating-point number, (1-b⁻ᵖ)b^{eₘₓ}
*/
#define FLT_MAX _PDCLIB_FLT_MAX
#define DBL_MAX _PDCLIB_DBL_MAX
#define LDBL_MAX _PDCLIB_LDBL_MAX
/* Difference between 1 and the least value greater than 1 that is
representable in the type, b¹⁻ᵖ
*/
#define FLT_EPSILON _PDCLIB_FLT_EPSILON
#define DBL_EPSILON _PDCLIB_DBL_EPSILON
#define LDBL_EPSILON _PDCLIB_LDBL_EPSILON
/* Minimum normalized positive floating-point number, b^{eₘₙ⁻¹} */
#define FLT_MIN _PDCLIB_FLT_MIN
#define DBL_MIN _PDCLIB_DBL_MIN
#define LDBL_MIN _PDCLIB_LDBL_MIN
/* Minimum positive floating-point number */
#define FLT_TRUE_MIN _PDCLIB_FLT_TRUE_MIN
#define DBL_TRUE_MIN _PDCLIB_DBL_TRUE_MIN
#define LDBL_TRUE_MIN _PDCLIB_LDBL_TRUE_MIN
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_FLOAT_H
#include _PDCLIB_EXTEND_FLOAT_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,368 @@
/* Format conversion of integer types <inttypes.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_INTTYPES_H
#define _PDCLIB_INTTYPES_H _PDCLIB_INTTYPES_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
typedef struct _PDCLIB_imaxdiv_t imaxdiv_t;
/* 7.8.1 Macros for format specifiers */
/* The various leastN_t, fastN_t, intmax_t, and intptr_t types are typedefs
to native types. But the user does not know which ones, which gives some
problems when trying to *printf() / *scanf() those types. The various
macros defined below allow to give the correct conversion specifiers
without knowing the actual native type they represent.
*/
#if _PDCLIB_INT_LEAST8_MAX > _PDCLIB_INT_MAX
#define PRIdLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) )
#define PRIiLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) )
#define PRIoLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) )
#define PRIuLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) )
#define PRIxLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) )
#define PRIXLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, X ) )
#else
#define PRIdLEAST8 "d"
#define PRIiLEAST8 "i"
#define PRIoLEAST8 "o"
#define PRIuLEAST8 "u"
#define PRIxLEAST8 "x"
#define PRIXLEAST8 "X"
#endif
#if _PDCLIB_INT_FAST8_MAX > _PDCLIB_INT_MAX
#define PRIdFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, d ) )
#define PRIiFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, i ) )
#define PRIoFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, o ) )
#define PRIuFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, u ) )
#define PRIxFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, x ) )
#define PRIXFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, X ) )
#else
#define PRIdFAST8 "d"
#define PRIiFAST8 "i"
#define PRIoFAST8 "o"
#define PRIuFAST8 "u"
#define PRIxFAST8 "x"
#define PRIXFAST8 "X"
#endif
#if _PDCLIB_INT_LEAST16_MAX > _PDCLIB_INT_MAX
#define PRIdLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) )
#define PRIiLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) )
#define PRIoLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) )
#define PRIuLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) )
#define PRIxLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) )
#define PRIXLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, X ) )
#else
#define PRIdLEAST16 "d"
#define PRIiLEAST16 "i"
#define PRIoLEAST16 "o"
#define PRIuLEAST16 "u"
#define PRIxLEAST16 "x"
#define PRIXLEAST16 "X"
#endif
#if _PDCLIB_INT_FAST16_MAX > _PDCLIB_INT_MAX
#define PRIdFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, d ) )
#define PRIiFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, i ) )
#define PRIoFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, o ) )
#define PRIuFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, u ) )
#define PRIxFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, x ) )
#define PRIXFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, X ) )
#else
#define PRIdFAST16 "d"
#define PRIiFAST16 "i"
#define PRIoFAST16 "o"
#define PRIuFAST16 "u"
#define PRIxFAST16 "x"
#define PRIXFAST16 "X"
#endif
#if _PDCLIB_INT_LEAST32_MAX > _PDCLIB_INT_MAX
#define PRIdLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) )
#define PRIiLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) )
#define PRIoLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) )
#define PRIuLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) )
#define PRIxLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) )
#define PRIXLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, X ) )
#else
#define PRIdLEAST32 "d"
#define PRIiLEAST32 "i"
#define PRIoLEAST32 "o"
#define PRIuLEAST32 "u"
#define PRIxLEAST32 "x"
#define PRIXLEAST32 "X"
#endif
#if _PDCLIB_INT_FAST32_MAX > _PDCLIB_INT_MAX
#define PRIdFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, d ) )
#define PRIiFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, i ) )
#define PRIoFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, o ) )
#define PRIuFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, u ) )
#define PRIxFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, x ) )
#define PRIXFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, X ) )
#else
#define PRIdFAST32 "d"
#define PRIiFAST32 "i"
#define PRIoFAST32 "o"
#define PRIuFAST32 "u"
#define PRIxFAST32 "x"
#define PRIXFAST32 "X"
#endif
#if _PDCLIB_INT_LEAST64_MAX > _PDCLIB_INT_MAX
#define PRIdLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) )
#define PRIiLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) )
#define PRIoLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) )
#define PRIuLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) )
#define PRIxLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) )
#define PRIXLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, X ) )
#else
#define PRIdLEAST64 "d"
#define PRIiLEAST64 "i"
#define PRIoLEAST64 "o"
#define PRIuLEAST64 "u"
#define PRIxLEAST64 "x"
#define PRIXLEAST64 "X"
#endif
#if _PDCLIB_INT_FAST64_MAX > _PDCLIB_INT_MAX
#define PRIdFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, d ) )
#define PRIiFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, i ) )
#define PRIoFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, o ) )
#define PRIuFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, u ) )
#define PRIxFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, x ) )
#define PRIXFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, X ) )
#else
#define PRIdFAST64 "d"
#define PRIiFAST64 "i"
#define PRIoFAST64 "o"
#define PRIuFAST64 "u"
#define PRIxFAST64 "x"
#define PRIXFAST64 "X"
#endif
#if _PDCLIB_INTMAX_MAX > _PDCLIB_INT_MAX
#define PRIdMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, d ) )
#define PRIiMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, i ) )
#define PRIoMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, o ) )
#define PRIuMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, u ) )
#define PRIxMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, x ) )
#define PRIXMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, X ) )
#else
#define PRIdMAX "d"
#define PRIiMAX "i"
#define PRIoMAX "o"
#define PRIuMAX "u"
#define PRIxMAX "x"
#define PRIXMAX "X"
#endif
#if _PDCLIB_INTPTR_MAX > _PDCLIB_INT_MAX
#define PRIdPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, d ) )
#define PRIiPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, i ) )
#define PRIoPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, o ) )
#define PRIuPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, u ) )
#define PRIxPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, x ) )
#define PRIXPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, X ) )
#else
#define PRIdPTR "d"
#define PRIiPTR "i"
#define PRIoPTR "o"
#define PRIuPTR "u"
#define PRIxPTR "x"
#define PRIXPTR "X"
#endif
#define SCNdLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) )
#define SCNiLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) )
#define SCNoLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) )
#define SCNuLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) )
#define SCNxLEAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) )
#define SCNdFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, d ) )
#define SCNiFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, i ) )
#define SCNoFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, o ) )
#define SCNuFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, u ) )
#define SCNxFAST8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST8_PREFIX, x ) )
#define SCNdLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) )
#define SCNiLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) )
#define SCNoLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) )
#define SCNuLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) )
#define SCNxLEAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) )
#define SCNdFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, d ) )
#define SCNiFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, i ) )
#define SCNoFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, o ) )
#define SCNuFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, u ) )
#define SCNxFAST16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST16_PREFIX, x ) )
#define SCNdLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) )
#define SCNiLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) )
#define SCNoLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) )
#define SCNuLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) )
#define SCNxLEAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) )
#define SCNdFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, d ) )
#define SCNiFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, i ) )
#define SCNoFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, o ) )
#define SCNuFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, u ) )
#define SCNxFAST32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST32_PREFIX, x ) )
#define SCNdLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) )
#define SCNiLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) )
#define SCNoLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) )
#define SCNuLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) )
#define SCNxLEAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) )
#define SCNdFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, d ) )
#define SCNiFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, i ) )
#define SCNoFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, o ) )
#define SCNuFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, u ) )
#define SCNxFAST64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_FAST64_PREFIX, x ) )
#define SCNdMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, d ) )
#define SCNiMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, i ) )
#define SCNoMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, o ) )
#define SCNuMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, u ) )
#define SCNxMAX _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTMAX_PREFIX, x ) )
#define SCNdPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, d ) )
#define SCNiPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, i ) )
#define SCNoPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, o ) )
#define SCNuPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, u ) )
#define SCNxPTR _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INTPTR_PREFIX, x ) )
/* The exact-width types (int8_t, int16_t, ...) are *optional*, as not all
architectures support the necessary 8-bits-per-byte two's complement
native types.
*/
#if _PDCLIB_TWOS_COMPLEMENT == 1
#if _PDCLIB_INT_LEAST8_MAX == 0x7f
#if _PDCLIB_INT_LEAST8_MAX > _PDCLIB_INT_MAX
#define PRId8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) )
#define PRIi8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) )
#define PRIo8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) )
#define PRIu8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) )
#define PRIx8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) )
#define PRIX8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, X ) )
#endif
#define SCNd8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, d ) )
#define SCNi8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, i ) )
#define SCNo8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, o ) )
#define SCNu8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, u ) )
#define SCNx8 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST8_PREFIX, x ) )
#endif
#if _PDCLIB_INT_LEAST16_MAX == 0x7fff
#if _PDCLIB_INT_LEAST16_MAX > _PDCLIB_INT_MAX
#define PRId16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) )
#define PRIi16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) )
#define PRIo16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) )
#define PRIu16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) )
#define PRIx16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) )
#define PRIX16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, X ) )
#endif
#define SCNd16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, d ) )
#define SCNi16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, i ) )
#define SCNo16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, o ) )
#define SCNu16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, u ) )
#define SCNx16 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST16_PREFIX, x ) )
#endif
#if _PDCLIB_INT_LEAST32_MAX == 0x7fffffffl
#if _PDCLIB_INT_LEAST32_MAX > _PDCLIB_INT_MAX
#define PRId32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) )
#define PRIi32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) )
#define PRIo32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) )
#define PRIu32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) )
#define PRIx32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) )
#define PRIX32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, X ) )
#endif
#define SCNd32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, d ) )
#define SCNi32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, i ) )
#define SCNo32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, o ) )
#define SCNu32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, u ) )
#define SCNx32 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST32_PREFIX, x ) )
#endif
#if _PDCLIB_INT_LEAST64_MAX == 0x7fffffffffffffffll
#if _PDCLIB_INT_LEAST64_MAX > _PDCLIB_INT_MAX
#define PRId64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) )
#define PRIi64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) )
#define PRIo64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) )
#define PRIu64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) )
#define PRIx64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) )
#define PRIX64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, X ) )
#endif
#define SCNd64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, d ) )
#define SCNi64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, i ) )
#define SCNo64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, o ) )
#define SCNu64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, u ) )
#define SCNx64 _PDCLIB_value2string( _PDCLIB_concat( _PDCLIB_INT_LEAST64_PREFIX, x ) )
#endif
#endif
/* 7.8.2 Functions for greatest-width integer types */
/* Calculate the absolute value of j */
_PDCLIB_PUBLIC intmax_t imaxabs( intmax_t j );
/* Return quotient (quot) and remainder (rem) of an integer division in the
imaxdiv_t struct.
*/
_PDCLIB_PUBLIC imaxdiv_t imaxdiv( intmax_t numer, intmax_t denom );
/* Separate the character array nptr into three parts: A (possibly empty)
sequence of whitespace characters, a character representation of an integer
to the given base, and trailing invalid characters (including the terminating
null character). If base is 0, assume it to be 10, unless the integer
representation starts with 0x / 0X (setting base to 16) or 0 (setting base to
8). If given, base can be anything from 0 to 36, using the 26 letters of the
base alphabet (both lowercase and uppercase) as digits 10 through 35.
The integer representation is then converted into the return type of the
function. It can start with a '+' or '-' sign. If the sign is '-', the result
of the conversion is negated.
If the conversion is successful, the converted value is returned. If endptr
is not a NULL pointer, a pointer to the first trailing invalid character is
returned in *endptr.
If no conversion could be performed, zero is returned (and nptr in *endptr,
if endptr is not a NULL pointer). If the converted value does not fit into
the return type, the functions return INTMAX_MIN, INTMAX_MAX, or UINTMAX_MAX,
respectively, depending on the sign of the integer representation and the
return type, and errno is set to ERANGE.
*/
/* This function is equivalent to strtol() / strtoul() in <stdlib.h>, but on
the potentially larger type.
*/
_PDCLIB_PUBLIC intmax_t strtoimax( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base );
_PDCLIB_PUBLIC uintmax_t strtoumax( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base );
/* TODO: wcstoimax(), wcstoumax() */
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_INTTYPES_H
#include _PDCLIB_EXTEND_INTTYPES_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,31 @@
/* Alternative spellings <iso646.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_ISO646_H
#define _PDCLIB_ISO646_H _PDCLIB_ISO646_H
#ifndef __cplusplus
#define and &&
#define and_eq &=
#define bitand &
#define bitor |
#define compl ~
#define not !
#define not_eq !=
#define or ||
#define or_eq |=
#define xor ^
#define xor_eq ^=
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_ISO646_H
#include _PDCLIB_EXTEND_ISO646_H
#endif
#endif

View File

@ -0,0 +1,50 @@
/* Sizes of integer types <limits.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_LIMITS_H
#define _PDCLIB_LIMITS_H _PDCLIB_LIMITS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_internal.h"
/* TODO: Defined to 1 as multibyte characters are not supported yet. */
#define MB_LEN_MAX 1
#define LLONG_MIN _PDCLIB_LLONG_MIN
#define LLONG_MAX _PDCLIB_LLONG_MAX
#define ULLONG_MAX _PDCLIB_ULLONG_MAX
#define CHAR_BIT _PDCLIB_CHAR_BIT
#define CHAR_MAX _PDCLIB_CHAR_MAX
#define CHAR_MIN _PDCLIB_CHAR_MIN
#define SCHAR_MAX _PDCLIB_SCHAR_MAX
#define SCHAR_MIN _PDCLIB_SCHAR_MIN
#define UCHAR_MAX _PDCLIB_UCHAR_MAX
#define SHRT_MAX _PDCLIB_SHRT_MAX
#define SHRT_MIN _PDCLIB_SHRT_MIN
#define INT_MAX _PDCLIB_INT_MAX
#define INT_MIN _PDCLIB_INT_MIN
#define LONG_MAX _PDCLIB_LONG_MAX
#define LONG_MIN _PDCLIB_LONG_MIN
#define USHRT_MAX _PDCLIB_USHRT_MAX
#define UINT_MAX _PDCLIB_UINT_MAX
#define ULONG_MAX _PDCLIB_ULONG_MAX
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_LIMITS_H
#include _PDCLIB_EXTEND_LIMITS_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,114 @@
/* Localization <locale.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_LOCALE_H
#define _PDCLIB_LOCALE_H _PDCLIB_LOCALE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_internal.h"
#ifndef _PDCLIB_NULL_DEFINED
#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED
#define NULL _PDCLIB_NULL
#endif
/* The structure returned by localeconv().
The values for *_sep_by_space:
0 - no space
1 - if symbol and sign are adjacent, a space separates them from the value;
otherwise a space separates the symbol from the value
2 - if symbol and sign are adjacent, a space separates them; otherwise a
space separates the sign from the value
The values for *_sign_posn:
0 - Parentheses surround value and symbol
1 - sign precedes value and symbol
2 - sign succeeds value and symbol
3 - sign immediately precedes symbol
4 - sign immediately succeeds symbol
*/
struct lconv
{
char * decimal_point; /* decimal point character */ /* LC_NUMERIC */
char * thousands_sep; /* character for separating groups of digits */ /* LC_NUMERIC */
char * grouping; /* string indicating the size of digit groups */ /* LC_NUMERIC */
char * mon_decimal_point; /* decimal point for monetary quantities */ /* LC_MONETARY */
char * mon_thousands_sep; /* thousands_sep for monetary quantities */ /* LC_MONETARY */
char * mon_grouping; /* grouping for monetary quantities */ /* LC_MONETARY */
char * positive_sign; /* string indicating nonnegative mty. qty. */ /* LC_MONETARY */
char * negative_sign; /* string indicating negative mty. qty. */ /* LC_MONETARY */
char * currency_symbol; /* local currency symbol (e.g. '$') */ /* LC_MONETARY */
char * int_curr_symbol; /* international currency symbol (e.g. "USD" */ /* LC_MONETARY */
char frac_digits; /* fractional digits in local monetary qty. */ /* LC_MONETARY */
char p_cs_precedes; /* if currency_symbol precedes positive qty. */ /* LC_MONETARY */
char n_cs_precedes; /* if currency_symbol precedes negative qty. */ /* LC_MONETARY */
char p_sep_by_space; /* if it is separated by space from pos. qty. */ /* LC_MONETARY */
char n_sep_by_space; /* if it is separated by space from neg. qty. */ /* LC_MONETARY */
char p_sign_posn; /* positioning of positive_sign for mon. qty. */ /* LC_MONETARY */
char n_sign_posn; /* positioning of negative_sign for mon. qty. */ /* LC_MONETARY */
char int_frac_digits; /* Same as above, for international format */ /* LC_MONETARY */
char int_p_cs_precedes; /* Same as above, for international format */ /* LC_MONETARY */
char int_n_cs_precedes; /* Same as above, for international format */ /* LC_MONETARY */
char int_p_sep_by_space; /* Same as above, for international format */ /* LC_MONETARY */
char int_n_sep_by_space; /* Same as above, for international format */ /* LC_MONETARY */
char int_p_sign_posn; /* Same as above, for international format */ /* LC_MONETARY */
char int_n_sign_posn; /* Same as above, for international format */ /* LC_MONETARY */
};
/* First arguments to setlocale().
NOTE: If you add to / modify these, look at functions/locale/setlocale.c
and keep things in sync.
*/
/* Entire locale */
#define LC_ALL _PDCLIB_LC_ALL
/* Collation (strcoll(), strxfrm()) */
#define LC_COLLATE _PDCLIB_LC_COLLATE
/* Character types (<ctype.h>, <wctype.h>) */
#define LC_CTYPE _PDCLIB_LC_CTYPE
/* Monetary formatting (as returned by localeconv) */
#define LC_MONETARY _PDCLIB_LC_MONETARY
/* Decimal-point character (for printf() / scanf() functions), string
conversions, nonmonetary formatting as returned by localeconv
*/
#define LC_NUMERIC _PDCLIB_LC_NUMERIC
/* Time formats (strftime(), wcsftime()) */
#define LC_TIME _PDCLIB_LC_TIME
/* Messages (not specified but allowed by C99, and specified by POSIX)
(used by perror() / strerror())
*/
#define LC_MESSAGES _PDCLIB_LC_MESSAGES
/* The category parameter can be any of the LC_* macros to specify if the call
to setlocale() shall affect the entire locale or only a portion thereof.
The category locale specifies which locale should be switched to, with "C"
being the minimal default locale, and "" being the locale-specific native
environment. A NULL pointer makes setlocale() return the *current* setting.
Otherwise, returns a pointer to a string associated with the specified
category for the new locale.
*/
_PDCLIB_PUBLIC char * setlocale( int category, const char * locale );
/* Returns a struct lconv initialized to the values appropriate for the current
locale setting.
*/
_PDCLIB_PUBLIC struct lconv * localeconv( void );
#ifdef __cplusplus
}
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_LOCALE_H
#include _PDCLIB_EXTEND_LOCALE_H
#endif
#endif

View File

@ -0,0 +1,904 @@
/* Internal PDCLib configuration <_PDCLIB_config.h>
("Example" platform target, for PDCLib development)
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_CONFIG_H
#define _PDCLIB_CONFIG_H _PDCLIB_CONFIG_H
/* -------------------------------------------------------------------------- */
/* Misc */
/* -------------------------------------------------------------------------- */
/* Helper macros also documented in _PDCLIB_internal.h, but defined here as */
/* they are needed in this file already. */
/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending. */
/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */
#define _PDCLIB_cc( x, y ) x ## y
#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y )
/* exit() can signal success to the host environment by the value of zero or */
/* the constant EXIT_SUCCESS. Failure is signaled by EXIT_FAILURE. Note that */
/* any other return value is "implementation-defined", i.e. your environment */
/* is not required to handle it gracefully. Set your definitions here. */
#define _PDCLIB_SUCCESS 0
#define _PDCLIB_FAILURE -1
/* qsort() in <stdlib.h> requires a function that swaps two memory areas. */
/* Below is a naive implementation that can be improved significantly for */
/* specific platforms, e.g. by swapping int instead of char. */
#define _PDCLIB_memswp( i, j, size ) \
char tmp; \
do { \
tmp = *i; \
*i++ = *j; \
*j++ = tmp; \
} while ( --size );
/* Define this to some compiler directive that can be written after the */
/* parameter list of a function declaration to indicate the function does */
/* never return. If your compiler does not support such a directive, define */
/* to nothing. (This is to avoid warnings with the exit functions under GCC */
/* when compiling with C99/C++ settings, where C11 _Noreturn is unavailable.) */
#define _PDCLIB_NORETURN __attribute__(( noreturn ))
/* -------------------------------------------------------------------------- */
/* Symbol Visibility */
/* -------------------------------------------------------------------------- */
/* This defines _PDCLIB_PUBLIC to indicate external linkage, and _PDCLIB_LOCAL
to indicate local linkage.
*/
#ifdef _PDCLIB_STATIC_DEFINE
#define _PDCLIB_PUBLIC
#define _PDCLIB_LOCAL
#else
#if defined _WIN32 || defined __CYGWIN__
#ifdef _PDCLIB_BUILD
#ifdef __GNUC__
#define _PDCLIB_PUBLIC __attribute__ ((dllexport))
#else
#define _PDCLIB_PUBLIC __declspec(dllexport)
#endif
#else
#ifdef __GNUC__
#define _PDCLIB_PUBLIC __attribute__ ((dllimport))
#else
#define _PDCLIB_PUBLIC __declspec(dllimport)
#endif
#endif
#define _PDCLIB_LOCAL
#else
#if __GNUC__ >= 4
#define _PDCLIB_PUBLIC __attribute__ ((visibility ("default")))
#define _PDCLIB_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define _PDCLIB_PUBLIC
#define _PDCLIB_LOCAL
#endif
#endif
#endif
/* -------------------------------------------------------------------------- */
/* Integers */
/* -------------------------------------------------------------------------- */
/* The defines below make use of predefines offered by GCC and clang. If you */
/* adapt PDCLib for a different compiler family, you will have to use what */
/* that compiler provides, or enter actual values. */
/* -------------------------------------------------------------------------- */
/* At the point of writing, PDCLib makes no provisions for, nor has it been */
/* tested, on a platform that uses signed magnitude or one's complement to */
/* encode its integers. Most importantly, there are no guarantees that the */
/* negative zero of those encodings is in any form handled gracefully. */
#define _PDCLIB_TWOS_COMPLEMENT 1
/* 1234 for little endian, 4321 for big endian; other types not supported. */
#define _PDCLIB_ENDIANESS __BYTE_ORDER__
/* Calculation of a minimum value from a given maximum for two's complement. */
/* (For convenience only, used only in this header file below.) */
#define _PDCLIB_MIN_CALC( max ) ( ( - max ) - 1 )
/* Now, introducting the various predefines to the _PDCLIB_* namespace, so */
/* the rest of PDCLib can work with that and adapting to a different compiler */
/* will require changes only in this one file. */
/* Bits in a char */
#define _PDCLIB_CHAR_BIT __CHAR_BIT__
/* Maximum and minimum values of signed / unsigned char */
#define _PDCLIB_SCHAR_MAX __SCHAR_MAX__
#define _PDCLIB_SCHAR_MIN _PDCLIB_MIN_CALC( __SCHAR_MAX__ )
#define _PDCLIB_UCHAR_MAX ( __SCHAR_MAX__ * 2 + 1 )
/* Whether the 'char' type is unsigned */
#ifdef __CHAR_UNSIGNED__
#define _PDCLIB_CHAR_MAX _PDCLIB_UCHAR_MAX
#define _PDCLIB_CHAR_MIN 0
#else
#define _PDCLIB_CHAR_MAX _PDCLIB_SCHAR_MAX
#define _PDCLIB_CHAR_MIN _PDCLIB_SCHAR_MIN
#endif
/* Maximum and minimum values of signed / unsigned short */
#define _PDCLIB_SHRT_MAX __SHRT_MAX__
#define _PDCLIB_SHRT_MIN _PDCLIB_MIN_CALC( __SHRT_MAX__ )
#define _PDCLIB_USHRT_MAX ( __SHRT_MAX__ * 2u + 1 )
/* Maximum and minimum values of signed / unsigned int */
#define _PDCLIB_INT_MAX __INT_MAX__
#define _PDCLIB_INT_MIN _PDCLIB_MIN_CALC( __INT_MAX__ )
#define _PDCLIB_UINT_MAX ( __INT_MAX__ * 2u + 1 )
/* Maximum and minimum values of signed / unsigned long */
#define _PDCLIB_LONG_MAX __LONG_MAX__
#define _PDCLIB_LONG_MIN _PDCLIB_MIN_CALC( __LONG_MAX__ )
#define _PDCLIB_ULONG_MAX ( __LONG_MAX__ * 2ul + 1 )
/* Maximum and minimum values of signed / unsigned long long */
#define _PDCLIB_LLONG_MAX __LONG_LONG_MAX__
#define _PDCLIB_LLONG_MIN _PDCLIB_MIN_CALC( __LONG_LONG_MAX__ )
#define _PDCLIB_ULLONG_MAX ( __LONG_LONG_MAX__ * 2ull + 1 )
/* -------------------------------------------------------------------------- */
/* <stdint.h> defines a set of integer types that are of a minimum width, and */
/* "usually fastest" on the system. (If, for example, accessing a single char */
/* requires the CPU to access a complete int and then mask out the char, the */
/* "usually fastest" type of at least 8 bits would be int, not char.) */
/* If you do not have information on the relative performance of the types, */
/* the standard allows you to define any type that meets minimum width and */
/* signedness requirements. */
/* The first define is the appropriate basic type (e.g. "long int"), second */
/* its max value, the third its min value (both expressed in the given type). */
/* The same follows for the unsigned type (for which the minimum value is */
/* obviously zero and need not be defined). */
/* There *are* predefines provided for the printf()/scanf() length specifiers */
/* but tunneling them through here would have added many lines of repetitive */
/* and mostly redundant defines. They are determined in <_PDCLIB_internal.h>. */
/* -------------------------------------------------------------------------- */
/* int_fast8_t / uint_fast8_t */
#define _PDCLIB_int_fast8_t __INT_FAST8_TYPE__
#define _PDCLIB_INT_FAST8_MAX __INT_FAST8_MAX__
#define _PDCLIB_INT_FAST8_MIN _PDCLIB_MIN_CALC( __INT_FAST8_MAX__ )
#define _PDCLIB_uint_fast8_t __UINT_FAST8_TYPE__
#define _PDCLIB_UINT_FAST8_MAX __UINT_FAST8_MAX__
/* int_least8_t / uint_least8_t */
#define _PDCLIB_int_least8_t __INT_LEAST8_TYPE__
#define _PDCLIB_INT_LEAST8_MAX __INT_LEAST8_MAX__
#define _PDCLIB_INT_LEAST8_MIN _PDCLIB_MIN_CALC( __INT_LEAST8_MAX__ )
#define _PDCLIB_uint_least8_t __UINT_LEAST8_TYPE__
#define _PDCLIB_UINT_LEAST8_MAX __UINT_LEAST8_MAX__
/* int_fast16_t / uint_fast16_t */
#define _PDCLIB_int_fast16_t __INT_FAST16_TYPE__
#define _PDCLIB_INT_FAST16_MAX __INT_FAST16_MAX__
#define _PDCLIB_INT_FAST16_MIN _PDCLIB_MIN_CALC( __INT_FAST16_MAX__ )
#define _PDCLIB_uint_fast16_t __UINT_FAST16_TYPE__
#define _PDCLIB_UINT_FAST16_MAX __UINT_FAST16_MAX__
/* int_least16_t / uint_least16_t */
#define _PDCLIB_int_least16_t __INT_LEAST16_TYPE__
#define _PDCLIB_INT_LEAST16_MAX __INT_LEAST16_MAX__
#define _PDCLIB_INT_LEAST16_MIN _PDCLIB_MIN_CALC( __INT_LEAST16_MAX__ )
#define _PDCLIB_uint_least16_t __UINT_LEAST16_TYPE__
#define _PDCLIB_UINT_LEAST16_MAX __UINT_LEAST16_MAX__
/* int_fast32_t / uint_fast32_t */
#define _PDCLIB_int_fast32_t __INT_FAST32_TYPE__
#define _PDCLIB_INT_FAST32_MAX __INT_FAST32_MAX__
#define _PDCLIB_INT_FAST32_MIN _PDCLIB_MIN_CALC( __INT_FAST32_MAX__ )
#define _PDCLIB_uint_fast32_t __UINT_FAST32_TYPE__
#define _PDCLIB_UINT_FAST32_MAX __UINT_FAST32_MAX__
/* int_least32_t / uint_least32_t */
#define _PDCLIB_int_least32_t __INT_LEAST32_TYPE__
#define _PDCLIB_INT_LEAST32_MAX __INT_LEAST32_MAX__
#define _PDCLIB_INT_LEAST32_MIN _PDCLIB_MIN_CALC( __INT_LEAST32_MAX__ )
#define _PDCLIB_uint_least32_t __UINT_LEAST32_TYPE__
#define _PDCLIB_UINT_LEAST32_MAX __UINT_LEAST32_MAX__
/* int_fast64_t / uint_fast64_t */
#define _PDCLIB_int_fast64_t __INT_FAST64_TYPE__
#define _PDCLIB_INT_FAST64_MAX __INT_FAST64_MAX__
#define _PDCLIB_INT_FAST64_MIN _PDCLIB_MIN_CALC( __INT_FAST64_MAX__ )
#define _PDCLIB_uint_fast64_t __UINT_FAST64_TYPE__
#define _PDCLIB_UINT_FAST64_MAX __UINT_FAST64_MAX__
/* int_least64_t / uint_least64_t */
#define _PDCLIB_int_least64_t __INT_LEAST64_TYPE__
#define _PDCLIB_INT_LEAST64_MAX __INT_LEAST64_MAX__
#define _PDCLIB_INT_LEAST64_MIN _PDCLIB_MIN_CALC( __INT_LEAST64_MAX__ )
#define _PDCLIB_uint_least64_t __UINT_LEAST64_TYPE__
#define _PDCLIB_UINT_LEAST64_MAX __UINT_LEAST64_MAX__
/* Exact-width integer types. These are *optional*. If your platform does not */
/* support types of these exact widths in two's complement encoding, just */
/* leave them undefined. */
#define _PDCLIB_int8_t __INT8_TYPE__
#define _PDCLIB_int16_t __INT16_TYPE__
#define _PDCLIB_int32_t __INT32_TYPE__
#define _PDCLIB_int64_t __INT64_TYPE__
#define _PDCLIB_uint8_t __UINT8_TYPE__
#define _PDCLIB_uint16_t __UINT16_TYPE__
#define _PDCLIB_uint32_t __UINT32_TYPE__
#define _PDCLIB_uint64_t __UINT64_TYPE__
/* INTn_C / UINTn_C macros to define int_leastN_t / uint_leastN_t literals. */
#if defined( __INT8_C )
/* GCC */
#define _PDCLIB_INT_LEAST8_C __INT8_C
#define _PDCLIB_UINT_LEAST8_C __UINT8_C
#define _PDCLIB_INT_LEAST16_C __INT16_C
#define _PDCLIB_UINT_LEAST16_C __UINT16_C
#define _PDCLIB_INT_LEAST32_C __INT32_C
#define _PDCLIB_UINT_LEAST32_C __UINT32_C
#define _PDCLIB_INT_LEAST64_C __INT64_C
#define _PDCLIB_UINT_LEAST64_C __UINT64_C
#elif defined( __INT8_C_SUFFIX__ )
/* Clang */
#define _PDCLIB_INT_LEAST8_C(c) _PDCLIB_concat( c, __INT8_C_SUFFIX__ )
#define _PDCLIB_UINT_LEAST8_C(c) _PDCLIB_concat( c, __UINT8_C_SUFFIX__ )
#define _PDCLIB_INT_LEAST16_C(c) _PDCLIB_concat( c, __INT16_C_SUFFIX__ )
#define _PDCLIB_UINT_LEAST16_C(c) _PDCLIB_concat( c, __UINT16_C_SUFFIX__ )
#define _PDCLIB_INT_LEAST32_C(c) _PDCLIB_concat( c, __INT32_C_SUFFIX__ )
#define _PDCLIB_UINT_LEAST32_C(c) _PDCLIB_concat( c, __UINT32_C_SUFFIX__ )
#define _PDCLIB_INT_LEAST64_C(c) _PDCLIB_concat( c, __INT64_C_SUFFIX__ )
#define _PDCLIB_UINT_LEAST64_C(c) _PDCLIB_concat( c, __UINT64_C_SUFFIX__ )
#else
#error Please create your own _PDCLIB_config.h. Using the existing one as-is will not work. (Unsupported *INTn_C macros.)
#endif
/* <stdlib.h> defines the div() function family that allows taking quotient */
/* and remainder of an integer division in one operation. Many platforms */
/* support this in hardware / opcode, and the standard permits ordering of */
/* the return structure in any way to fit the hardware. That is why those */
/* structs can be configured here. */
struct _PDCLIB_div_t
{
int quot;
int rem;
};
struct _PDCLIB_ldiv_t
{
long int quot;
long int rem;
};
struct _PDCLIB_lldiv_t
{
long long int quot;
long long int rem;
};
/* -------------------------------------------------------------------------- */
/* What follows are a couple of "special" typedefs and their limits. */
/* -------------------------------------------------------------------------- */
/* The result type of substracting two pointers */
#define _PDCLIB_ptrdiff_t __PTRDIFF_TYPE__
#define _PDCLIB_PTRDIFF_MAX __PTRDIFF_MAX__
#define _PDCLIB_PTRDIFF_MIN _PDCLIB_MIN_CALC( __PTRDIFF_MAX__ )
/* An integer type that can be accessed as atomic entity (think asynchronous */
/* interrupts). In a freestanding environment, the type itself need not be */
/* defined, but its limits must. (Don't ask.) GCC is so kind to predefine it, */
/* but clang is only giving us its MAX value, so we use that to identify the */
/* type in _PDCLIB_int.h if the type definition is unavailable. */
#ifdef __SIG_ATOMIC_TYPE__
#define _PDCLIB_sig_atomic_t __SIG_ATOMIC_TYPE__
#endif
#define _PDCLIB_SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
#define _PDCLIB_SIG_ATOMIC_MIN _PDCLIB_MIN_CALC( __SIG_ATOMIC_MAX__ )
/* Result type of the 'sizeof' operator (must be unsigned). */
/* Note: In <stdint.h>, this is taken as the base for RSIZE_MAX, the limit */
/* for the bounds-checking interfaces of Annex K. The recommendation by the */
/* standard is to use ( SIZE_MAX >> 1 ) when "targeting machines with large */
/* addess spaces", whereas small address spaces should use SIZE_MAX directly. */
#define _PDCLIB_size_t __SIZE_TYPE__
#define _PDCLIB_SIZE_MAX __SIZE_MAX__
/* Large enough an integer to hold all character codes of the widest */
/* supported locale. */
#define _PDCLIB_wchar_t __WCHAR_TYPE__
#define _PDCLIB_WCHAR_MAX __WCHAR_MAX__
#define _PDCLIB_WCHAR_MIN __WCHAR_MIN__
/* Large enough an integer to hold all character codes of the widest */
/* supported locale plus WEOF (which needs not to be equal to EOF, nor needs */
/* to be of negative value). */
#define _PDCLIB_wint_t __WINT_TYPE__
#define _PDCLIB_WINT_MAX __WINT_MAX__
#define _PDCLIB_WINT_MIN __WINT_MIN__
/* Integer types capable of taking the (cast) value of a void *, and having */
/* the value cast back to void *, comparing equal to the original. */
#define _PDCLIB_intptr_t __INTPTR_TYPE__
#define _PDCLIB_INTPTR_MAX __INTPTR_MAX__
#define _PDCLIB_INTPTR_MIN _PDCLIB_MIN_CALC( __INTPTR_MAX__ )
#define _PDCLIB_uintptr_t __UINTPTR_TYPE__
#define _PDCLIB_UINTPTR_MAX __UINTPTR_MAX__
/* Largest supported integer type. Implementation note: see _PDCLIB_atomax(). */
#define _PDCLIB_intmax_t __INTMAX_TYPE__
#define _PDCLIB_INTMAX_MAX __INTMAX_MAX__
#define _PDCLIB_INTMAX_MIN _PDCLIB_MIN_CALC( __INTMAX_MAX__ )
#define _PDCLIB_INTMAX_C __INTMAX_C
#define _PDCLIB_uintmax_t __UINTMAX_TYPE__
#define _PDCLIB_UINTMAX_MAX __UINTMAX_MAX__
#define _PDCLIB_UINTMAX_C __UINTMAX_C
/* <inttypes.h> defines imaxdiv(), which is equivalent to the div() function */
/* family (see further above) with intmax_t as basis. */
struct _PDCLIB_imaxdiv_t
{
_PDCLIB_intmax_t quot;
_PDCLIB_intmax_t rem;
};
/* -------------------------------------------------------------------------- */
/* Time types, limits, constants, and paths */
/* -------------------------------------------------------------------------- */
/* _PDCLIB_time is the type for type_t; _PDCLIB_clock for clock_t. Both types */
/* are defined as "real types capable of representing times". The "range and */
/* precision of times representable" is implementation-defined. */
/* For clock_t, the standard defines that dividing the result of clock() by */
/* CLOCKS_PER_SEC gives the seconds elapsed. */
#ifdef __CYGWIN__
#define _PDCLIB_clock_t unsigned long
#else
#define _PDCLIB_clock_t long
#endif
#define _PDCLIB_CLOCKS_PER_SEC 1000000
/* For time_t, no such divider exists. Most implementations use a count of */
/* seconds since a specified epoch. While PDCLib really should support other */
/* encodings as well, for now "count of seconds" is the only supported one. */
/* MIN / MAX values for time_t are not required by the standard (and they are */
/* not "exported" from the _PDCLIB namespace), but they are useful in support */
/* of the _tzcode implementation. */
#ifdef __MINGW64__
#define _PDCLIB_time_t long long
#define _PDCLIB_TIME_MAX __LONG_LONG_MAX__
#define _PDCLIB_TIME_MIN _PDCLIB_MIN_CALC( __LONG_LONG_MAX__ )
#else
#define _PDCLIB_time_t long
#define _PDCLIB_TIME_MAX __LONG_MAX__
#define _PDCLIB_TIME_MIN _PDCLIB_MIN_CALC( __LONG_MAX__ )
#endif
/* "Unix time" uses 1970-01-01T00:00:00 as "epoch". If your system uses a */
/* different "zero point" for its timestamps, set this to the offset between */
/* your epoch and Unix epoch. (For example, NTP uses 1900-01-01T00:00:00 as */
/* epoch, giving an offset of (70 * 365 + 17) * 86400 = 220898800 seconds.) */
#define _PDCLIB_EPOCH_BIAS INT64_C( 0 )
/* Leave this alone for now. */
#define _PDCLIB_TIME_UTC 1
/* Path to TZ data. */
/* IMPORTANT: *Must* end with separator character! */
/* It does make it much easier for the time data handling code if this detail */
/* can be relied upon and need not be handled in code. */
#define _PDCLIB_TZDIR "/usr/share/zoneinfo/"
/* Path to default (local) timezone */
#define _PDCLIB_TZDEFAULT "/etc/localtime"
/* -------------------------------------------------------------------------- */
/* Floating Point */
/* -------------------------------------------------------------------------- */
/* Whether the implementation rounds toward zero (0), to nearest (1), toward */
/* positive infinity (2), or toward negative infinity (3). (-1) signifies */
/* indeterminable rounding, any other value implementation-specific rounding. */
#define _PDCLIB_FLT_ROUNDS -1
/* Check <float.h> for explanations on each of these values. */
#define _PDCLIB_FLT_EVAL_METHOD __FLT_EVAL_METHOD__
#define _PDCLIB_FLT_HAS_SUBNORM __FLT_HAS_DENORM__
#define _PDCLIB_DBL_HAS_SUBNORM __DBL_HAS_DENORM__
#define _PDCLIB_LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__
#define _PDCLIB_FLT_RADIX __FLT_RADIX__
#define _PDCLIB_FLT_MANT_DIG __FLT_MANT_DIG__
#define _PDCLIB_DBL_MANT_DIG __DBL_MANT_DIG__
#define _PDCLIB_LDBL_MANT_DIG __LDBL_MANT_DIG__
#define _PDCLIB_FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__
#define _PDCLIB_DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__
#define _PDCLIB_LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
#define _PDCLIB_DECIMAL_DIG __DECIMAL_DIG__
#define _PDCLIB_FLT_DIG __FLT_DIG__
#define _PDCLIB_DBL_DIG __DBL_DIG__
#define _PDCLIB_LDBL_DIG __LDBL_DIG__
#define _PDCLIB_FLT_MIN_EXP __FLT_MIN_EXP__
#define _PDCLIB_DBL_MIN_EXP __DBL_MIN_EXP__
#define _PDCLIB_LDBL_MIN_EXP __LDBL_MIN_EXP__
#define _PDCLIB_FLT_MIN_10_EXP __FLT_MIN_10_EXP__
#define _PDCLIB_DBL_MIN_10_EXP __DBL_MIN_10_EXP__
#define _PDCLIB_LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
#define _PDCLIB_FLT_MAX_EXP __FLT_MAX_EXP__
#define _PDCLIB_DBL_MAX_EXP __DBL_MAX_EXP__
#define _PDCLIB_LDBL_MAX_EXP __LDBL_MAX_EXP__
#define _PDCLIB_FLT_MAX_10_EXP __FLT_MAX_10_EXP__
#define _PDCLIB_DBL_MAX_10_EXP __DBL_MAX_10_EXP__
#define _PDCLIB_LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__
#define _PDCLIB_FLT_MAX __FLT_MAX__
#define _PDCLIB_DBL_MAX __DBL_MAX__
#define _PDCLIB_LDBL_MAX __LDBL_MAX__
#define _PDCLIB_FLT_EPSILON __FLT_EPSILON__
#define _PDCLIB_DBL_EPSILON __DBL_EPSILON__
#define _PDCLIB_LDBL_EPSILON __LDBL_EPSILON__
#define _PDCLIB_FLT_MIN __FLT_MIN__
#define _PDCLIB_DBL_MIN __DBL_MIN__
#define _PDCLIB_LDBL_MIN __LDBL_MIN__
#define _PDCLIB_FLT_TRUE_MIN __FLT_DENORM_MIN__
#define _PDCLIB_DBL_TRUE_MIN __DBL_DENORM_MIN__
#define _PDCLIB_LDBL_TRUE_MIN __LDBL_DENORM_MIN__
/* Macros for deconstructing floating point values */
#define _PDCLIB_DBL_SIGN( bytes ) ( ( (unsigned)bytes[7] & 0x80 ) >> 7 )
#define _PDCLIB_DBL_DEC( bytes ) ( ( _PDCLIB_DBL_EXP( bytes ) > 0 ) ? 1 : 0 )
#define _PDCLIB_DBL_EXP( bytes ) ( ( ( (unsigned)bytes[7] & 0x7f ) << 4 ) | ( ( (unsigned)bytes[6] & 0xf0 ) >> 4 ) )
#define _PDCLIB_DBL_BIAS 1023
#define _PDCLIB_DBL_MANT_START( bytes ) ( bytes + 6 )
/* Most platforms today use IEEE 754 single precision for 'float', and double */
/* precision for 'double'. But type 'long double' varies. We use what the */
/* compiler states about LDBL_MANT_DIG to determine the type. */
#if _PDCLIB_LDBL_MANT_DIG == 64
/* Intel "Extended Precision" format, using 80 bits (64bit mantissa) */
#define _PDCLIB_LDBL_SIGN( bytes ) ( ( (unsigned)bytes[9] & 0x80 ) >> 7 )
#define _PDCLIB_LDBL_DEC( bytes ) ( ( (unsigned)bytes[7] & 0x80 ) >> 7 )
#define _PDCLIB_LDBL_EXP( bytes ) ( ( ( (unsigned)bytes[9] & 0x7f ) << 8 ) | (unsigned)bytes[8] )
#define _PDCLIB_LDBL_BIAS 16383
#define _PDCLIB_LDBL_MANT_START( bytes ) ( bytes + 7 )
#elif _PDCLIB_LDBL_MANT_DIG == 113
/* IEEE "Quadruple Precision" format, using 128 bits (113bit mantissa) */
#define _PDCLIB_LDBL_SIGN( bytes ) ( ( (unsigned)bytes[15] & 0x80 ) >> 7 )
#define _PDCLIB_LDBL_DEC( bytes ) ( ( _PDCLIB_LDBL_EXP( bytes ) > 0 ) ? 1 : 0 )
#define _PDCLIB_LDBL_EXP( bytes ) ( ( ( (unsigned)bytes[15] & 0x7f ) << 8 ) | (unsigned)bytes[14] )
#define _PDCLIB_LDBL_BIAS 16383
#define _PDCLIB_LDBL_MANT_START( bytes ) ( bytes + 13 )
#else
/* IEEE "Double Precision" format, using 64 bits (53bit mantissa,
same as DBL above) */
#define _PDCLIB_LDBL_SIGN( bytes ) ( ( (unsigned)bytes[7] & 0x80 ) >> 7 )
#define _PDCLIB_LDBL_DEC( bytes ) ( ( _PDCLIB_LDBL_EXP( bytes ) > 0 ) ? 1 : 0 )
#define _PDCLIB_LDBL_EXP( bytes ) ( ( ( (unsigned)bytes[7] & 0x7f ) << 4 ) | ( ( (unsigned)bytes[6] & 0xf0 ) >> 4 ) )
#define _PDCLIB_LDBL_BIAS 1023
#define _PDCLIB_LDBL_MANT_START( bytes ) ( bytes + 6 )
#endif
/* -------------------------------------------------------------------------- */
/* Big Integer Arithmetic */
/* -------------------------------------------------------------------------- */
/* In support of the floating point converstions required by printf() etc., */
/* PDCLib provides rudimentary big integer arithmetics. The _PDCLIB_bigint_t */
/* type stores values in a sequence of integer "digits", which may be of any */
/* uint_leastN_t type with N being 32 or 16. Note that multiplication and */
/* division require the help of the next larger type. So set the define to */
/* 32 if efficient 64bit integer arithmetics are available on your platform, */
/* and to 16 otherwise. */
/* (The value range of _PDCLIB_bigint_t is not affected by this setting.) */
#define _PDCLIB_BIGINT_DIGIT_BITS 16
/* -------------------------------------------------------------------------- */
/* Platform-dependent macros defined by the standard headers. */
/* -------------------------------------------------------------------------- */
/* The offsetof macro */
/* Contract: Expand to an integer constant expression of type size_t, which */
/* represents the offset in bytes to the structure member from the beginning */
/* of the structure. If the specified member is a bitfield, behaviour is */
/* undefined. */
/* There is no standard-compliant way to do this. */
/* This implementation casts an integer zero to 'pointer to type', and then */
/* takes the address of member. This is undefined behaviour but should work */
/* on most compilers. */
#define _PDCLIB_offsetof( type, member ) ( (size_t) &( ( (type *) 0 )->member ) )
/* Variable Length Parameter List Handling (<stdarg.h>) */
/* The macros defined by <stdarg.h> are highly dependent on the calling */
/* conventions used, and you probably have to replace them with builtins of */
/* your compiler. */
#if defined( __i386 )
/* The following generic implementation works only for pure stack-based */
/* architectures, and only if arguments are aligned to pointer type. Credits */
/* to Michael Moody, who contributed this to the Public Domain. */
/* Internal helper macro. va_round is not part of <stdarg.h>. */
#define _PDCLIB_va_round( type ) ( (sizeof(type) + sizeof(void *) - 1) & ~(sizeof(void *) - 1) )
typedef char * _PDCLIB_va_list;
#define _PDCLIB_va_arg( ap, type ) ( (ap) += (_PDCLIB_va_round(type)), ( *(type*) ( (ap) - (_PDCLIB_va_round(type)) ) ) )
#define _PDCLIB_va_copy( dest, src ) ( (dest) = (src), (void)0 )
#define _PDCLIB_va_end( ap ) ( (ap) = (void *)0, (void)0 )
#define _PDCLIB_va_start( ap, parmN ) ( (ap) = (char *) &parmN + ( _PDCLIB_va_round(parmN) ), (void)0 )
#elif defined( __x86_64 ) || defined( __arm__ ) || defined( __ARM_NEON )
/* No way to cover x86_64 or arm with a generic implementation, as it uses */
/* register-based parameter passing. Using compiler builtins here. */
typedef __builtin_va_list _PDCLIB_va_list;
#define _PDCLIB_va_arg( ap, type ) ( __builtin_va_arg( ap, type ) )
#define _PDCLIB_va_copy( dest, src ) ( __builtin_va_copy( dest, src ) )
#define _PDCLIB_va_end( ap ) ( __builtin_va_end( ap ) )
#define _PDCLIB_va_start( ap, parmN ) ( __builtin_va_start( ap, parmN ) )
#else
#error Please create your own _PDCLIB_config.h. Using the existing one as-is will not work. (Unsupported varargs.)
#endif
/* -------------------------------------------------------------------------- */
/* OS "glue", part 1 */
/* These are values and data type definitions that you would have to adapt to */
/* the capabilities and requirements of your OS. */
/* The actual *functions* of the OS interface are declared in _PDCLIB_glue.h. */
/* -------------------------------------------------------------------------- */
/* I/O ---------------------------------------------------------------------- */
/* The type of the file descriptor returned by _PDCLIB_open(), i.e. whatever */
/* the underlying kernel uses for stream identification. */
typedef int _PDCLIB_fd_t;
/* The value of type _PDCLIB_fd_t returned by _PDCLIB_open() if the operation */
/* failed. */
#define _PDCLIB_NOHANDLE ( (_PDCLIB_fd_t) -1 )
/* The default size for file buffers. Must be at least 256. */
#define _PDCLIB_BUFSIZ 1024
/* The minimum number of files the implementation guarantees can opened */
/* simultaneously. Must be at least 8. Depends largely on how the platform */
/* does the bookkeeping in whatever is called by _PDCLIB_open(). PDCLib puts */
/* no further limits on the number of open files other than available memory. */
#define _PDCLIB_FOPEN_MAX 8
/* Length of the longest filename the implementation guarantees to support. */
#define _PDCLIB_FILENAME_MAX 128
/* Maximum length of filenames generated by tmpnam(). (See tmpfile.c.) */
#define _PDCLIB_L_tmpnam 46
/* Number of distinct file names that can be generated by tmpnam(). */
#define _PDCLIB_TMP_MAX 50
/* The values of SEEK_SET, SEEK_CUR and SEEK_END, used by fseek(). */
/* Since at least one platform (POSIX) uses the same symbols for its own */
/* "seek" function, you should use whatever the host defines (if it does */
/* define them). */
#define _PDCLIB_SEEK_SET 0
#define _PDCLIB_SEEK_CUR 1
#define _PDCLIB_SEEK_END 2
/* The number of characters that can be buffered with ungetc(). The standard */
/* guarantees only one (1); PDCLib supports larger values, but applications */
/* relying on this would rely on implementation-defined behaviour (not good). */
#define _PDCLIB_UNGETCBUFSIZE 1
/* The number of functions that can be registered with atexit(). Needs to be */
/* at least 33 (32 guaranteed by the standard, plus _PDCLIB_closeall() which */
/* is used internally by PDCLib to close all open streams). */
/* TODO: Should expand dynamically. */
#define _PDCLIB_ATEXIT_SLOTS 40
/* errno -------------------------------------------------------------------- */
/* These are the values that _PDCLIB_errno can be set to by the library. */
/* */
/* By keeping PDCLib's errno in the _PDCLIB_* namespace, the library is */
/* capable of "translating" between errno values used by the hosting OS and */
/* those used and passed out by the library. */
/* */
/* Example: In the example platform, the remove() function uses the unlink() */
/* system call as backend. Linux sets its errno to EISDIR if you try to */
/* unlink() a directory, but POSIX demands EPERM. Within the remove() */
/* function, you can catch 'errno == EISDIR', and set '*_PDCLIB_errno_func() */
/* = _PDCLIB_EPERM'. Anyone using PDCLib's <errno.h> will "see" EPERM instead */
/* of EISDIR. */
/* */
/* If you do not want that kind of translation, you might want to "match" the */
/* values used by PDCLib with those used by the host OS, to avoid confusion. */
/* auxiliary/errno/errno_readout.c provides a convenience program to read */
/* those errno values mandated by the standard from a platform's <errno.h>, */
/* giving output that can readily be pasted here. */
/* Either way, note that the list below, the list in PDCLib's <errno.h>, and */
/* the list in _PDCLIB_stdinit.h, need to be kept in sync. */
/* */
/* The values below are read from a Linux system. */
/* Argument list too long */
#define _PDCLIB_E2BIG 7
/* Permission denied */
#define _PDCLIB_EACCES 13
/* Address in use */
#define _PDCLIB_EADDRINUSE 98
/* Address not available */
#define _PDCLIB_EADDRNOTAVAIL 99
/* Address family not supported */
#define _PDCLIB_EAFNOSUPPORT 97
/* Resource unavailable, try again */
#define _PDCLIB_EAGAIN 11
/* Connection already in progress */
#define _PDCLIB_EALREADY 114
/* Bad file descriptor */
#define _PDCLIB_EBADF 9
/* Bad message */
#define _PDCLIB_EBADMSG 74
/* Device or resource busy */
#define _PDCLIB_EBUSY 16
/* Operation canceled */
#define _PDCLIB_ECANCELED 125
/* No child processes */
#define _PDCLIB_ECHILD 10
/* Connection aborted */
#define _PDCLIB_ECONNABORTED 103
/* Connection refused */
#define _PDCLIB_ECONNREFUSED 111
/* Connection reset */
#define _PDCLIB_ECONNRESET 104
/* Resource deadlock would occur */
#define _PDCLIB_EDEADLK 35
/* Destination address required */
#define _PDCLIB_EDESTADDRREQ 89
/* Mathematics argument out of domain of function */
#define _PDCLIB_EDOM 33
/* File exists */
#define _PDCLIB_EEXIST 17
/* Bad address */
#define _PDCLIB_EFAULT 14
/* File too large */
#define _PDCLIB_EFBIG 27
/* Host is unreachable */
#define _PDCLIB_EHOSTUNREACH 113
/* Identifier removed */
#define _PDCLIB_EIDRM 43
/* Illegal byte sequence */
#define _PDCLIB_EILSEQ 84
/* Operation in progress */
#define _PDCLIB_EINPROGRESS 115
/* Interrupted function */
#define _PDCLIB_EINTR 4
/* Invalid argument */
#define _PDCLIB_EINVAL 22
/* I/O error */
#define _PDCLIB_EIO 5
/* Socket is connected */
#define _PDCLIB_EISCONN 106
/* Is a directory */
#define _PDCLIB_EISDIR 21
/* Too many levels of symbolic links */
#define _PDCLIB_ELOOP 40
/* File descriptor value too large */
#define _PDCLIB_EMFILE 24
/* Too many links */
#define _PDCLIB_EMLINK 31
/* Message too large */
#define _PDCLIB_EMSGSIZE 90
/* Filename too long */
#define _PDCLIB_ENAMETOOLONG 36
/* Network is down */
#define _PDCLIB_ENETDOWN 100
/* Connection aborted by network */
#define _PDCLIB_ENETRESET 102
/* Network unreachable */
#define _PDCLIB_ENETUNREACH 101
/* Too many files open in system */
#define _PDCLIB_ENFILE 23
/* No buffer space available */
#define _PDCLIB_ENOBUFS 105
/* No message is available on the STREAM head read queue */
#define _PDCLIB_ENODATA 61
/* No such device */
#define _PDCLIB_ENODEV 19
/* No such file or directory */
#define _PDCLIB_ENOENT 2
/* Executable file format error */
#define _PDCLIB_ENOEXEC 8
/* No locks available */
#define _PDCLIB_ENOLCK 37
/* Link has been severed */
#define _PDCLIB_ENOLINK 67
/* Not enough space */
#define _PDCLIB_ENOMEM 12
/* No message of the desired type */
#define _PDCLIB_ENOMSG 42
/* Protocol not available */
#define _PDCLIB_ENOPROTOOPT 92
/* No space left on device */
#define _PDCLIB_ENOSPC 28
/* No STREAM resources */
#define _PDCLIB_ENOSR 63
/* Not a STREAM */
#define _PDCLIB_ENOSTR 60
/* Function not supported */
#define _PDCLIB_ENOSYS 38
/* The socket is not connected */
#define _PDCLIB_ENOTCONN 107
/* Not a directory */
#define _PDCLIB_ENOTDIR 20
/* Directory not empty */
#define _PDCLIB_ENOTEMPTY 39
/* State not recoverable */
#define _PDCLIB_ENOTRECOVERABLE 131
/* Not a socket */
#define _PDCLIB_ENOTSOCK 88
/* Not supported */
#define _PDCLIB_ENOTSUP 95
/* Inappropriate I/O control operation */
#define _PDCLIB_ENOTTY 25
/* No such device or address */
#define _PDCLIB_ENXIO 6
/* Operation not supported on socket */
#define _PDCLIB_EOPNOTSUPP 95
/* Value too large to be stored in data type */
#define _PDCLIB_EOVERFLOW 75
/* Previous owner died */
#define _PDCLIB_EOWNERDEAD 130
/* Operation not permitted */
#define _PDCLIB_EPERM 1
/* Broken pipe */
#define _PDCLIB_EPIPE 32
/* Protocol error */
#define _PDCLIB_EPROTO 71
/* Protocol not supported */
#define _PDCLIB_EPROTONOSUPPORT 93
/* Protocol wrong type for socket */
#define _PDCLIB_EPROTOTYPE 91
/* Result too large */
#define _PDCLIB_ERANGE 34
/* Read-only file system */
#define _PDCLIB_EROFS 30
/* Invalid seek */
#define _PDCLIB_ESPIPE 29
/* No such process */
#define _PDCLIB_ESRCH 3
/* Stream ioctl() timeout */
#define _PDCLIB_ETIME 62
/* Connection timed out */
#define _PDCLIB_ETIMEDOUT 110
/* Text file busy */
#define _PDCLIB_ETXTBSY 26
/* Operation would block */
#define _PDCLIB_EWOULDBLOCK 11
/* Cross-device link */
#define _PDCLIB_EXDEV 18
/* The highest defined errno value, plus one. This is used to set the size */
/* of the array in struct _PDCLIB_lc_text_t holding error messages for the */
/* strerror() and perror() functions. (If you change this value because you */
/* are using additional errno values, you *HAVE* to provide appropriate error */
/* messages for *ALL* locales.) */
#define _PDCLIB_ERRNO_MAX 132
/* The error message used for unknown error codes (generated by errno_readout */
/* for consistency between the 'holes' in the list of defined error messages */
/* and the text generated by e.g. strerror() for out-of-range error values.) */
#define _PDCLIB_EUNKNOWN_TEXT (char*)"unknown error"
/* locale data -------------------------------------------------------------- */
/* The default path where PDCLib should look for its locale data. */
/* Must end with the appropriate separator character. */
#define _PDCLIB_LOCALE_PATH "/usr/share/pdclib/i18n/"
/* The name of the environment variable that can be used to override that */
/* path setting. */
#define _PDCLIB_LOCALE_PATH_ENV PDCLIB_I18N
#ifdef __CYGWIN__
typedef unsigned int wint_t;
#endif
/* threads ------------------------------------------------------------------ */
/* This is relying on underlying <pthread.h> implementation to provide thread */
/* support. */
/* The problem here is we cannot just #include <pthread.h> and access the */
/* original definitions. The standard library must not drag identifiers into */
/* the user's namespace, so we have to set our own definitions in the _PDCLIB */
/* namespace. Which are, obviously, platform-specific. */
/* If you do NOT want to provide threads support, define __STDC_NO_THREADS__ */
/* to 1 and simply delete the threads.h header and the corresponding files in */
/* functions/threads/. This makes PDCLib non-thread-safe (obviously), as the */
/* safeguards against race conditions (e.g. in <stdio.h>) will be omitted. */
/* auxiliary/pthread/pthread_readout.c provides a convenience program to read */
/* appropriate definitions from a platform's <pthread.h>, giving output that */
/* can be copy & pasted here. */
typedef unsigned long int _PDCLIB_thrd_t;
typedef union { unsigned char _PDCLIB_cnd_t_data[ 48 ]; long long int _PDCLIB_cnd_t_align; } _PDCLIB_cnd_t;
#if defined( __arm__ ) || defined( __ARM_NEON )
typedef union { unsigned char _PDCLIB_mtx_t_data[ 24 ]; long int _PDCLIB_mtx_t_align; } _PDCLIB_mtx_t;
#else
typedef union { unsigned char _PDCLIB_mtx_t_data[ 40 ]; long int _PDCLIB_mtx_t_align; } _PDCLIB_mtx_t;
#endif
typedef unsigned int _PDCLIB_tss_t;
typedef int _PDCLIB_once_flag;
#define _PDCLIB_ONCE_FLAG_INIT 0
#define _PDCLIB_RECURSIVE_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
/* This one is actually hidden in <limits.h>, and only if __USE_POSIX is */
/* defined prior to #include <limits.h> (PTHREAD_DESTRUCTOR_ITERATIONS). */
#define _PDCLIB_TSS_DTOR_ITERATIONS 4
/* The following are not made public in any header, but used internally for */
/* interfacing with the pthread API. */
typedef union { unsigned char _PDCLIB_cnd_attr_t_data[ 4 ]; int _PDCLIB_cnd_attr_t_align; } _PDCLIB_cnd_attr_t;
typedef union { unsigned char _PDCLIB_mtx_attr_t_data[ 4 ]; int _PDCLIB_mtx_attr_t_align; } _PDCLIB_mtx_attr_t;
#if defined( __arm__ ) || defined( __ARM_NEON )
typedef union { unsigned char _PDCLIB_thrd_attr_t_data[ 36 ]; long int _PDCLIB_thrd_attr_t_align; } _PDCLIB_thrd_attr_t;
#else
typedef union { unsigned char _PDCLIB_thrd_attr_t_data[ 56 ]; long int _PDCLIB_thrd_attr_t_align; } _PDCLIB_thrd_attr_t;
#endif
/* Static initialization of recursive mutex. */
#if defined( __arm__ ) || defined( __ARM_NEON )
#define _PDCLIB_MTX_RECURSIVE_INIT { {\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
/* Static initialization of plain / timeout mutex (identical with pthread). */
#define _PDCLIB_MTX_PLAIN_INIT { {\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
#else
#define _PDCLIB_MTX_RECURSIVE_INIT { {\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
/* Static initialization of plain / timeout mutex (identical with pthread). */
#define _PDCLIB_MTX_PLAIN_INIT { {\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
#endif
/* Termux defines atexit in crtbegin_so.o leading to a multiple definition */
/* error from the linker. This is a crude workaround, which does NOT fix */
/* various run-time issues on Termux likely also related to crt linkage. But */
/* at least things compile OK, and SOME tests can be run. */
#if defined( __ARM_NEON )
#define atexit _PDCLIB_atexit
#endif
#endif

View File

@ -0,0 +1,29 @@
/* Definition guard <_PDCLIB_defguard.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_DEFGUARD_H
#define _PDCLIB_DEFGUARD_H _PDCLIB_DEFGUARD_H
#if defined( __ANDROID__ )
/* typedef sigset_t */
#include "bits/signal_types.h"
#endif
/* Linux defines its own version of struct timespec (from <time.h>) in
some internal header (depending on clib implementation), which leads
to problems when accessing e.g. sys/time.h (type redefinition).
The solution is to set the Linux header's include guard (to avoid
Linux' definition), and to include PDCLib's <time.h> to define the
type unambiguously.
*/
#define _TIMESPEC_DEFINED
#define _SYS__TIMESPEC_H_
#define _STRUCT_TIMESPEC
#include <time.h>
#endif

View File

@ -0,0 +1,93 @@
/* OS glue functions declaration <_PDCLIB_glue.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_GLUE_H
#define _PDCLIB_GLUE_H _PDCLIB_GLUE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_internal.h"
/* -------------------------------------------------------------------------- */
/* OS "glue", part 2 */
/* These are the functions you will have to touch, as they are where PDCLib */
/* interfaces with the operating system. */
/* They operate on data types partially defined by _PDCLIB_config.h. */
/* -------------------------------------------------------------------------- */
/* stdlib.h */
/* A system call that terminates the calling process, returning a given status
to the environment.
*/
_PDCLIB_LOCAL _PDCLIB_Noreturn void _PDCLIB_Exit( int status ) _PDCLIB_NORETURN;
/* stdio.h */
/* A system call that opens a file identified by name in a given mode. Return
a file descriptor uniquely identifying that file.
(The mode is the return value of the _PDCLIB_filemode() function.)
*/
_PDCLIB_LOCAL _PDCLIB_fd_t _PDCLIB_open( const char * const filename, unsigned int mode );
/* A system call that writes a stream's buffer.
Returns 0 on success, EOF on write error.
Sets stream error flags and errno appropriately on error.
*/
_PDCLIB_LOCAL int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream );
/* A system call that fills a stream's buffer.
Returns 0 on success, EOF on read error / EOF.
Sets stream EOF / error flags and errno appropriately on error.
*/
_PDCLIB_LOCAL int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream );
/* A system call that repositions within a file. Returns new offset on success,
-1 / errno on error.
*/
_PDCLIB_LOCAL _PDCLIB_int_least64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int_least64_t offset, int whence );
/* A system call that closes a file identified by given file descriptor. Return
zero on success, non-zero otherwise.
*/
_PDCLIB_LOCAL int _PDCLIB_close( _PDCLIB_fd_t fd );
/* A system call that changes the mode of a given stream to that passed as
argument (the argument being the value returned by _PDCLIB_filemode()),
*without* closing the stream. See comments in example implementation
for details. Return zero if the requested mode change is not supported
for this stream and freopen() should try to close and reopen the stream;
return INT_MIN if the change is not supported and freopen() should close
and NOT try to close / reopen (i.e., fail). Return any other value on
success.
*/
_PDCLIB_LOCAL int _PDCLIB_changemode( struct _PDCLIB_file_t * stream, unsigned int mode );
/* A system call that returns a canonicalized absolute filename in
dynamically allocated memory, or NULL if the file does not exist.
*/
_PDCLIB_LOCAL char * _PDCLIB_realpath( const char * path );
/* A system call that removes a file. Return zero on success, non-zero
otherwise.
*/
_PDCLIB_LOCAL int _PDCLIB_remove( const char * pathname );
/* A system call that renames a file from given old name to given new name.
Return zero on success, non-zero otherwise. In case of failure, the file
must still be accessible by old name. Any handling of open files etc. is
done by standard rename() already.
*/
_PDCLIB_LOCAL int _PDCLIB_rename( const char * oldpath, const char * newpath );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,776 @@
/* PDCLib internal logic <_PDCLIB_internal.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_INTERNAL_H
#define _PDCLIB_INTERNAL_H _PDCLIB_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
/* -------------------------------------------------------------------------- */
/* You should not have to edit anything in this file; if you DO have to, it */
/* would be considered a bug / missing feature: notify the author(s). */
/* -------------------------------------------------------------------------- */
#include "pdclib/_PDCLIB_config.h"
/* -------------------------------------------------------------------------- */
/* Standard Version */
/* -------------------------------------------------------------------------- */
/* Many a compiler gets this wrong, so you might have to hardcode it instead. */
#if __STDC__ != 1
#error Compiler does not define _ _STDC_ _ to 1 (not standard-compliant)!
#endif
#ifndef __STDC_HOSTED__
#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)!
#elif __STDC_HOSTED__ != 0 && __STDC_HOSTED__ != 1
#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)!
#endif
/* null pointer constant -- ((void *)0) in C, 0 in C++98, nullptr since C++11 */
#ifdef __cplusplus
#if __cplusplus >= 201103L
#define _PDCLIB_NULL nullptr
#else
#define _PDCLIB_NULL 0
#endif
#else
#define _PDCLIB_NULL ((void *)0)
#endif
/* restrict / inline enabled for C99 onward only */
#if defined( __cplusplus ) || ! defined( __STDC_VERSION ) || __STDC_VERSION__ < 199901L
#define _PDCLIB_restrict
#define _PDCLIB_inline
#else
#define _PDCLIB_restrict restrict
#define _PDCLIB_inline inline
#endif
/* noreturn enabled for C11 onward only */
#if defined( __cplusplus ) && __cplusplus >= 201103L
#define _PDCLIB_Noreturn [[noreturn]]
#else
#if defined( __STDC_VERSION__ ) >= 201112L
#define _PDCLIB_Noreturn _Noreturn
#else
#define _PDCLIB_Noreturn
#endif
#endif
/* -------------------------------------------------------------------------- */
/* Helper macros: */
/* */
/* (defined in _PDCLIB_config.h) */
/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending. */
/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */
/* */
/* (defined below) */
/* _PDCLIB_static_assert( e, m ) does a compile-time assertion of expression */
/* e, with m as the failure message. */
/* _PDCLIB_symbol2string( x ) turn symbol into string literal (by adding ""). */
/* _PDCLIB_value2string( x ) expands a preprocessor token and turns it into a */
/* string literal (by adding ""). */
/* _PDCLIB_TYPE_SIGNED( type ) resolves to true if type is signed. */
/* _PDCLIB_LOCK( mtx ) lock a mutex if library has threads support. */
/* _PDCLIB_UNLOCK( mtx ) unlock a mutex if library has threads support. */
/* _PDCLIB_CONSTRAINT_VIOLATION( e ) expand errno number e to parameter list */
/* fit for Annex K constraint violation */
/* handler. */
/* -------------------------------------------------------------------------- */
#define _PDCLIB_static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) }
#define _PDCLIB_TYPE_SIGNED( type ) (((type) -1) < 0)
#define _PDCLIB_symbol2string( x ) #x
#define _PDCLIB_value2string( x ) _PDCLIB_symbol2string( x )
#ifndef __STDC_NO_THREADS__
#define _PDCLIB_LOCK( mtx ) mtx_lock( &mtx )
#define _PDCLIB_UNLOCK( mtx ) mtx_unlock( &mtx )
#else
#define _PDCLIB_LOCK( mtx )
#define _PDCLIB_UNLOCK( mtx )
#endif
#define _PDCLIB_CONSTRAINT_VIOLATION( e ) _PDCLIB_lc_messages->errno_texts[e], NULL, e
#define _PDCLIB_GETC( fh ) ( ( fh->ungetidx == 0 ) ? ( unsigned char )fh->buffer[ fh->bufidx++ ] : ( unsigned char )fh->ungetbuf[ --fh->ungetidx ] )
#define _PDCLIB_CHECKBUFFER( fh ) ( ( ( fh->bufidx == fh->bufend ) && ( fh->ungetidx == 0 ) ) ? _PDCLIB_fillbuffer( fh ) : 0 )
/* -------------------------------------------------------------------------- */
/* Preparing the length modifiers used in <inttypes.h>. */
/* -------------------------------------------------------------------------- */
/* We use the _MAX value as a proxy for the actual type here. That is crude
but the best we can do, cross-platform wise.
Identifying which type the leastN_t / fastN_t / intmax_t / intptr_t are
and providing the appropriate printf()/scanf() length modifier.
*/
#if _PDCLIB_INT_FAST8_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INT_FAST8_PREFIX hh
#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INT_FAST8_PREFIX h
#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INT_FAST8_PREFIX
#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INT_FAST8_PREFIX l
#elif _PDCLIB_INT_FAST8_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INT_FAST8_PREFIX ll
#else
#error No matching native type for int_fast8_t. Please check your setup.
#endif
#if _PDCLIB_INT_FAST16_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INT_FAST16_PREFIX hh
#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INT_FAST16_PREFIX h
#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INT_FAST16_PREFIX
#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INT_FAST16_PREFIX l
#elif _PDCLIB_INT_FAST16_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INT_FAST16_PREFIX ll
#else
#error No matching native type for int_fast16_t. Please check your setup.
#endif
#if _PDCLIB_INT_FAST32_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INT_FAST32_PREFIX hh
#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INT_FAST32_PREFIX h
#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INT_FAST32_PREFIX
#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INT_FAST32_PREFIX l
#elif _PDCLIB_INT_FAST32_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INT_FAST32_PREFIX ll
#else
#error No matching native type for int_fast32_t. Please check your setup.
#endif
#if _PDCLIB_INT_FAST64_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INT_FAST64_PREFIX hh
#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INT_FAST64_PREFIX h
#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INT_FAST64_PREFIX
#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INT_FAST64_PREFIX l
#elif _PDCLIB_INT_FAST64_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INT_FAST64_PREFIX ll
#else
#error No matching native type for int_fast64_t. Please check your setup.
#endif
/* Many of the combinations below can very likely be ruled out logically.
All combinations are still listed for simplicity's sake (and to not fall
into the trap of false assumptions).
*/
#if _PDCLIB_INT_LEAST8_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INT_LEAST8_PREFIX hh
#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INT_LEAST8_PREFIX h
#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INT_LEAST8_PREFIX
#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INT_LEAST8_PREFIX l
#elif _PDCLIB_INT_LEAST8_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INT_LEAST8_PREFIX ll
#else
#error No matching native type for int_least8_t. Please check your setup.
#endif
#if _PDCLIB_INT_LEAST16_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INT_LEAST16_PREFIX hh
#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INT_LEAST16_PREFIX h
#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INT_LEAST16_PREFIX
#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INT_LEAST16_PREFIX l
#elif _PDCLIB_INT_LEAST16_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INT_LEAST16_PREFIX ll
#else
#error No matching native type for int_least16_t. Please check your setup.
#endif
#if _PDCLIB_INT_LEAST32_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INT_LEAST32_PREFIX hh
#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INT_LEAST32_PREFIX h
#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INT_LEAST32_PREFIX
#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INT_LEAST32_PREFIX l
#elif _PDCLIB_INT_LEAST32_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INT_LEAST32_PREFIX ll
#else
#error No matching native type for int_least32_t. Please check your setup.
#endif
#if _PDCLIB_INT_LEAST64_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INT_LEAST64_PREFIX hh
#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INT_LEAST64_PREFIX h
#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INT_LEAST64_PREFIX
#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INT_LEAST64_PREFIX l
#elif _PDCLIB_INT_LEAST64_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INT_LEAST64_PREFIX ll
#else
#error No matching native type for int_least64_t. Please check your setup.
#endif
#if _PDCLIB_INTMAX_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INTMAX_PREFIX hh
#elif _PDCLIB_INTMAX_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INTMAX_PREFIX h
#elif _PDCLIB_INTMAX_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INTMAX_PREFIX
#elif _PDCLIB_INTMAX_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INTMAX_PREFIX l
#elif _PDCLIB_INTMAX_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INTMAX_PREFIX ll
#else
#error No matching native type for intmax_t. Please check your setup.
#endif
#if _PDCLIB_INTPTR_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_INTPTR_PREFIX hh
#elif _PDCLIB_INTPTR_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_INTPTR_PREFIX h
#elif _PDCLIB_INTPTR_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_INTPTR_PREFIX
#elif _PDCLIB_INTPTR_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_INTPTR_PREFIX l
#elif _PDCLIB_INTPTR_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_INTPTR_PREFIX ll
#else
#error No matching native type for intptr_t. Please check your setup.
#endif
/* We might not have a type definition for sig_atomic_t at this point. The */
/* clang compiler does not provide an appropriate predefine for it. So if we */
/* do not have _PDCLIB_sig_atomic_t, identify the type trough its MAX value. */
#ifndef _PDCLIB_sig_atomic_t
#if _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_SCHAR_MAX
#define _PDCLIB_sig_atomic_t char
#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_SHRT_MAX
#define _PDCLIB_sig_atomic_t short
#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_INT_MAX
#define _PDCLIB_sig_atomic_t int
#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_LONG_MAX
#define _PDCLIB_sig_atomic_t long
#elif _PDCLIB_SIG_ATOMIC_MAX == _PDCLIB_LLONG_MAX
#define _PDCLIB_sig_atomic_t long long
#else
#error No matching native type for sig_atomic_t. Please check your setup.
#endif
#endif
/* -------------------------------------------------------------------------- */
/* Various <stdio.h> internals */
/* -------------------------------------------------------------------------- */
/* Flags for representing mode (see fopen()). Note these must fit the same
status field as the _IO?BF flags in <stdio.h> and the internal flags below.
*/
#define _PDCLIB_FREAD (1u<<3)
#define _PDCLIB_FWRITE (1u<<4)
#define _PDCLIB_FAPPEND (1u<<5)
#define _PDCLIB_FRW (1u<<6)
#define _PDCLIB_FBIN (1u<<7)
/* Internal flags, made to fit the same status field as the flags above. */
/* -------------------------------------------------------------------------- */
/* free() the buffer memory on closing (setvbuf()) */
#define _PDCLIB_FREEBUFFER (1u<<8)
/* stream has encountered error / EOF */
#define _PDCLIB_ERRORFLAG (1u<<9)
#define _PDCLIB_EOFFLAG (1u<<10)
/* stream is wide-oriented */
#define _PDCLIB_WIDESTREAM (1u<<11)
/* stream is byte-oriented */
#define _PDCLIB_BYTESTREAM (1u<<12)
/* file associated with stream should be remove()d on closing (tmpfile()) */
#define _PDCLIB_DELONCLOSE (1u<<13)
/* Position / status structure for getpos() / fsetpos(). */
struct _PDCLIB_fpos_t
{
_PDCLIB_uint_least64_t offset; /* File position offset */
int status; /* Multibyte parsing state (unused, reserved) */
};
/* FILE structure */
struct _PDCLIB_file_t
{
_PDCLIB_fd_t handle; /* OS file handle */
char * buffer; /* Pointer to buffer memory */
_PDCLIB_size_t bufsize; /* Size of buffer */
_PDCLIB_size_t bufidx; /* Index of current position in buffer */
_PDCLIB_size_t bufend; /* Index of last pre-read character in buffer */
struct _PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */
_PDCLIB_size_t ungetidx; /* Number of ungetc()'ed characters */
unsigned char ungetbuf[_PDCLIB_UNGETCBUFSIZE]; /* ungetc() buffer */
unsigned int status; /* Status flags; see above */
/* multibyte parsing status to be added later */
#ifndef __STDC_NO_THREADS__
_PDCLIB_mtx_t mtx; /* Multithreading safety */
#endif
char * filename; /* Name the current stream has been opened with */
struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */
};
/* -------------------------------------------------------------------------- */
/* Internal data types */
/* -------------------------------------------------------------------------- */
/* Structure required by both atexit() and exit() for handling atexit functions */
struct _PDCLIB_exitfunc_t
{
struct _PDCLIB_exitfunc_t * next;
void ( *func )( void );
};
/* Status structure required by _PDCLIB_print(). */
struct _PDCLIB_status_t
{
int base; /* base to which the value shall be converted */
_PDCLIB_int_fast32_t flags; /* flags and length modifiers */
_PDCLIB_size_t n; /* print: maximum characters to be written */
/* scan: number matched conversion specifiers */
_PDCLIB_size_t i; /* number of characters read/written */
_PDCLIB_size_t current;/* chars read/written in the CURRENT conversion */
char * s; /* *sprintf(): target buffer */
/* *sscanf(): source string */
_PDCLIB_size_t width; /* specified field width */
int prec; /* specified field precision */
struct _PDCLIB_file_t * stream; /* *fprintf() / *fscanf() stream */
_PDCLIB_va_list arg; /* argument stack */
};
/* -------------------------------------------------------------------------- */
/* Declaration of helper functions (implemented in functions/_PDCLIB). */
/* -------------------------------------------------------------------------- */
/* This is the main function called by atoi(), atol() and atoll(). */
_PDCLIB_LOCAL _PDCLIB_intmax_t _PDCLIB_atomax( const char * s );
/* Two helper functions used by strtol(), strtoul() and long long variants. */
_PDCLIB_LOCAL const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base );
_PDCLIB_LOCAL _PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, _PDCLIB_uintmax_t error, _PDCLIB_uintmax_t limval, int limdigit, char * sign );
/* A helper function used by strtof(), strtod(), and strtold(). */
_PDCLIB_LOCAL void _PDCLIB_strtod_scan( const char * s, const char ** dec, const char ** frac, const char ** exp, int base );
/* Digits arrays used by various integer conversion functions */
extern const char _PDCLIB_digits[];
extern const char _PDCLIB_Xdigits[];
/* The worker for all printf() type of functions. The pointer spec should point
to the introducing '%' of a conversion specifier. The status structure is to
be that of the current printf() function, of which the members n, s, stream
and arg will be preserved; i will be updated; and all others will be trashed
by the function.
Returns a pointer to the first character not parsed as conversion specifier.
*/
_PDCLIB_LOCAL const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status );
/* The worker for all scanf() type of functions. The pointer spec should point
to the introducing '%' of a conversion specifier. The status structure is to
be that of the current scanf() function, of which the member stream will be
preserved; n, i, and s will be updated; and all others will be trashed by
the function.
Returns a pointer to the first character not parsed as conversion specifier,
or NULL in case of error.
FIXME: Should distinguish between matching and input error
*/
_PDCLIB_LOCAL const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status );
/* Parsing any fopen() style filemode string into a number of flags. */
_PDCLIB_LOCAL unsigned int _PDCLIB_filemode( const char * mode );
/* Initialize a FILE structure. If the parameter is NULL, a new FILE structure
is malloc'ed. Returns a pointer to the stream if successful, NULL otherwise.
*/
_PDCLIB_LOCAL struct _PDCLIB_file_t * _PDCLIB_init_file_t( struct _PDCLIB_file_t * stream );
/* Sanity checking and preparing of read buffer, should be called first thing
by any stdio read-data function.
Returns 0 on success, EOF on error.
On error, EOF / error flags and errno are set appropriately.
*/
_PDCLIB_LOCAL int _PDCLIB_prepread( struct _PDCLIB_file_t * stream );
/* Sanity checking, should be called first thing by any stdio write-data
function.
Returns 0 on success, EOF on error.
On error, error flags and errno are set appropriately.
*/
_PDCLIB_LOCAL int _PDCLIB_prepwrite( struct _PDCLIB_file_t * stream );
/* Closing all streams on program exit */
_PDCLIB_LOCAL void _PDCLIB_closeall( void );
/* Check if a given year is a leap year. Parameter is offset to 1900. */
_PDCLIB_LOCAL int _PDCLIB_is_leap( int year_offset );
/* Read a specified number of lines from a file stream; return a pointer to
allocated memory holding the lines (newlines replaced with zero terminators)
or NULL in case of error.
*/
_PDCLIB_LOCAL char * _PDCLIB_load_lines( struct _PDCLIB_file_t * stream, _PDCLIB_size_t lines );
/* Returns the (locale dependent) error message associated with the argument
errno value.
*/
_PDCLIB_LOCAL char * _PDCLIB_geterrtext( int errnum );
/* Returns non-zero if the given stream is on the internal list of open files,
zero otherwise. Sets the second paramenter (if not NULL) to the previous
stream on the list (or NULL if the given stream is the first on the list).
This function does not lock _PDCLIB_filelist_mtx, this needs to be done by
the calling function (_PDCLIB_getstream() or freopen()).
*/
_PDCLIB_LOCAL int _PDCLIB_isstream( struct _PDCLIB_file_t * stream, struct _PDCLIB_file_t ** previous );
/* Removes the given stream from the internal list of open files. Returns zero
if successful, non-zero otherwise. In case of error, sets errno to EBADF.
This function does not lock _PDCLIB_filelist_mtx, this needs to be done by
the calling function (fclose()).
*/
_PDCLIB_LOCAL int _PDCLIB_getstream( struct _PDCLIB_file_t * stream );
/* Backend for strtok and strtok_s (plus potential extensions like strtok_r). */
_PDCLIB_LOCAL char * _PDCLIB_strtok( char * _PDCLIB_restrict s1, _PDCLIB_size_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr );
/* -------------------------------------------------------------------------- */
/* errno */
/* -------------------------------------------------------------------------- */
/* A mechanism for delayed evaluation.
If PDCLib would call its error number "errno" directly, there would be no way
to catch its value from underlying system calls that also use it (i.e., POSIX
operating systems). That is why we use an internal name, providing a means to
access it through <errno.h>.
*/
_PDCLIB_PUBLIC int * _PDCLIB_errno_func( void );
/* -------------------------------------------------------------------------- */
/* <locale.h> support */
/* -------------------------------------------------------------------------- */
#define _PDCLIB_LC_ALL 0
#define _PDCLIB_LC_COLLATE 1
#define _PDCLIB_LC_CTYPE 2
#define _PDCLIB_LC_MONETARY 3
#define _PDCLIB_LC_NUMERIC 4
#define _PDCLIB_LC_TIME 5
#define _PDCLIB_LC_MESSAGES 6
#define _PDCLIB_LC_COUNT 7
#define _PDCLIB_CTYPE_ALPHA 1
#define _PDCLIB_CTYPE_BLANK 2
#define _PDCLIB_CTYPE_CNTRL 4
#define _PDCLIB_CTYPE_GRAPH 8
#define _PDCLIB_CTYPE_PUNCT 16
#define _PDCLIB_CTYPE_SPACE 32
#define _PDCLIB_CTYPE_LOWER 64
#define _PDCLIB_CTYPE_UPPER 128
#define _PDCLIB_CHARSET_SIZE ( 1 << _PDCLIB_CHAR_BIT )
struct _PDCLIB_lc_lconv_numeric_t
{
char * decimal_point;
char * thousands_sep;
char * grouping;
};
struct _PDCLIB_lc_lconv_monetary_t
{
char * mon_decimal_point;
char * mon_thousands_sep;
char * mon_grouping;
char * positive_sign;
char * negative_sign;
char * currency_symbol;
char * int_curr_symbol;
char frac_digits;
char p_cs_precedes;
char n_cs_precedes;
char p_sep_by_space;
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
char int_frac_digits;
char int_p_cs_precedes;
char int_n_cs_precedes;
char int_p_sep_by_space;
char int_n_sep_by_space;
char int_p_sign_posn;
char int_n_sign_posn;
};
struct _PDCLIB_lc_numeric_monetary_t
{
struct lconv * lconv;
int numeric_alloced;
int monetary_alloced;
};
extern struct _PDCLIB_lc_numeric_monetary_t _PDCLIB_lc_numeric_monetary;
struct _PDCLIB_lc_collate_t
{
int alloced;
/* 1..3 code points */
/* 1..8, 18 collation elements of 3 16-bit integers */
};
extern struct _PDCLIB_lc_collate_t _PDCLIB_lc_collate_C;
extern struct _PDCLIB_lc_collate_t * _PDCLIB_lc_collate;
/* One entry to the _PDCLIB_lc_ctype_t.entry data table */
struct _PDCLIB_lc_ctype_entry_t
{
_PDCLIB_uint_least16_t flags; /* Whether a character is of a given CTYPE */
unsigned char upper; /* Result for toupper() */
unsigned char lower; /* Result for tolower() */
};
struct _PDCLIB_lc_ctype_t
{
int alloced; /* .entry dynamically allocated? */
int digits_low; /* Where decimal digits start */
int digits_high; /* Where decimal digits end */
int Xdigits_low; /* Where A..F start */
int Xdigits_high; /* Where A..F end */
int xdigits_low; /* Where a..f start */
int xdigits_high; /* Where a..f end */
struct _PDCLIB_lc_ctype_entry_t * entry; /* The data table */
};
extern struct _PDCLIB_lc_ctype_t _PDCLIB_lc_ctype_C;
extern struct _PDCLIB_lc_ctype_t * _PDCLIB_lc_ctype;
struct _PDCLIB_lc_messages_t
{
int alloced;
char * errno_texts[_PDCLIB_ERRNO_MAX]; /* strerror() / perror() */
};
extern struct _PDCLIB_lc_messages_t _PDCLIB_lc_messages_C;
extern struct _PDCLIB_lc_messages_t * _PDCLIB_lc_messages;
struct _PDCLIB_lc_time_t
{
int alloced;
char * month_name_abbr[12]; /* month names, abbreviated */
char * month_name_full[12]; /* month names, full */
char * day_name_abbr[7]; /* weekday names, abbreviated */
char * day_name_full[7]; /* weekday names, full */
char * date_time_format; /* date / time format for strftime( "%c" ) */
char * time_format_12h; /* 12-hour time format for strftime( "%r" ) */
char * date_format; /* date format for strftime( "%x" ) */
char * time_format; /* time format for strftime( "%X" ) */
char * am_pm[2]; /* AM / PM designation */
};
extern struct _PDCLIB_lc_time_t _PDCLIB_lc_time_C;
extern struct _PDCLIB_lc_time_t * _PDCLIB_lc_time;
_PDCLIB_LOCAL struct _PDCLIB_lc_lconv_numeric_t * _PDCLIB_load_lc_numeric( const char * path, const char * locale );
_PDCLIB_LOCAL struct _PDCLIB_lc_lconv_monetary_t * _PDCLIB_load_lc_monetary( const char * path, const char * locale );
_PDCLIB_LOCAL struct _PDCLIB_lc_collate_t * _PDCLIB_load_lc_collate( const char * path, const char * locale );
_PDCLIB_LOCAL struct _PDCLIB_lc_ctype_t * _PDCLIB_load_lc_ctype( const char * path, const char * locale );
_PDCLIB_LOCAL struct _PDCLIB_lc_time_t * _PDCLIB_load_lc_time( const char * path, const char * locale );
_PDCLIB_LOCAL struct _PDCLIB_lc_messages_t * _PDCLIB_load_lc_messages( const char * path, const char * locale );
/* -------------------------------------------------------------------------- */
/* _PDCLIB_bigint_t support (required for floating point conversions) */
/* -------------------------------------------------------------------------- */
/* Must be divisible by 32. */
#define _PDCLIB_BIGINT_BITS 1024
#if _PDCLIB_BIGINT_DIGIT_BITS == 32
#define _PDCLIB_BIGINT_DIGIT_MAX UINT32_C( 0xFFFFFFFF )
#define _PDCLIB_BIGINT_BASE ( UINT64_C(1) << _PDCLIB_BIGINT_DIGIT_BITS )
typedef _PDCLIB_uint_least32_t _PDCLIB_bigint_digit_t;
typedef _PDCLIB_uint_least64_t _PDCLIB_bigint_arith_t;
typedef _PDCLIB_int_least64_t _PDCLIB_bigint_sarith_t;
#elif _PDCLIB_BIGINT_DIGIT_BITS == 16
#define _PDCLIB_BIGINT_DIGIT_MAX UINT16_C( 0xFFFF )
#define _PDCLIB_BIGINT_BASE ( UINT32_C(1) << _PDCLIB_BIGINT_DIGIT_BITS )
typedef _PDCLIB_uint_least16_t _PDCLIB_bigint_digit_t;
typedef _PDCLIB_uint_least32_t _PDCLIB_bigint_arith_t;
typedef _PDCLIB_int_least32_t _PDCLIB_bigint_sarith_t;
#elif _PDCLIB_BIGINT_DIGIT_BITS == 8
/* For testing purposes only. */
#define _PDCLIB_BIGINT_DIGIT_MAX UINT8_C( 0xFF )
#define _PDCLIB_BIGINT_BASE ( UINT16_C(1) << _PDCLIB_BIGINT_DIGIT_BITS )
typedef _PDCLIB_uint_least8_t _PDCLIB_bigint_digit_t;
typedef _PDCLIB_uint_least16_t _PDCLIB_bigint_arith_t;
typedef _PDCLIB_int_least16_t _PDCLIB_bigint_sarith_t;
#else
#error Only 16 or 32 supported for _PDCLIB_BIGINT_DIGIT_BITS.
#endif
/* How many "digits" a _PDCLIB_bigint_t holds. */
#define _PDCLIB_BIGINT_DIGITS _PDCLIB_BIGINT_BITS / _PDCLIB_BIGINT_DIGIT_BITS
/* Maximum number of characters needed for _PDCLIB_bigint_tostring() */
#define _PDCLIB_BIGINT_CHARS ( _PDCLIB_BIGINT_BITS / 4 + _PDCLIB_BIGINT_DIGITS + 2 )
/* Type */
/* ---- */
typedef struct
{
/* Least significant digit first */
_PDCLIB_bigint_digit_t data[ _PDCLIB_BIGINT_DIGITS ];
/* Number of digits used; zero value == zero size */
_PDCLIB_size_t size;
} _PDCLIB_bigint_t;
/* Initializer */
/* ----------- */
/* Sets a bigint to pow2( n ) */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint2( _PDCLIB_bigint_t * bigint, unsigned n );
/* Sets a bigint to pow10( n ) */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint10( _PDCLIB_bigint_t * bigint, unsigned n );
/* Sets a bigint from a 32bit input value. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint32( _PDCLIB_bigint_t * bigint, _PDCLIB_uint_least32_t value );
/* Sets a bigint from two 32bit input values. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint64( _PDCLIB_bigint_t * bigint, _PDCLIB_uint_least32_t high, _PDCLIB_uint_least32_t low );
/* Sets a bigint from another bigint. (Copies only value->size digits, so it is
faster than a POD copy of a _PDCLIB_bigint_t in most cases.)
*/
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint( _PDCLIB_bigint_t * _PDCLIB_restrict bigint, _PDCLIB_bigint_t const * _PDCLIB_restrict value );
/* Comparison, Output */
/* ------------------ */
/* Compares two given bigint values. Returns 0 if lhs == rhs, a negative number
if lhs < rhs, and a positive number if lhs > rhs.
*/
_PDCLIB_LOCAL int _PDCLIB_bigint_cmp( _PDCLIB_bigint_t const * _PDCLIB_restrict lhs, _PDCLIB_bigint_t const * _PDCLIB_restrict rhs );
/* Writes a hexadecimal representation of the given bigint into the given buffer.
Buffer should be at least _PDCLIB_BIGINT_CHARS in size.
*/
_PDCLIB_LOCAL char * _PDCLIB_bigint_tostring( _PDCLIB_bigint_t const * _PDCLIB_restrict value, char * _PDCLIB_restrict buffer );
/* Operations (in-place) */
/* --------------------- */
/* Adds to a given bigint another given bigint. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint_add( _PDCLIB_bigint_t * _PDCLIB_restrict lhs, _PDCLIB_bigint_t const * _PDCLIB_restrict rhs );
/* Substracts from a given bigint another given bigint. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint_sub( _PDCLIB_bigint_t * _PDCLIB_restrict lhs, _PDCLIB_bigint_t const * _PDCLIB_restrict rhs );
/* Multiplies a given bigint with a given 32bit value. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint_mul_dig( _PDCLIB_bigint_t * lhs, _PDCLIB_bigint_digit_t rhs );
/* Divides a given bigint by a given 32bit value. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint_div_dig( _PDCLIB_bigint_t * lhs, _PDCLIB_bigint_digit_t rhs );
/* Shifts a given bigint left by a given count of bits. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint_shl( _PDCLIB_bigint_t * lhs, unsigned rhs );
/* Operations (into new bigint) */
/* ---------------------------- */
/* Multiplies a given bigint with another given bigint. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint_mul( _PDCLIB_bigint_t * _PDCLIB_restrict result, _PDCLIB_bigint_t const * _PDCLIB_restrict lhs, _PDCLIB_bigint_t const * _PDCLIB_restrict rhs );
/* Divides a given bigint by another given bigint. */
_PDCLIB_LOCAL _PDCLIB_bigint_t * _PDCLIB_bigint_div( _PDCLIB_bigint_t * _PDCLIB_restrict result, _PDCLIB_bigint_t const * _PDCLIB_restrict lhs, _PDCLIB_bigint_t const * _PDCLIB_restrict rhs );
/* Queries */
/* ------- */
/* Returns the log2() of a given bigint */
_PDCLIB_LOCAL unsigned _PDCLIB_bigint_log2( _PDCLIB_bigint_t const * bigint );
/* FP Conversions */
/* -------------- */
/* Split a float into its integral components.
Returns 1 if value is negative, zero otherwise.
*/
_PDCLIB_LOCAL int _PDCLIB_float_split( float value, unsigned * exponent, _PDCLIB_bigint_t * significand );
/* Split a double into its integral components.
Returns 1 if value is negative, zero otherwise.
*/
_PDCLIB_LOCAL int _PDCLIB_double_split( double value, unsigned * exponent, _PDCLIB_bigint_t * significand );
/* Split a long double into its integral components.
Returns 1 if value is negative, zero otherwise.
*/
_PDCLIB_LOCAL int _PDCLIB_long_double_split( long double value, unsigned * exponent, _PDCLIB_bigint_t * significand );
/* -------------------------------------------------------------------------- */
/* Sanity checks */
/* -------------------------------------------------------------------------- */
/* signed-ness of char */
_PDCLIB_static_assert( _PDCLIB_CHAR_MIN == ((((char) -1) < 0) ? _PDCLIB_SCHAR_MIN : 0), "Compiler disagrees on signed-ness of 'char'." );
/* two's complement */
#if _PDCLIB_TWOS_COMPLEMENT == 1
#if _PDCLIB_CHAR_MIN < 0
_PDCLIB_static_assert( ((char) ~ (char) 0 < 0), "Not two's complement on 'char'." );
#endif
_PDCLIB_static_assert( ((short) ~ (short) 0 < 0), "Not two's complement on 'short'." );
_PDCLIB_static_assert( ((int) ~ (int) 0 < 0), "Not two's complement on 'int'." );
_PDCLIB_static_assert( ((long) ~ (long) 0 < 0), "Not two's complement on 'long'." );
_PDCLIB_static_assert( ((long long) ~ (long long) 0 < 0), "Not two's complement on 'long long'." );
#endif
/* size_t as the result of sizeof */
_PDCLIB_static_assert( sizeof( sizeof( int ) ) == sizeof( _PDCLIB_size_t ), "Compiler disagrees on size_t." );
/* wchar_t as the type of wide character literals */
_PDCLIB_static_assert( sizeof( _PDCLIB_wchar_t ) == sizeof( L'x' ), "Compiler disagrees on wchar_t." );
#ifdef __cplusplus
_PDCLIB_static_assert( sizeof( _PDCLIB_wchar_t ) == sizeof( wchar_t ), "Compiler disagrees on wchar_t (C++)." );
#endif
/* intptr_t/uintptr_t being wide enough to store the value of a pointer */
_PDCLIB_static_assert( sizeof( void * ) == sizeof( _PDCLIB_intptr_t ), "Compiler disagrees on intptr_t." );
_PDCLIB_static_assert( sizeof( void * ) == sizeof( _PDCLIB_uintptr_t ), "Compiler disagrees on uintptr_t." );
/* ptrdiff_t as the result of pointer arithmetic */
_PDCLIB_static_assert( sizeof( &_PDCLIB_digits[1] - &_PDCLIB_digits[0] ) == sizeof( _PDCLIB_ptrdiff_t ), "Compiler disagrees on ptrdiff_t." );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,32 @@
/* __STDC_WANT_LIB_EXT1__ redefinition guard
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef __STDC_WANT_LIB_EXT1__
#ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__
#if __STDC_WANT_LIB_EXT1_PREVIOUS__ != -1
#error __STDC_WANT_LIB_EXT1__ undefined when it was defined earlier.
#endif
#else
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ -1
#endif
#else
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) == 0 && ( 0 - __STDC_WANT_LIB_EXT1__ - 1 ) == 1
#error __STDC_WANT_LIB_EXT1__ defined but empty. Should be an integer value.
#endif
#ifdef __STDC_WANT_LIB_EXT1_PREVIOUS__
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != __STDC_WANT_LIB_EXT1_PREVIOUS__
#error __STDC_WANT_LIB_EXT1__ redefined from previous value.
#endif
#else
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) == 0
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ 0
#elif ( __STDC_WANT_LIB_EXT1__ + 0 ) == 1
#define __STDC_WANT_LIB_EXT1_PREVIOUS__ 1
#else
#error __STDC_WANT_LIB_EXT1__ set to value other than 0,1 -- undefined behavior
#endif
#endif
#endif

View File

@ -0,0 +1,71 @@
/* PDCLib printf logic <_PDCLIB_print.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_PRINT_H
#define _PDCLIB_PRINT_H _PDCLIB_PRINT_H
#include "pdclib/_PDCLIB_internal.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
/* This macro delivers a given character to either a memory buffer or a stream,
depending on the contents of 'status' (struct _PDCLIB_status_t).
x - the character to be delivered
i - pointer to number of characters already delivered in this call
n - pointer to maximum number of characters to be delivered in this call
s - the buffer into which the character shall be delivered
*/
#define PUT( x ) \
do { \
int character = x; \
if ( status->i < status->n ) { \
if ( status->stream != NULL ) \
putc( character, status->stream ); \
else \
status->s[status->i] = character; \
} \
++(status->i); \
} while ( 0 )
/* Using an integer's bits as flags for both the conversion flags and length
modifiers.
*/
#define E_minus (INT32_C(1)<<0)
#define E_plus (INT32_C(1)<<1)
#define E_alt (INT32_C(1)<<2)
#define E_space (INT32_C(1)<<3)
#define E_zero (INT32_C(1)<<4)
#define E_done (INT32_C(1)<<5)
#define E_char (INT32_C(1)<<6)
#define E_short (INT32_C(1)<<7)
#define E_long (INT32_C(1)<<8)
#define E_llong (INT32_C(1)<<9)
#define E_intmax (INT32_C(1)<<10)
#define E_size (INT32_C(1)<<11)
#define E_ptrdiff (INT32_C(1)<<12)
#define E_pointer (INT32_C(1)<<13)
#define E_double (INT32_C(1)<<14)
#define E_ldouble (INT32_C(1)<<15)
#define E_decimal (INT32_C(1)<<18)
#define E_exponent (INT32_C(1)<<19)
#define E_generic (INT32_C(1)<<20)
#define E_hexa (INT32_C(1)<<21)
#define E_lower (INT32_C(1)<<16)
#define E_unsigned (INT32_C(1)<<17)
void _PDCLIB_print_integer( struct _PDCLIB_imaxdiv_t div, struct _PDCLIB_status_t * status );
void _PDCLIB_print_string( const char * s, struct _PDCLIB_status_t * status );
void _PDCLIB_print_double( double value, struct _PDCLIB_status_t * status );
void _PDCLIB_print_ldouble( long double value, struct _PDCLIB_status_t * status );
#endif

View File

@ -0,0 +1,153 @@
/* TZ Code declarations and definitions <_PDCLIB_tzcode.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_TZCODE_H
#define _PDCLIB_TZCODE_H _PDCLIB_TZCODE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <pdclib/_PDCLIB_config.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
/* Handy macros that are independent of tzfile implementation. */
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
#define SECSPERMIN 60
#define MINSPERHOUR 60
#define HOURSPERDAY 24
#define DAYSPERWEEK 7
#define DAYSPERNYEAR 365
#define DAYSPERLYEAR 366
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
#define MONSPERYEAR 12
#define AVGSECSPERYEAR 31556952L
#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
#define TM_SUNDAY 0
#define TM_MONDAY 1
#define TM_TUESDAY 2
#define TM_WEDNESDAY 3
#define TM_THURSDAY 4
#define TM_FRIDAY 5
#define TM_SATURDAY 6
#define TM_YEAR_BASE 1900
#define EPOCH_YEAR 1970
#define EPOCH_WDAY TM_THURSDAY
extern struct tm _PDCLIB_tm;
extern int lcl_is_set;
static const char gmt[] = "GMT";
static const int mon_lengths[ 2 ][ MONSPERYEAR ] =
{
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
static const int year_lengths[2] =
{
DAYSPERNYEAR, DAYSPERLYEAR
};
/* time type information */
struct ttinfo
{
int_fast32_t utoff; /* UT offset in seconds */
bool isdst; /* used to set tm_isdst */
int desigidx; /* abbreviation list index */
bool ttisstd; /* transition is std time */
bool ttisut; /* transition is UT */
};
/* leap second information */
struct lsinfo
{
time_t trans; /* transition time */
int_fast64_t corr; /* correction to apply */
};
#define BIGGEST( a, b ) (((a) > (b)) ? (a) : (b))
#ifndef TZ_MAX_TIMES
#define TZ_MAX_TIMES 2000
#endif
#ifndef TZ_MAX_TYPES
/* This must be at least 17 for Europe/Vilnius. */
/* Limited by what (unsigned char)s can hold */
#define TZ_MAX_TYPES 256
#endif
#ifndef TZ_MAX_CHARS
/* Maximum number of abbreviation characters */
/* Limited by what (unsigned char)s can hold */
#define TZ_MAX_CHARS 50
#endif
#ifndef TZ_MAX_LEAPS
/* Maximum number of leap second corrections */
#define TZ_MAX_LEAPS 50
#endif
#ifdef TZNAME_MAX
#define MY_TZNAME_MAX TZNAME_MAX
#else
#define MY_TZNAME_MAX 255
#endif
struct state
{
int leapcnt;
int timecnt;
int typecnt;
int charcnt;
bool goback;
bool goahead;
time_t ats[ TZ_MAX_TIMES ];
unsigned char types[ TZ_MAX_TIMES ];
struct ttinfo ttis[ TZ_MAX_TYPES ];
char chars[ BIGGEST( BIGGEST( TZ_MAX_CHARS + 1, sizeof gmt ), ( 2 * ( MY_TZNAME_MAX + 1 ) ) ) ];
struct lsinfo lsis[ TZ_MAX_LEAPS ];
/* The time type to use for early times or if no transitions.
It is always zero for recent tzdb releases.
It might be nonzero for data from tzdb 2018e or earlier.
*/
int defaulttype;
};
extern struct state _PDCLIB_lclmem;
extern struct state _PDCLIB_gmtmem;
void _PDCLIB_gmtcheck(void);
struct tm * _PDCLIB_gmtsub( struct state const * sp, time_t const * timep, int_fast32_t offset, struct tm * tmp );
bool _PDCLIB_increment_overflow( int * ip, int j );
void _PDCLIB_init_ttinfo( struct ttinfo * s, int_fast32_t utoff, bool isdst, int desigidx );
struct tm * _PDCLIB_localsub( struct state const * sp, time_t const * timep, int_fast32_t setname, struct tm * const tmp );
struct tm * _PDCLIB_localtime_tzset( time_t const * timep, struct tm * tmp, bool setname );
time_t _PDCLIB_mktime_tzname( struct state * sp, struct tm * tmp, bool setname );
struct tm * _PDCLIB_timesub( const time_t * timep, int_fast32_t offset, const struct state * sp, struct tm * tmp );
int _PDCLIB_tzload( char const * name, struct state * sp, bool doextend );
bool _PDCLIB_tzparse(char const *, struct state *, bool);
void _PDCLIB_tzset_unlocked( void );
void _PDCLIB_update_tzname_etc( struct state const * sp, struct ttinfo const * ttisp );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,91 @@
/* Signal handling <signal.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_SIGNAL_H
#define _PDCLIB_SIGNAL_H _PDCLIB_SIGNAL_H
#include "pdclib/_PDCLIB_internal.h"
/* Signals ------------------------------------------------------------------ */
/* A word on signals, to the people using PDCLib in their OS projects.
The definitions of the C standard leave about everything that *could* be
useful to be "implementation defined". Without additional, non-standard
arrangements, it is not possible to turn them into a useful tool.
This example implementation chose to "not generate any of these signals,
except as a result of explicit calls to the raise function", which is
allowed by the standard but of course does nothing for the usefulness of
<signal.h>.
A useful signal handling would:
1) make signal() a system call that registers the signal handler with the OS
2) make raise() a system call triggering an OS signal to the running process
3) make provisions that further signals of the same type are blocked until
the signal handler returns (optional for SIGILL)
*/
/* These are the values used by Linux. */
/* Abnormal termination / abort() */
#define SIGABRT 6
/* Arithmetic exception / division by zero / overflow */
#define SIGFPE 8
/* Illegal instruction */
#define SIGILL 4
/* Interactive attention signal */
#define SIGINT 2
/* Invalid memory access */
#define SIGSEGV 11
/* Termination request */
#define SIGTERM 15
/* The following should be defined to pointer values that could NEVER point to
a valid signal handler function. (They are used as special arguments to
signal().) Again, these are the values used by Linux.
*/
#define SIG_DFL (void (*)( int ))0
#define SIG_ERR (void (*)( int ))-1
#define SIG_IGN (void (*)( int ))1
typedef _PDCLIB_sig_atomic_t sig_atomic_t;
/* Installs a signal handler "func" for the given signal.
A signal handler is a function that takes an integer as argument (the signal
number) and returns void.
Note that a signal handler can do very little else than:
1) assign a value to a static object of type "volatile sig_atomic_t",
2) call signal() with the value of sig equal to the signal received,
3) call _Exit(),
4) call abort().
Virtually everything else is undefind.
The signal() function returns the previous installed signal handler, which
at program start may be SIG_DFL or SIG_ILL. (This implementation uses
SIG_DFL for all handlers.) If the request cannot be honored, SIG_ERR is
returned and errno is set to an unspecified positive value.
*/
_PDCLIB_PUBLIC void ( *signal( int sig, void ( *func )( int ) ) )( int );
/* Raises the given signal (executing the registered signal handler with the
given signal number as parameter).
This implementation does not prevent further signals of the same time from
occuring, but executes signal( sig, SIG_DFL ) before entering the signal
handler (i.e., a second signal before the signal handler re-registers itself
or SIG_IGN will end the program).
Returns zero if successful, nonzero otherwise. */
_PDCLIB_PUBLIC int raise( int sig );
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_SIGNAL_H
#include _PDCLIB_EXTEND_SIGNAL_H
#endif
#endif

View File

@ -0,0 +1,26 @@
/* Alignment <stdalign.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STDALIGN_H
#define _PDCLIB_ALIGN_H _PDCLIB_ALIGN_H
#ifndef __cplusplus
#define alignas _Alignas
#define alignof _Alignof
#endif
#define __alignas_is_defined 1
#define __alignof_is_defined 1
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STDALIGN_H
#include _PDCLIB_EXTEND_STDALIGN_H
#endif
#endif

View File

@ -0,0 +1,34 @@
/* Variable arguments <stdarg.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STDARG_H
#define _PDCLIB_STDARG_H _PDCLIB_STDARG_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_config.h"
typedef _PDCLIB_va_list va_list;
#define va_arg( ap, type ) _PDCLIB_va_arg( ap, type )
#define va_copy( dest, src ) _PDCLIB_va_copy( dest, src )
#define va_end( ap ) _PDCLIB_va_end( ap )
#define va_start( ap, parmN ) _PDCLIB_va_start( ap, parmN )
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STDARG_H
#include _PDCLIB_EXTEND_STDARG_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,24 @@
/* Boolean type and values <stdbool.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STDBOOL_H
#define _PDCLIB_STDBOOL_H _PDCLIB_STDBOOL_H
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#endif
#define __bool_true_false_are_defined 1
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STDBOOL_H
#include _PDCLIB_EXTEND_STDBOOL_H
#endif
#endif

View File

@ -0,0 +1,55 @@
/* Common definitions <stddef.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STDDEF_H
#define _PDCLIB_STDDEF_H _PDCLIB_STDDEF_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_lib_ext1.h"
#include "pdclib/_PDCLIB_internal.h"
typedef _PDCLIB_ptrdiff_t ptrdiff_t;
#ifndef _PDCLIB_SIZE_T_DEFINED
#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED
typedef _PDCLIB_size_t size_t;
#endif
#ifndef __cplusplus
typedef _PDCLIB_wchar_t wchar_t;
#endif
#ifndef _PDCLIB_NULL_DEFINED
#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED
#define NULL _PDCLIB_NULL
#endif
#define offsetof( type, member ) _PDCLIB_offsetof( type, member )
/* Annex K -- Bounds-checking interfaces */
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0
#ifndef _PDCLIB_RSIZE_T_DEFINED
#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED
typedef size_t rsize_t;
#endif
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STDDEF_H
#include _PDCLIB_EXTEND_STDDEF_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,236 @@
/* Integer types <stdint.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STDINT_H
#define _PDCLIB_STDINT_H _PDCLIB_STDINT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_lib_ext1.h"
#include "pdclib/_PDCLIB_internal.h"
/* 7.18.1.1 Exact-width integer types. */
#ifdef _PDCLIB_int8_t
typedef _PDCLIB_int8_t int8_t;
typedef _PDCLIB_uint8_t uint8_t;
#endif
#ifdef _PDCLIB_int16_t
typedef _PDCLIB_int16_t int16_t;
typedef _PDCLIB_uint16_t uint16_t;
#endif
#ifdef _PDCLIB_int32_t
typedef _PDCLIB_int32_t int32_t;
typedef _PDCLIB_uint32_t uint32_t;
#endif
#ifdef _PDCLIB_int64_t
typedef _PDCLIB_int64_t int64_t;
typedef _PDCLIB_uint64_t uint64_t;
#endif
/* 7.18.1.2 Minimum-width integer types */
/* You are allowed to add more types here, e.g. int_least24_t. */
typedef _PDCLIB_int_least8_t int_least8_t;
typedef _PDCLIB_int_least16_t int_least16_t;
typedef _PDCLIB_int_least32_t int_least32_t;
typedef _PDCLIB_int_least64_t int_least64_t;
typedef _PDCLIB_uint_least8_t uint_least8_t;
typedef _PDCLIB_uint_least16_t uint_least16_t;
typedef _PDCLIB_uint_least32_t uint_least32_t;
typedef _PDCLIB_uint_least64_t uint_least64_t;
/* 7.18.1.3 Fastest minimum-width integer types */
/* You are allowed to add more types here, e.g. int_fast24_t. */
typedef _PDCLIB_int_fast8_t int_fast8_t;
typedef _PDCLIB_int_fast16_t int_fast16_t;
typedef _PDCLIB_int_fast32_t int_fast32_t;
typedef _PDCLIB_int_fast64_t int_fast64_t;
typedef _PDCLIB_uint_fast8_t uint_fast8_t;
typedef _PDCLIB_uint_fast16_t uint_fast16_t;
typedef _PDCLIB_uint_fast32_t uint_fast32_t;
typedef _PDCLIB_uint_fast64_t uint_fast64_t;
/* 7.18.1.4 Integer types capable of holding object pointers */
typedef _PDCLIB_intptr_t intptr_t;
typedef _PDCLIB_uintptr_t uintptr_t;
/* 7.18.1.5 Greatest-width integer types */
typedef _PDCLIB_intmax_t intmax_t;
typedef _PDCLIB_uintmax_t uintmax_t;
/* 7.18.2 Limits of specified-width integer types */
#if defined( __cplusplus ) && __cplusplus < 201103L
#ifndef __STDC_LIMIT_MACROS
#define _PDCLIB_NO_LIMIT_MACROS
#endif
#endif
#ifndef _PDCLIB_NO_LIMIT_MACROS
/* 7.18.2.1 Limits of exact-width integer types */
#if _PDCLIB_TWOS_COMPLEMENT == 1
#if _PDCLIB_INT_LEAST8_MAX == 0x7f
#define INT8_MAX _PDCLIB_INT_LEAST8_MAX
#define INT8_MIN _PDCLIB_INT_LEAST8_MIN
#define UINT8_MAX _PDCLIB_UINT_LEAST8_MAX
#endif
#if _PDCLIB_INT_LEAST16_MAX == 0x7fff
#define INT16_MAX _PDCLIB_INT_LEAST16_MAX
#define INT16_MIN _PDCLIB_INT_LEAST16_MIN
#define UINT16_MAX _PDCLIB_UINT_LEAST16_MAX
#endif
#if _PDCLIB_INT_LEAST32_MAX == 0x7fffffffl
#define INT32_MAX _PDCLIB_INT_LEAST32_MAX
#define INT32_MIN _PDCLIB_INT_LEAST32_MIN
#define UINT32_MAX _PDCLIB_UINT_LEAST32_MAX
#endif
#if _PDCLIB_INT_LEAST64_MAX == 0x7fffffffffffffffll
#define INT64_MAX _PDCLIB_INT_LEAST64_MAX
#define INT64_MIN _PDCLIB_INT_LEAST64_MIN
#define UINT64_MAX _PDCLIB_UINT_LEAST64_MAX
#endif
#endif
/* 7.18.2.2 Limits of minimum-width integer types */
#define INT_LEAST8_MIN _PDCLIB_INT_LEAST8_MIN
#define INT_LEAST8_MAX _PDCLIB_INT_LEAST8_MAX
#define UINT_LEAST8_MAX _PDCLIB_UINT_LEAST8_MAX
#define INT_LEAST16_MIN _PDCLIB_INT_LEAST16_MIN
#define INT_LEAST16_MAX _PDCLIB_INT_LEAST16_MAX
#define UINT_LEAST16_MAX _PDCLIB_UINT_LEAST16_MAX
#define INT_LEAST32_MIN _PDCLIB_INT_LEAST32_MIN
#define INT_LEAST32_MAX _PDCLIB_INT_LEAST32_MAX
#define UINT_LEAST32_MAX _PDCLIB_UINT_LEAST32_MAX
#define INT_LEAST64_MIN _PDCLIB_INT_LEAST64_MIN
#define INT_LEAST64_MAX _PDCLIB_INT_LEAST64_MAX
#define UINT_LEAST64_MAX _PDCLIB_UINT_LEAST64_MAX
/* 7.18.2.3 Limits of fastest minimum-width integer types */
#define INT_FAST8_MIN _PDCLIB_INT_FAST8_MIN
#define INT_FAST8_MAX _PDCLIB_INT_FAST8_MAX
#define UINT_FAST8_MAX _PDCLIB_UINT_FAST8_MAX
#define INT_FAST16_MIN _PDCLIB_INT_FAST16_MIN
#define INT_FAST16_MAX _PDCLIB_INT_FAST16_MAX
#define UINT_FAST16_MAX _PDCLIB_UINT_FAST16_MAX
#define INT_FAST32_MIN _PDCLIB_INT_FAST32_MIN
#define INT_FAST32_MAX _PDCLIB_INT_FAST32_MAX
#define UINT_FAST32_MAX _PDCLIB_UINT_FAST32_MAX
#define INT_FAST64_MIN _PDCLIB_INT_FAST64_MIN
#define INT_FAST64_MAX _PDCLIB_INT_FAST64_MAX
#define UINT_FAST64_MAX _PDCLIB_UINT_FAST64_MAX
/* 7.18.2.4 Limits of integer types capable of holding object pointers */
#define INTPTR_MIN _PDCLIB_INTPTR_MIN
#define INTPTR_MAX _PDCLIB_INTPTR_MAX
#define UINTPTR_MAX _PDCLIB_UINTPTR_MAX
/* 7.18.2.5 Limits of greatest-width integer types */
#define INTMAX_MIN _PDCLIB_INTMAX_MIN
#define INTMAX_MAX _PDCLIB_INTMAX_MAX
#define UINTMAX_MAX _PDCLIB_UINTMAX_MAX
/* 7.18.3 Limits of other integer types */
#define PTRDIFF_MIN _PDCLIB_PTRDIFF_MIN
#define PTRDIFF_MAX _PDCLIB_PTRDIFF_MAX
#define SIG_ATOMIC_MIN _PDCLIB_SIG_ATOMIC_MIN
#define SIG_ATOMIC_MAX _PDCLIB_SIG_ATOMIC_MAX
#define SIZE_MAX _PDCLIB_SIZE_MAX
#define WCHAR_MIN _PDCLIB_WCHAR_MIN
#define WCHAR_MAX _PDCLIB_WCHAR_MAX
#define WINT_MIN _PDCLIB_WINT_MIN
#define WINT_MAX _PDCLIB_WINT_MAX
#endif
/* 7.18.4 Macros for integer constants */
#if defined( __cplusplus ) && __cplusplus < 201103L
#ifndef __STDC_CONSTANT_MACROS
#define _PDCLIB_NO_CONSTANT_MACROS
#endif
#endif
#ifndef _PDCLIB_NO_CONSTANT_MACROS
/* 7.18.4.1 Macros for minimum-width integer constants */
/* Expand to an integer constant of specified value and type int_leastN_t */
#define INT8_C _PDCLIB_INT_LEAST8_C
#define INT16_C _PDCLIB_INT_LEAST16_C
#define INT32_C _PDCLIB_INT_LEAST32_C
#define INT64_C _PDCLIB_INT_LEAST64_C
/* Expand to an integer constant of specified value and type uint_leastN_t */
#define UINT8_C _PDCLIB_UINT_LEAST8_C
#define UINT16_C _PDCLIB_UINT_LEAST16_C
#define UINT32_C _PDCLIB_UINT_LEAST32_C
#define UINT64_C _PDCLIB_UINT_LEAST64_C
/* 7.18.4.2 Macros for greatest-width integer constants */
/* Expand to an integer constant of specified value and type intmax_t */
#define INTMAX_C( value ) _PDCLIB_INTMAX_C( value )
/* Expand to an integer constant of specified value and type uintmax_t */
#define UINTMAX_C( value ) _PDCLIB_UINTMAX_C( value )
#endif
/* Annex K -- Bounds-checking interfaces */
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0
#define RSIZE_MAX ( _PDCLIB_SIZE_MAX >> 1 )
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STDINT_H
#include _PDCLIB_EXTEND_STDINT_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,935 @@
/* Input/output <stdio.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STDIO_H
#define _PDCLIB_STDIO_H _PDCLIB_STDIO_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_lib_ext1.h"
#include "pdclib/_PDCLIB_internal.h"
#ifndef _PDCLIB_SIZE_T_DEFINED
#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED
typedef _PDCLIB_size_t size_t;
#endif
#ifndef _PDCLIB_NULL_DEFINED
#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED
#define NULL _PDCLIB_NULL
#endif
/* See setvbuf(), third argument */
#define _IOFBF (1u<<0)
#define _IOLBF (1u<<1)
#define _IONBF (1u<<2)
/* The following are platform-dependent, and defined in _PDCLIB_config.h. */
typedef struct _PDCLIB_fpos_t fpos_t;
typedef struct _PDCLIB_file_t FILE;
#define EOF (-1)
#define BUFSIZ _PDCLIB_BUFSIZ
#define FOPEN_MAX _PDCLIB_FOPEN_MAX
#define FILENAME_MAX _PDCLIB_FILENAME_MAX
#define L_tmpnam _PDCLIB_L_tmpnam
#define TMP_MAX _PDCLIB_TMP_MAX
/* See fseek(), third argument */
#define SEEK_CUR _PDCLIB_SEEK_CUR
#define SEEK_END _PDCLIB_SEEK_END
#define SEEK_SET _PDCLIB_SEEK_SET
extern FILE * stdin;
extern FILE * stdout;
extern FILE * stderr;
/* Operations on files */
/* Remove the given file.
Returns zero if successful, non-zero otherwise.
This implementation does detect if a file of that name is currently open,
and fails the remove in this case. This does not detect two distinct names
that merely result in the same file (e.g. "/home/user/foo" vs. "~/foo").
*/
_PDCLIB_PUBLIC int remove( const char * filename );
/* Rename the given old file to the given new name.
Returns zero if successful, non-zero otherwise.
This implementation does detect if the old filename corresponds to an open
file, and fails the rename in this case.
If there already is a file with the new filename, behaviour is defined by
the glue code (see functions/_PDCLIB/rename.c).
*/
_PDCLIB_PUBLIC int rename( const char * oldpath, const char * newpath );
/* Open a temporary file with mode "wb+", i.e. binary-update. Remove the file
automatically if it is closed or the program exits normally (by returning
from main() or calling exit()).
Returns a pointer to a FILE handle for this file.
This implementation does not remove temporary files if the process aborts
abnormally (e.g. abort()).
*/
_PDCLIB_PUBLIC FILE * tmpfile( void );
/* Generate a file name that is not equal to any existing filename AT THE TIME
OF GENERATION. Generate a different name each time it is called.
Returns a pointer to an internal static buffer containing the filename if s
is a NULL pointer. (This is not thread-safe!)
Returns s if it is not a NULL pointer (s is then assumed to point to an array
of at least L_tmpnam characters).
Returns NULL if unable to generate a suitable name (because all possible
names already exist, or the function has been called TMP_MAX times already).
Note that this implementation cannot guarantee a file of the name generated
is not generated between the call to this function and a subsequent fopen().
*/
_PDCLIB_PUBLIC char * tmpnam( char * s );
/* File access functions */
/* Close the file associated with the given stream (after flushing its buffers).
Returns zero if successful, EOF if any errors occur.
*/
_PDCLIB_PUBLIC int fclose( FILE * stream );
/* Flush the buffers of the given output stream. If the stream is an input
stream, or an update stream with the last operation being an input operation,
behaviour is undefined.
If stream is a NULL pointer, perform the buffer flushing for all applicable
streams.
Returns zero if successful, EOF if a write error occurs.
Sets the error indicator of the stream if a write error occurs.
*/
_PDCLIB_PUBLIC int fflush( FILE * stream );
/* Open the file with the given filename in the given mode, and return a stream
handle for it in which error and end-of-file indicator are cleared. Defined
values for mode are:
READ MODES
text files binary files
without update "r" "rb"
with update "r+" "rb+" or "r+b"
Opening in read mode fails if no file with the given filename exists, or if
cannot be read.
WRITE MODES
text files binary files
without update "w" "wb"
with update "w+" "wb+" or "w+b"
With write modes, if a file with the given filename already exists, it is
truncated to zero length.
APPEND MODES
text files binary files
without update "a" "ab"
with update "a+" "ab+" or "a+b"
With update modes, if a file with the given filename already exists, it is
not truncated to zero length, but all writes are forced to end-of-file (this
regardless to fseek() calls). Note that binary files opened in append mode
might have their end-of-file padded with '\0' characters.
Update modes mean that both input and output functions can be performed on
the stream, but output must be terminated with a call to either fflush(),
fseek(), fsetpos(), or rewind() before input is performed, and input must
be terminated with a call to either fseek(), fsetpos(), or rewind() before
output is performed, unless input encountered end-of-file.
If a text file is opened with update mode, the implementation is at liberty
to open a binary stream instead. This implementation honors the exact mode
given.
The stream is fully buffered if and only if it can be determined not to
refer to an interactive device.
If the mode string begins with but is longer than one of the above sequences
the implementation is at liberty to ignore the additional characters, or do
implementation-defined things. This implementation only accepts the exact
modes above.
Returns a pointer to the stream handle if successfull, NULL otherwise.
*/
_PDCLIB_PUBLIC FILE * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode );
/* Close any file currently associated with the given stream. Open the file
identified by the given filename with the given mode (equivalent to fopen()),
and associate it with the given stream. If filename is a NULL pointer,
attempt to change the mode of the given stream.
This implementation allows any mode changes on "real" files, and associating
of the standard streams with files. It does *not* support mode changes on
standard streams.
(Primary use of this function is to redirect stdin, stdout, and stderr.)
Returns a pointer to the stream handle if successfull, NULL otherwise.
*/
_PDCLIB_PUBLIC FILE * freopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, FILE * _PDCLIB_restrict stream );
/* If buf is a NULL pointer, call setvbuf( stream, NULL, _IONBF, BUFSIZ ).
If buf is not a NULL pointer, call setvbuf( stream, buf, _IOFBF, BUFSIZ ).
*/
_PDCLIB_PUBLIC void setbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf );
/* Set the given stream to the given buffering mode. If buf is not a NULL
pointer, use buf as file buffer (of given size). If buf is a NULL pointer,
use a buffer of given size allocated internally. _IONBF causes unbuffered
behaviour, _IOLBF causes line-buffered behaviour, _IOFBF causes fully
buffered behaviour. Calling this function is only valid right after a file is
opened, and before any other operation (except for any unsuccessful calls to
setvbuf()) has been performed.
Returns zero if successful, nonzero otherwise.
*/
_PDCLIB_PUBLIC int setvbuf( FILE * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf, int mode, size_t size );
/* Formatted input/output functions */
/*
Write output to the given stream, as defined by the given format string and
0..n subsequent arguments (the argument stack).
The format string is written to the given stream verbatim, except for any
conversion specifiers included, which start with the letter '%' and are
documented below. If the given conversion specifiers require more arguments
from the argument stack than provided, behaviour is undefined. Additional
arguments not required by conversion specifiers are evaluated but otherwise
ignored.
(The standard specifies the format string is allowed to contain multibyte
character sequences as long as it starts and ends in initial shift state,
but this is not yet supported by this implementation, which interprets the
format string as sequence of char.)
TODO: Add multibyte support to printf() functions.
A conversion specifier consists of:
- Zero or more flags (one of the characters "-+ #0").
- Optional minimum field width as decimal integer. Default is padding to the
left, using spaces. Note that 0 is taken as a flag, not the beginning of a
field width. Note also that a small field width will not result in the
truncation of a value.
- Optional precision (given as ".#" with # being a decimal integer),
specifying:
- the min. number of digits to appear (diouxX),
- the max. number of digits after the decimal point (aAeEfF),
- the max. number of significant digits (gG),
- the max. number of bytes to be written (s).
- behaviour with other conversion specifiers is undefined.
- Optional length modifier specifying the size of the argument (one of "hh",
"ll", or one of the characters "hljztL").
- Conversion specifier character specifying the type of conversion to be
applied (and the type of the next argument from the argument stack). One
of the characters "diouxXfFeEgGaAcspn%".
Minimum field width and/or precision may be given as asterisk ('*') instead
of a decimal integer. In this case, the next argument from the argument
stack is assumed to be an int value specifying the width / precision. A
negative field width is interpreted as flag '-' followed by a positive field
width. A negative precision is interpreted as if no precision was given.
FLAGS
- Left-justify the conversion result within its field width.
+ Prefix a '+' on positive signed conversion results. Prefix a '-' on
floating conversions resulting in negative zero, or negative values
rounding to zero.
space Prefix a space on positive signed conversion results, or if a signed
conversion results in no characters. If both '+' and ' ' are given,
' ' is ignored.
# Use an "alternative form" for
- 'o' conversion, increasing precision until the first digit of the
result is a zero;
- 'x' or 'X' conversion, prefixing "0x" or "0X" to nonzero results;
- "aAeEfF" conversions, always printing a decimal point even if no
digits are following;
- 'g' or 'G' conversions, always printing a decimal point even if no
digits are following, and not removing trailing zeroes.
- behaviour for other conversions is unspecified.
0 Use leading zeroes instead of spaces for field width padding. If both
'-' and '0' are given, '0' is ignored. If a precision is specified for
any of the "diouxX" conversions, '0' is ignored. Behaviour is only
defined for "diouxXaAeEfFgG".
LENGTH MODIFIERS
hh For "diouxX" conversions, the argument from the argument stack is
assumed to be of char width. (It will have been subject to integer
promotion but will be converted back.) For 'n' conversions, the argument
is assumed to be a pointer to signed char.
h For "diouxX" conversions, the argument from the argument stack is
assumed to be of short int width. (It will have been subject to integer
promotion but will be converted back.) For 'n' conversions, the argument
is assumed to be a pointer to short int.
l For "diouxX" conversions, the argument from the argument stack is
assumed to be of long int width. For 'n' conversions, the argument is
assumed to be a pointer to short int. For 'c' conversions, the argument
is assumed to be a wint_t. For 's' conversions, the argument is assumed
to be a pointer to wchar_t. No effect on "aAeEfFgG" conversions.
ll For "diouxX" conversions, the argument from the argument stack is
assumed to be of long long int width. For 'n' conversions, the argument
is assumed to be a pointer to long long int.
j For "diouxX" conversions, the argument from the argument stack is
assumed to be of intmax_t width. For 'n' conversions, the argument is
assumed to be a pointer to intmax_t.
z For "diouxX" conversions, the argument from the argument stack is
assumed to be of size_t width. For 'n' conversions, the argument is
assumed to be a pointer to size_t.
t For "diouxX" conversions, the argument from the argument stack is
assumed to be of ptrdiff_t width. For 'n' conversions, the argument is
assumed to be a pointer to ptrdiff_t.
L For "aAeEfFgG" conversions, the argument from the argument stack is
assumed to be a long double.
Length modifiers appearing for any conversions not mentioned above will have
undefined behaviour.
If a length modifier appears with any conversion specifier other than as
specified above, the behavior is undefined.
CONVERSION SPECIFIERS
d,i The argument from the argument stack is assumed to be of type int, and
is converted to a signed decimal value with a minimum number of digits
as specified by the precision (default 1), padded with leading zeroes.
A zero value converted with precision zero yields no output.
o The argument from the argument stack is assumed to be of type unsigned
int, and is converted to an unsigned octal value, other behaviour being
as above.
u The argument from the argument stack is assumed to be of type unsigned
int, and converted to an unsigned decimal value, other behaviour being
as above.
x,X The argument from the argument stack is assumed to be of type unsigned
int, and converted to an unsigned hexadecimal value, using lowercase
"abcdef" for 'x' and uppercase "ABCDEF" for 'X' conversion, other
behaviour being as above.
f,F The argument from the argument stack is assumed to be of type double,
and converted to a decimal floating point in decimal-point notation,
with the number of digits after the decimal point as specified by the
precision (default 6) and the value being rounded appropriately. If
precision is zero (and the '#' flag is not given), no decimal point is
printed. At least one digit is always printed before the decimal point.
For 'f' conversions, an infinity value is printed as either [-]inf or
[-]infinity (, depending on the configuration of this implementation. A
NaN value is printed as [-]nan. For 'F' conversions uppercase characters
are used for these special values. The flags '-', '+' and ' ' apply as
usual to these special values, '#' and '0' have no effect.
e,E The argument from the argument stack is assumed to be of type double,
and converted to a decimal floating point in normalized exponential
notation ([?]d.ddd edd). "Normalized" means one nonzero digit before
the decimal point, unless the value is zero. The number of digits after
the decimal point is specified by the precision (default 6), the value
being rounded appropriately. If precision is zero (and the '#' flag is
not given), no decimal point is printed. The exponent has at least two
digits, and not more than necessary to represent the exponent. If the
value is zero, the exponent is zero. The 'e' written to indicate the
exponend is uppercase for 'E' conversions.
Infinity or NaN values are represented as for 'f' and 'F' conversions,
respectively.
g,G The argument from the argument stack is assumed to be of type double,
and converted according to either 'f' or 'e' format for 'g' conversions,
or 'F' or 'E' format for 'G' conversions, respectively, with the actual
conversion chosen depending on the value. 'e' / 'E' conversion is chosen
if the resulting exponent is < -4 or >= the precision (default 1).
Trailing zeroes are removed (unless the '#' flag is given). A decimal
point appears only if followed by a digit.
Infinity or NaN values are represented as for 'f' and 'F' conversions,
respectively.
a,A The argument from the argument stack is assumed to be of type double,
and converted to a floating point hexadecimal notation ([?]0xh.hhhh pd)
with one hexadecimal digit (being nonzero if the value is normalized,
and otherwise unspecified) before the decimal point, and the number of
digits after the decimal point being specified by the precision. If no
precision is given, the default is to print as many digits as nevessary
to give an exact representation of the value (if FLT_RADIX is a power of
2). If no precision is given and FLT_RADIX is not a power of 2, the
default is to print as many digits to distinguish values of type double
(possibly omitting trailing zeroes). (A precision p is sufficient to
distinguish values of the source type if 16^p-1 > b^n where b is
FLT_RADIX and n is the number of digits in the significand (to base b)
of the source type. A smaller p might suffice depending on the
implementation's scheme for determining the digit to the left of the
decimal point.) The error has the correct sign for the current rounding
direction.
Unless the '#' flag is given, no decimal-point is given for zero
precision.
The 'a' conversion uses lowercase "abcdef", "0x" and 'p', the 'A'
conversion uppercase "ABCDEF", "0X" and 'P'.
The exponent always has at least one digit, and not more than necessary
to represent the decimal exponent of 2. If the value is zero, the
exponent is zero.
Infinity or NaN values are represented as for 'f' and 'F' conversions,
respectively.
Binary implementations are at liberty to chose the hexadecimal digit to
the left of the decimal point so that subsequent digits align to nibble
boundaries.
c The argument from the argument stack is assumed to be of type int, and
converted to a character after the value has been cast to unsigned char.
If the 'l' length modifier is given, the argument is assumed to be of
type wint_t, and converted as by a "%ls" conversion with no precision
and a pointer to a two-element wchar_t array, with the first element
being the wint_t argument and the second a '\0' wide character.
s The argument from the argument stack is assumed to be a char array (i.e.
pointer to char). Characters from that array are printed until a zero
byte is encountered or as many bytes as specified by a given precision
have been written.
If the l length modifier is given, the argument from the argument stack
is assumed to be a wchar_t array (i.e. pointer to wchar_t). Wide
characters from that array are converted to multibyte characters as by
calls to wcrtomb() (using a mbstate_t object initialized to zero prior
to the first conversion), up to and including the terminating null wide
character. The resulting multibyte character sequence is then printed up
to but not including the terminating null character. If a precision is
given, it specifies the maximum number of bytes to be written (including
shift sequences). If the given precision would require access to a wide
character one past the end of the array, the array shall contain a '\0'
wide character. In no case is a partial multibyte character written.
Redundant shift sequences may result if the multibyte characters have a
state-dependent encoding.
TODO: Clarify these statements regarding %ls.
p The argument from the argument stack is assumed to be a void pointer,
and converted to a sequence of printing characters in an implementation-
defined manner.
This implementation casts the pointer to type intptr_t, and prints the
value as if a %#x conversion specifier was given.
n The argument from the argument stack is assumed to be a pointer to a
signed integer, into which the number of characters written so far by
this call to fprintf is stored. The behaviour, should any flags, field
widths, or precisions be given is undefined.
% A verbatim '%' character is written. No argument is taken from the
argument stack.
Returns the number of characters written if successful, a negative value
otherwise.
*/
_PDCLIB_PUBLIC int fprintf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... );
/* TODO: fscanf() documentation */
/*
Read input from a given stream, as defined by the given format string, and
store converted input in the objects pointed to by 0..n subsequent arguments
(the argument stack).
The format string contains a sequence of directives that are expected to
match the input. If such a directive fails to match, the function returns
(matching error). It also returns if an input error occurs (input error).
Directives can be:
- one or more whitespaces, matching any number of whitespaces in the input;
- printing characters, matching the input verbatim;
- conversion specifications, which convert an input sequence into a value as
defined by the individual specifier, and store that value in a memory
location pointed to by the next pointer on the argument stack. Details are
documented below. If there is an insufficient number of pointers on the
argument stack, behaviour is undefined. Additional arguments not required
by any conversion specifications are evaluated, but otherwise ignored.
(The standard specifies the format string is allowed to contain multibyte
character sequences as long as it starts and ends in initial shift state,
but this is not yet supported by this implementation, which interprets the
format string as sequence of char.)
TODO: Add multibyte support to scanf() functions.
A conversion specifier consists of:
- Optional assignment-suppressing character ('*') that makes the conversion
read input as usual, but does not assign the conversion result.
- Optional maximum field width as decimal integer.
- Optional length modifier specifying the size of the argument (one of "hh",
"ll", or one of the characters "hljztL").
- Conversion specifier character specifying the type of conversion to be
applied (and the type of the next argument from the argument stack). One
of the characters "diouxXaAeEfFgGcs[pn%".
LENGTH MODIFIERS
hh For "diouxXn" conversions, the next pointer from the argument stack is
assumed to point to a variable of of char width.
h For "diouxXn" conversions, the next pointer from the argument stack is
assumed to point to a variable of short int width.
l For "diouxXn" conversions, the next pointer from the argument stack is
assumed to point to a variable of long int width.
For "aAeEfFgG" conversions, it is assumed to point to a variable of type
double.
For "cs[" conversions, it is assumed to point to a variable of type
wchar_t.
ll For "diouxXn" conversions, the next pointer from the argument stack is
assumed to point to a variable of long long int width.
j For "diouxXn" conversions, the next pointer from the argument stack is
assumed to point to a variable of intmax_t width.
z For "diouxXn" conversions, the next pointer from the argument stack is
assumed to point to a variable of size_t width.
t For "diouxXn" conversions, the next pointer from the argument stack is
assumed to point to a variable of ptrdiff_t width.
L For "aAeEfFgG" conversions, the next pointer from the argument stack is
assumed to point to a variable of type long double.
Length modifiers appearing for any conversions not mentioned above will have
undefined behaviour.
If a length modifier appears with any conversion specifier other than as
specified above, the behavior is undefined.
CONVERSION SPECIFIERS
d Matches an (optionally signed) decimal integer of the format expected
by strtol() with base 10. The next pointer from the argument stack is
assumed to point to a signed integer.
i Matches an (optionally signed) integer of the format expected by
strtol() with base 0. The next pointer from the argument stack is
assumed to point to a signed integer.
o Matches an (optionally signed) octal integer of the format expected by
strtoul() with base 8. The next pointer from the argument stack is
assumed to point to an unsigned integer.
u Matches an (optionally signed) decimal integer of the format expected
by strtoul() with base 10. The next pointer from the argument stack is
assumed to point to an unsigned integer.
x Matches an (optionally signed) hexadecimal integer of the format
expected by strtoul() with base 16. The next pointer from the argument
stack is assumed to point to an unsigned integer.
aefg Matches an (optionally signed) floating point number, infinity, or not-
a-number-value of the format expected by strtod(). The next pointer
from the argument stack is assumed to point to a float.
c Matches a number of characters as specified by the field width (default
1). The next pointer from the argument stack is assumed to point to a
character array large enough to hold that many characters.
If the 'l' length modifier is given, the input is assumed to match a
sequence of multibyte characters (starting in the initial shift state),
which will be converted to a wide character sequence as by successive
calls to mbrtowc() with a mbstate_t object initialized to zero prior to
the first conversion. The next pointer from the argument stack is
assumed to point to a wchar_t array large enough to hold that many
characters.
In either case, note that no '\0' character is added to terminate the
sequence.
s Matches a sequence of non-white-space characters. The next pointer from
the argument stack is assumed to point to a character array large
enough to hold the sequence including terminating '\0' character.
If the 'l' length modifier is given, the input is assumed to match a
sequence of multibyte characters (starting in the initial shift state),
which will be converted to a wide character sequence as by a call to
mbrtowc() with a mbstate_t object initialized to zero prior to the
first conversion. The next pointer from the argument stack is assumed
to point to a wchar_t array large enough to hold the sequence including
terminating '\0' character.
[ Matches a nonempty sequence consisting of any of those characters
specified between itself and a corresponding closing bracket (']').
If the first character in the list is a circumflex ('^'), this matches
a nonempty sequence consisting of any characters NOT specified. If the
closing bracket appears as the first character in the scanset ("[]" or
"[^]", it is assumed to belong to the scanset, which then ends with the
NEXT closing bracket.
If there is a '-' character in the scanset which is not the first after
the opening bracket (or the circumflex, see above) or the last in the
scanset, behaviour is implementation-defined. This implementation
handles this character like any other.
The extend of the input field is determined byte-by-byte for the above
conversions ('c', 's', '['), with no special provisions being made for
multibyte characters. The resulting field is nevertheless a multibyte
sequence begining in intial shift state.
p Matches a sequence of characters as produced by the printf() "%p"
conversion. The next pointer from the argument stack is assumed to
point to a void pointer, which will be filled with the same location
as the pointer used in the printf() statement. Note that behaviour is
undefined if the input value is not the result of an earlier printf()
call.
n Does not read input. The next pointer from the argument stack is
assumed to point to a signed integer, into which the number of
characters read from input so far by this call to fscanf() is stored.
This does not affect the return value of fscanf(). The behaviour,
should an assignment-supressing character of field width be given,
is undefined.
This can be used to test the success of literal matches and suppressed
assignments.
% Matches a single, verbatim '%' character.
A, E, F, G and X are valid, and equivalent to their lowercase counterparts.
All conversions except [, c, or n imply that whitespace characters from the
input stream are consumed until a non-whitespace character is encountered.
Such whitespaces do not count against a maximum field width.
Conversions push at most one character back into the input stream. That
implies that some character sequences converted by the strtol() and strtod()
function families are not converted identically by the scnaf() function
family.
Returns the number of input items successfully assigned. This can be zero if
an early mismatch occurs. Returns EOF if an input failure occurs before the
first conversion.
*/
_PDCLIB_PUBLIC int fscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... );
/* Equivalent to fprintf( stdout, format, ... ). */
_PDCLIB_PUBLIC int printf( const char * _PDCLIB_restrict format, ... );
/* Equivalent to fscanf( stdin, format, ... ). */
_PDCLIB_PUBLIC int scanf( const char * _PDCLIB_restrict format, ... );
/* Equivalent to fprintf( stdout, format, ... ), except that the result is
written into the buffer pointed to by s, instead of stdout, and that any
characters beyond the (n-1)th are discarded. The (n)th character is
replaced by a '\0' character in this case.
Returns the number of characters that would have been written (not counting
the terminating '\0' character) if n had been sufficiently large, if
successful, and a negative number if an encoding error ocurred.
*/
_PDCLIB_PUBLIC int snprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_restrict format, ... );
/* Equivalent to fprintf( stdout, format, ... ), except that the result is
written into the buffer pointed to by s, instead of stdout.
*/
_PDCLIB_PUBLIC int sprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... );
/* Equivalent to fscanf( stdin, format, ... ), except that the input is read
from the buffer pointed to by s, instead of stdin.
*/
_PDCLIB_PUBLIC int sscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... );
/* Equivalent to fprintf( stream, format, ... ), except that the argument stack
is passed as va_list parameter. Note that va_list is not declared by
<stdio.h>.
*/
_PDCLIB_PUBLIC int vfprintf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
/* Equivalent to fscanf( stream, format, ... ), except that the argument stack
is passed as va_list parameter. Note that va_list is not declared by
<stdio.h>.
*/
_PDCLIB_PUBLIC int vfscanf( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
/* Equivalent to fprintf( stdout, format, ... ), except that the argument stack
is passed as va_list parameter. Note that va_list is not declared by
<stdio.h>.
*/
_PDCLIB_PUBLIC int vprintf( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
/* Equivalent to fscanf( stdin, format, ... ), except that the argument stack
is passed as va_list parameter. Note that va_list is not declared by
<stdio.h>.
*/
_PDCLIB_PUBLIC int vscanf( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
/* Equivalent to snprintf( s, n, format, ... ), except that the argument stack
is passed as va_list parameter. Note that va_list is not declared by
<stdio.h>.
*/
_PDCLIB_PUBLIC int vsnprintf( char * _PDCLIB_restrict s, size_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
/* Equivalent to fprintf( stdout, format, ... ), except that the argument stack
is passed as va_list parameter, and the result is written to the buffer
pointed to by s, instead of stdout. Note that va_list is not declared by
<stdio.h>.
*/
_PDCLIB_PUBLIC int vsprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
/* Equivalent to fscanf( stdin, format, ... ), except that the argument stack
is passed as va_list parameter, and the input is read from the buffer
pointed to by s, instead of stdin. Note that va_list is not declared by
<stdio.h>.
*/
_PDCLIB_PUBLIC int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
/* Character input/output functions */
/* Retrieve the next character from given stream.
Returns the character, EOF otherwise.
If end-of-file is reached, the EOF indicator of the stream is set.
If a read error occurs, the error indicator of the stream is set.
*/
_PDCLIB_PUBLIC int fgetc( FILE * stream );
/* Read at most n-1 characters from given stream into the array s, stopping at
\n or EOF. Terminate the read string with \n. If EOF is encountered before
any characters are read, leave the contents of s unchanged.
Returns s if successful, NULL otherwise.
If a read error occurs, the error indicator of the stream is set. In this
case, the contents of s are indeterminate.
*/
_PDCLIB_PUBLIC char * fgets( char * _PDCLIB_restrict s, int n, FILE * _PDCLIB_restrict stream );
/* Write the value c (cast to unsigned char) to the given stream.
Returns c if successful, EOF otherwise.
If a write error occurs, sets the error indicator of the stream is set.
*/
_PDCLIB_PUBLIC int fputc( int c, FILE * stream );
/* Write the string s (not including the terminating \0) to the given stream.
Returns a value >=0 if successful, EOF otherwise.
This implementation does set the error indicator of the stream if a write
error occurs.
*/
_PDCLIB_PUBLIC int fputs( const char * _PDCLIB_restrict s, FILE * _PDCLIB_restrict stream );
/* Equivalent to fgetc( stream ), but may be overloaded by a macro that
evaluates its parameter more than once.
*/
_PDCLIB_PUBLIC int getc( FILE * stream );
/* Equivalent to fgetc( stdin ). */
_PDCLIB_PUBLIC int getchar( void );
/* Equivalent to fputc( c, stream ), but may be overloaded by a macro that
evaluates its parameter more than once.
*/
_PDCLIB_PUBLIC int putc( int c, FILE * stream );
/* Equivalent to fputc( c, stdout ), but may be overloaded by a macro that
evaluates its parameter more than once.
*/
_PDCLIB_PUBLIC int putchar( int c );
/* Write the string s (not including the terminating \0) to stdout, and append
a newline to the output. Returns a value >= 0 when successful, EOF if a
write error occurred.
*/
_PDCLIB_PUBLIC int puts( const char * s );
/* Push the value c (cast to unsigned char) back onto the given (input) stream.
A character pushed back in this way will be delivered by subsequent read
operations (and skipped by subsequent file positioning operations) as if it
has not been read. The external representation of the stream is unaffected
by this pushback (it is a buffer operation). One character of pushback is
guaranteed, further pushbacks may fail. EOF as value for c does not change
the input stream and results in failure of the function.
For text files, the file position indicator is indeterminate until all
pushed-back characters are read. For binary files, the file position
indicator is decremented by each successful call of ungetc(). If the file
position indicator for a binary file was zero before the call of ungetc(),
behaviour is undefined. (Older versions of the library allowed such a call.)
Returns the pushed-back character if successful, EOF if it fails.
*/
_PDCLIB_PUBLIC int ungetc( int c, FILE * stream );
/* Direct input/output functions */
/* Read up to nmemb elements of given size from given stream into the buffer
pointed to by ptr. Returns the number of elements successfully read, which
may be less than nmemb if a read error or EOF is encountered. If a read
error is encountered, the value of the file position indicator is
indeterminate. If a partial element is read, its value is indeterminate.
If size or nmemb are zero, the function does nothing and returns zero.
*/
_PDCLIB_PUBLIC size_t fread( void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, FILE * _PDCLIB_restrict stream );
/* Write up to nmemb elements of given size from buffer pointed to by ptr to
the given stream. Returns the number of elements successfully written, which
will be less than nmemb only if a write error is encountered. If a write
error is encountered, the value of the file position indicator is
indeterminate. If size or nmemb are zero, the function does nothing and
returns zero.
*/
_PDCLIB_PUBLIC size_t fwrite( const void * _PDCLIB_restrict ptr, size_t size, size_t nmemb, FILE * _PDCLIB_restrict stream );
/* File positioning functions */
/* Store the current position indicator (and, where appropriate, the current
mbstate_t status object) for the given stream into the given pos object. The
actual contents of the object are unspecified, but it can be used as second
parameter to fsetpos() to reposition the stream to the exact position and
parse state at the time fgetpos() was called.
Returns zero if successful, nonzero otherwise.
TODO: Implementation-defined errno setting for fgetpos().
*/
_PDCLIB_PUBLIC int fgetpos( FILE * _PDCLIB_restrict stream, fpos_t * _PDCLIB_restrict pos );
/* Set the position indicator for the given stream to the given offset from:
- the beginning of the file if whence is SEEK_SET,
- the current value of the position indicator if whence is SEEK_CUR,
- end-of-file if whence is SEEK_END.
On text streams, non-zero offsets are only allowed with SEEK_SET, and must
have been returned by ftell() for the same file.
Any characters buffered by ungetc() are dropped, the end-of-file indicator
for the stream is cleared. If the given stream is an update stream, the next
operation after a successful fseek() may be either input or output.
Returns zero if successful, nonzero otherwise. If a read/write error occurs,
the error indicator for the given stream is set.
*/
_PDCLIB_PUBLIC int fseek( FILE * stream, long int offset, int whence );
/* Set the position indicator (and, where appropriate the mbstate_t status
object) for the given stream to the given pos object (created by an earlier
call to fgetpos() on the same file).
Any characters buffered by ungetc() are dropped, the end-of-file indicator
for the stream is cleared. If the given stream is an update stream, the next
operation after a successful fsetpos() may be either input or output.
Returns zero if successful, nonzero otherwise. If a read/write error occurs,
the error indicator for the given stream is set.
TODO: Implementation-defined errno setting for fsetpos().
*/
_PDCLIB_PUBLIC int fsetpos( FILE * stream, const fpos_t * pos );
/* Return the current offset of the given stream from the beginning of the
associated file. For text streams, the exact value returned is unspecified
(and may not be equal to the number of characters), but may be used in
subsequent calls to fseek().
Returns -1L if unsuccessful.
TODO: Implementation-defined errno setting for ftell().
*/
_PDCLIB_PUBLIC long int ftell( FILE * stream );
/* Equivalent to (void)fseek( stream, 0L, SEEK_SET ), except that the error
indicator for the stream is also cleared.
*/
_PDCLIB_PUBLIC void rewind( FILE * stream );
/* Error-handling functions */
/* Clear the end-of-file and error indicators for the given stream. */
_PDCLIB_PUBLIC void clearerr( FILE * stream );
/* Return zero if the end-of-file indicator for the given stream is not set,
nonzero otherwise.
*/
_PDCLIB_PUBLIC int feof( FILE * stream );
/* Return zero if the error indicator for the given stream is not set, nonzero
otherwise.
*/
_PDCLIB_PUBLIC int ferror( FILE * stream );
/* If s is neither a NULL pointer nor an empty string, print the string to
stderr (with appended colon (':') and a space) first. In any case, print an
error message depending on the current value of errno (being the same as if
strerror( errno ) had been called).
*/
_PDCLIB_PUBLIC void perror( const char * s );
/* Annex K -- Bounds-checking interfaces */
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0
#define L_tmpnam_s _PDCLIB_L_tmpnam
#define TMP_MAX_S _PDCLIB_TMP_MAX
#ifndef _PDCLIB_ERRNO_T_DEFINED
#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED
typedef int errno_t;
#endif
#ifndef _PDCLIB_RSIZE_T_DEFINED
#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED
typedef _PDCLIB_size_t rsize_t;
#endif
/* Open a temporary file with mode "wb+", i.e. binary-update. Remove the file
automatically if it is closed or the program exits normally (by returning
from main() or calling exit()).
If successful, the FILE * pointed to by streamptr will be set to point at
the opened file handle, and the function returns zero. If unsuccessful,
the FILE * pointed to by streamptr will be set to NULL and a non-zero
value is returned.
The following conditions will be considered runtime constraint violations:
- streamptr being NULL.
In case of a constraint violation, no file is being created.
This implementation does not remove temporary files if the process aborts
abnormally (e.g. abort()).
*/
_PDCLIB_PUBLIC errno_t tmpfile_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict streamptr );
/* Open the file with the given filename in the given mode, and sets the given
streamptr to point at the file handle for that file, in which error and
end-of-file indicator are cleared. Defined values for mode are:
READ MODES
text files binary files
without update "r" "rb"
with update "r+" "rb+" or "r+b"
Opening in read mode fails if no file with the given filename exists, or if
cannot be read.
WRITE MODES
text files binary files
without update "w" "wb"
with update "w+" "wb+" or "w+b"
With write modes, if a file with the given filename already exists, it is
truncated to zero length.
APPEND MODES
text files binary files
without update "a" "ab"
with update "a+" "ab+" or "a+b"
With update modes, if a file with the given filename already exists, it is
not truncated to zero length, but all writes are forced to end-of-file (this
regardless to fseek() calls). Note that binary files opened in append mode
might have their end-of-file padded with '\0' characters.
Update modes mean that both input and output functions can be performed on
the stream, but output must be terminated with a call to either fflush(),
fseek(), fsetpos(), or rewind() before input is performed, and input must
be terminated with a call to either fseek(), fsetpos(), or rewind() before
output is performed, unless input encountered end-of-file.
If a text file is opened with update mode, the implementation is at liberty
to open a binary stream instead. This implementation honors the exact mode
given.
The stream is fully buffered if and only if it can be determined not to
refer to an interactive device.
If the mode string begins with but is longer than one of the above sequences
the implementation is at liberty to ignore the additional characters, or do
implementation-defined things. This implementation only accepts the exact
modes above.
The following conditions will be considered runtime constraint violations:
- streamptr being NULL.
- filename being NULL.
- mode being NULL.
In case of a constraint violation, no file is opened. If streamptr is not
NULL, *streamptr is set to NULL.
Returns zero if successful, non-zero otherwise.
*/
_PDCLIB_PUBLIC errno_t fopen_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict streamptr, const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode );
/* Close any file currently associated with the given stream. Open the file
identified by the given filename with the given mode (equivalent to fopen()),
and associate it with the given stream. If filename is a NULL pointer,
attempt to change the mode of the given stream.
This implementation allows any mode changes on "real" files, and associating
of the standard streams with files. It does *not* support mode changes on
standard streams.
(Primary use of this function is to redirect stdin, stdout, and stderr.)
The following conditions will be considered runtime constraint violations:
- newstreamptr being NULL.
- mode being NULL.
- stream being NULL.
In case of a constraint violation, no attempt is made to close or open any
file. If newstreamptr is not NULL, *newstreamptr is set to NULL.
Returns zero if successfull, non-zero otherwise.
*/
_PDCLIB_PUBLIC errno_t freopen_s( FILE * _PDCLIB_restrict * _PDCLIB_restrict newstreamptr, const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode, FILE * _PDCLIB_restrict stream );
/* None of these are implemented yet. Placeholder declarations. */
_PDCLIB_PUBLIC errno_t tmpnam_s( char * s, rsize_t maxsize );
_PDCLIB_PUBLIC int fprintf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... );
_PDCLIB_PUBLIC int fscanf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, ... );
_PDCLIB_PUBLIC int printf_s( const char * _PDCLIB_restrict format, ... );
_PDCLIB_PUBLIC int scanf_s( const char * _PDCLIB_restrict format, ... );
_PDCLIB_PUBLIC int snprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, ... );
_PDCLIB_PUBLIC int sprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, ... );
_PDCLIB_PUBLIC int sscanf_s( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, ... );
_PDCLIB_PUBLIC int vfprintf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
_PDCLIB_PUBLIC int vfscanf_s( FILE * _PDCLIB_restrict stream, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
_PDCLIB_PUBLIC int vprintf_s( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
_PDCLIB_PUBLIC int vscanf_s( const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
_PDCLIB_PUBLIC int vsnprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
_PDCLIB_PUBLIC int vsprintf_s( char * _PDCLIB_restrict s, rsize_t n, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
_PDCLIB_PUBLIC int vsscanf_s( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg );
_PDCLIB_PUBLIC char * gets_s( char * s, rsize_t n );
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STDIO_H
#include _PDCLIB_EXTEND_STDIO_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,379 @@
/* General utilities <stdlib.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STDLIB_H
#define _PDCLIB_STDLIB_H _PDCLIB_STDLIB_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_lib_ext1.h"
#include "pdclib/_PDCLIB_internal.h"
#ifndef _PDCLIB_SIZE_T_DEFINED
#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED
typedef _PDCLIB_size_t size_t;
#endif
#ifndef _PDCLIB_NULL_DEFINED
#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED
#define NULL _PDCLIB_NULL
#endif
/* Numeric conversion functions */
/* TODO: atof(), strtof(), strtod(), strtold() */
_PDCLIB_PUBLIC double atof( const char * nptr );
_PDCLIB_PUBLIC double strtod( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr );
_PDCLIB_PUBLIC float strtof( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr );
_PDCLIB_PUBLIC long double strtold( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr );
/* Separate the character array nptr into three parts: A (possibly empty)
sequence of whitespace characters, a character representation of an integer
to the given base, and trailing invalid characters (including the terminating
null character). If base is 0, assume it to be 10, unless the integer
representation starts with 0x / 0X (setting base to 16) or 0 (setting base to
8). If given, base can be anything from 0 to 36, using the 26 letters of the
base alphabet (both lowercase and uppercase) as digits 10 through 35.
The integer representation is then converted into the return type of the
function. It can start with a '+' or '-' sign. If the sign is '-', the result
of the conversion is negated.
If the conversion is successful, the converted value is returned. If endptr
is not a NULL pointer, a pointer to the first trailing invalid character is
returned in *endptr.
If no conversion could be performed, zero is returned (and nptr in *endptr,
if endptr is not a NULL pointer). If the converted value does not fit into
the return type, the functions return LONG_MIN, LONG_MAX, ULONG_MAX,
LLONG_MIN, LLONG_MAX, or ULLONG_MAX respectively, depending on the sign of
the integer representation and the return type, and errno is set to ERANGE.
*/
/* There is strtoimax() and strtoumax() in <inttypes.h> operating on intmax_t /
uintmax_t, if the long long versions do not suit your needs.
*/
_PDCLIB_PUBLIC long int strtol( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base );
_PDCLIB_PUBLIC long long int strtoll( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base );
_PDCLIB_PUBLIC unsigned long int strtoul( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base );
_PDCLIB_PUBLIC unsigned long long int strtoull( const char * _PDCLIB_restrict nptr, char ** _PDCLIB_restrict endptr, int base );
/* These functions are the equivalent of (int)strtol( nptr, NULL, 10 ),
strtol( nptr, NULL, 10 ) and strtoll(nptr, NULL, 10 ) respectively, with the
exception that they do not have to handle overflow situations in any defined
way.
(PDCLib does not simply forward these to their strtox() equivalents, but
provides a simpler atox() function that saves a couple of tests and simply
continues with the conversion in case of overflow.)
*/
_PDCLIB_PUBLIC int atoi( const char * nptr );
_PDCLIB_PUBLIC long int atol( const char * nptr );
_PDCLIB_PUBLIC long long int atoll( const char * nptr );
/* Pseudo-random sequence generation functions */
extern unsigned long int _PDCLIB_seed;
#define RAND_MAX 32767
/* Returns the next number in a pseudo-random sequence, which is between 0 and
RAND_MAX.
(PDCLib uses the implementation suggested by the standard document, which is
next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % 32768;)
*/
_PDCLIB_PUBLIC int rand( void );
/* Initialize a new pseudo-random sequence with the starting seed. Same seeds
result in the same pseudo-random sequence. The default seed is 1.
*/
_PDCLIB_PUBLIC void srand( unsigned int seed );
/* Memory management functions */
/* Allocate a chunk of heap memory of given size. If request could not be
satisfied, return NULL. Otherwise, return a pointer to the allocated
memory. Memory contents are undefined.
*/
_PDCLIB_PUBLIC void * malloc( size_t size );
/* Allocate a chunk of heap memory that is large enough to hold nmemb elements
of the given size, and zero-initialize that memory. If request could not be
satisfied, return NULL. Otherwise, return a pointer to the allocated
memory.
*/
_PDCLIB_PUBLIC void * calloc( size_t nmemb, size_t size );
/* De-allocate a chunk of heap memory previously allocated using malloc(),
calloc(), or realloc(), and pointed to by ptr. If ptr does not match a
pointer previously returned by the mentioned allocation functions, or
free() has already been called for this ptr, behaviour is undefined.
*/
_PDCLIB_PUBLIC void free( void * ptr );
/* Resize a chunk of memory previously allocated with malloc() and pointed to
by ptr to the given size (which might be larger or smaller than the original
size). Returns a pointer to the reallocated memory, or NULL if the request
could not be satisfied. Note that the resizing might include a memcpy()
from the original location to a different one, so the return value might or
might not equal ptr. If size is larger than the original size, the value of
memory beyond the original size is undefined. If ptr is NULL, realloc()
behaves like malloc().
*/
_PDCLIB_PUBLIC void * realloc( void * ptr, size_t size );
/* Communication with the environment */
/* These two can be passed to exit() or _Exit() as status values, to signal
successful and unsuccessful program termination, respectively. EXIT_SUCCESS
can be replaced by 0. How successful or unsuccessful program termination are
signaled to the environment, and what happens if exit() or _Exit() are being
called with a value that is neither of the three, is defined by the hosting
OS and its glue function.
*/
#define EXIT_SUCCESS _PDCLIB_SUCCESS
#define EXIT_FAILURE _PDCLIB_FAILURE
/* Initiate abnormal process termination, unless programm catches SIGABRT and
does not return from the signal handler.
This implementantion flushes all streams, closes all files, and removes any
temporary files before exiting with EXIT_FAILURE.
abort() does not return.
*/
_PDCLIB_PUBLIC _PDCLIB_Noreturn void abort( void ) _PDCLIB_NORETURN;
/* Register a function that will be called on quick_exit().
At least 32 functions can be registered this way, and will be called in
reverse order of registration (last-in, first-out).
Returns zero if registration is successfull, nonzero if it failed.
*/
_PDCLIB_PUBLIC int at_quick_exit( void ( *func )( void ) );
/* Register a function that will be called on exit(), or when main() returns.
At least 32 functions can be registered this way, and will be called in
reverse order of registration (last-in, first-out).
Returns zero if registration is successfull, nonzero if it failed.
*/
_PDCLIB_PUBLIC int atexit( void ( *func )( void ) );
/* Normal process termination. Functions registered by atexit() (see above) are
called, streams flushed, files closed and temporary files removed before the
program is terminated with the given status. (See comment for EXIT_SUCCESS
and EXIT_FAILURE above.)
exit() does not return.
*/
_PDCLIB_PUBLIC _PDCLIB_Noreturn void exit( int status ) _PDCLIB_NORETURN;
/* Normal process termination. Functions registered by at_quick_exit() (see
above) are called, streams flushed, files closed and temporary files removed
before the program is terminated with the given status. (See comment for
EXIT_SUCCESS and EXIT_FAILURE above.)
quick_exit() does not return.
*/
_PDCLIB_PUBLIC _PDCLIB_Noreturn void quick_exit( int status ) _PDCLIB_NORETURN;
/* Normal process termination. Functions registered by atexit()/at_quick_exit()
(see above) are NOT CALLED. This implementation DOES flush streams, close
files and removes temporary files before the program is teminated with the
given status. (See comment for EXIT_SUCCESS and EXIT_FAILURE above.)
_Exit() does not return.
*/
_PDCLIB_PUBLIC _PDCLIB_Noreturn void _Exit( int status ) _PDCLIB_NORETURN;
/* Search an environment-provided key-value map for the given key name, and
return a pointer to the associated value string (or NULL if key name cannot
be found). The value string pointed to might be overwritten by a subsequent
call to getenv(). The library never calls getenv() itself.
Details on the provided keys and how to set / change them are determined by
the hosting OS and its glue function.
*/
_PDCLIB_PUBLIC char * getenv( const char * name );
/* If string is a NULL pointer, system() returns nonzero if a command processor
is available, and zero otherwise. If string is not a NULL pointer, it is
passed to the command processor. If system() returns, it does so with a
value that is determined by the hosting OS and its glue function.
*/
_PDCLIB_PUBLIC int system( const char * string );
/* Searching and sorting */
/* Do a binary search for a given key in the array with a given base pointer,
which consists of nmemb elements that are of the given size each. To compare
the given key with an element from the array, the given function compar is
called (with key as first parameter and a pointer to the array member as
second parameter); the function should return a value less than, equal to,
or greater than 0 if the key is considered to be less than, equal to, or
greater than the array element, respectively.
The function returns a pointer to a matching element found, or NULL if no
match is found.
*/
_PDCLIB_PUBLIC void * bsearch( const void * key, const void * base, size_t nmemb, size_t size, int ( *compar )( const void *, const void * ) );
/* Do a quicksort on an array with a given base pointer, which consists of
nmemb elements that are of the given size each. To compare two elements from
the array, the given function compar is called, which should return a value
less than, equal to, or greater than 0 if the first argument is considered
to be less than, equal to, or greater than the second argument, respectively.
If two elements are compared equal, their order in the sorted array is not
specified.
*/
_PDCLIB_PUBLIC void qsort( void * base, size_t nmemb, size_t size, int ( *compar )( const void *, const void * ) );
/* Integer arithmetic functions */
/* Return the absolute value of the argument. Note that on machines using two-
complement's notation (most modern CPUs), the largest negative value cannot
be represented as positive value. In this case, behaviour is unspecified.
*/
_PDCLIB_PUBLIC int abs( int j );
_PDCLIB_PUBLIC long int labs( long int j );
_PDCLIB_PUBLIC long long int llabs( long long int j );
/* These structures each have a member quot and a member rem, of type int (for
div_t), long int (for ldiv_t) and long long it (for lldiv_t) respectively.
The order of the members is platform-defined to allow the div() functions
below to be implemented efficiently.
*/
typedef struct _PDCLIB_div_t div_t;
typedef struct _PDCLIB_ldiv_t ldiv_t;
typedef struct _PDCLIB_lldiv_t lldiv_t;
/* Return quotient (quot) and remainder (rem) of an integer division in one of
the structs above.
*/
_PDCLIB_PUBLIC div_t div( int numer, int denom );
_PDCLIB_PUBLIC ldiv_t ldiv( long int numer, long int denom );
_PDCLIB_PUBLIC lldiv_t lldiv( long long int numer, long long int denom );
/* TODO: Multibyte / wide character conversion functions */
/* TODO: Macro MB_CUR_MAX */
/*
_PDCLIB_PUBLIC int mblen( const char * s, size_t n );
_PDCLIB_PUBLIC int mbtowc( wchar_t * _PDCLIB_restrict pwc, const char * _PDCLIB_restrict s, size_t n );
_PDCLIB_PUBLIC int wctomb( char * s, wchar_t wc );
_PDCLIB_PUBLIC size_t mbstowcs( wchar_t * _PDCLIB_restrict pwcs, const char * _PDCLIB_restrict s, size_t n );
_PDCLIB_PUBLIC size_t wcstombs( char * _PDCLIB_restrict s, const wchar_t * _PDCLIB_restrict pwcs, size_t n );
*/
/* Annex K -- Bounds-checking interfaces */
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0
#ifndef _PDCLIB_ERRNO_T_DEFINED
#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED
typedef int errno_t;
#endif
#ifndef _PDCLIB_RSIZE_T_DEFINED
#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED
typedef size_t rsize_t;
#endif
/* A function type that can serve as a constraint handler (see below). The
first parameter is an error message on the constraint violation, the
second parameter a pointer to an implementation-defined object, the
third an error code related to the constraint violation.
If the function calling the constraint handler is defined to return
errno_t, the third parameter will be identical to the return value of
that function.
This implementation sets the second parameter of the constraint handler
call to NULL.
*/
typedef void ( *constraint_handler_t )( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error );
/* The currently active constraint violation handler. This implementation
sets abort_handler_s as the default constraint violation handler.
*/
extern constraint_handler_t _PDCLIB_constraint_handler;
/* Set the given function as the new constraint violation handler. */
_PDCLIB_PUBLIC constraint_handler_t set_constraint_handler_s( constraint_handler_t handler );
/* One of two predefined constraint violation handlers. When called, it will
print an error message (including the message passed as the first
parameter to the handler function) and call abort().
*/
_PDCLIB_PUBLIC void abort_handler_s( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error );
/* One of two predefined constraint violation handlers. Simply returns,
ignoring the constraint violation.
*/
_PDCLIB_PUBLIC void ignore_handler_s( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error );
/* Search an environment-provided key-value map for the given key name.
If the name is found,
- if len is not NULL, the length of the associated value string is stored
in that location.
- if len < maxsize, the value string is copied to the indicated location.
If the name is not found,
- if len is not NULL, a zero is stored in that location.
- if maxsize > 0, value[0] is set to the null character.
Details on the provided keys and how to set / change them are determined by
the hosting OS and its glue function.
The following conditions will be considered runtime constraint violations:
- value being a NULL pointer.
- maxsize == 0 or maxsize > RSIZE_MAX.
In case of a constraint violation, if len is not NULL a zero will be
stored at that location, and the environment key-value map not searched.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t getenv_s( size_t * _PDCLIB_restrict len, char * _PDCLIB_restrict value, rsize_t maxsize, const char * _PDCLIB_restrict name );
/* Do a binary search for a given key in the array with a given base pointer,
which consists of nmemb elements that are of the given size each. To compare
the given key with an element from the array, the given function compar is
called (with key as first parameter, a pointer to the array member as
second parameter, and the context parameter passed to bsearch_s() as third
parameter); the function should return a value less than, equal to,
or greater than 0 if the key is considered to be less than, equal to, or
greater than the array element, respectively.
The function returns a pointer to a matching element found, or NULL if no
match is found.
The following conditions will be considered runtime constraint violations:
- nmemb or size > RSIZE_MAX.
- nmemb > 0 and either of key, base, or compar being a null pointer.
In case of a constraint violation, the array will not be searched.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC void * bsearch_s( const void * key, const void * base, rsize_t nmemb, rsize_t size, int ( *compar )( const void * k, const void * y, void * context ), void * context );
/* Do a quicksort on an array with a given base pointer, which consists of
nmemb elements that are of the given size each. To compare two elements from
the array, the given function compar is called, with the first two arguments
being pointers to the two objects to be compared, and the third argument
being the context parameter passed to qsort_s. The compar function should
return a value less than, equal to, or greater than 0 if the first argument
is considered to be less than, equal to, or greater than the second argument,
respectively. If two elements are compared equal, their order in the sorted
array is not specified.
The following conditions will be considered runtime constraint violations:
- nmemb or size > RSIZE_MAX.
- nmemb > 0 and either of base or compar being a null pointer.
In case of a constraint violation, the array will not be sorted.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t qsort_s( void * base, rsize_t nmemb, rsize_t size, int ( *compar )( const void * x, const void * y, void * context ), void * context );
/* TODO: Multibyte / wide character functions */
#endif
#ifdef __cplusplus
}
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STDLIB_H
#include _PDCLIB_EXTEND_STDLIB_H
#endif
#endif

View File

@ -0,0 +1,26 @@
/* _Noreturn <stdnoreturn.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STDNORETURN_H
#define _PDCLIB_STDNORETURN_H _PDCLIB_STDNORETURN_H
#include "pdclib/_PDCLIB_internal.h"
/* This basically breaks the letter of the standard (which states that
noreturn be defined to _Noreturn). This defines noreturn -> _Noreturn
on C11 compliant compilers only (as older compilers do not know about
_Noreturn).
*/
#define noreturn _PDCLIB_Noreturn
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STDNORETURN_H
#include _PDCLIB_EXTEND_STDNORETURN_H
#endif
#endif

View File

@ -0,0 +1,394 @@
/* String handling <string.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_STRING_H
#define _PDCLIB_STRING_H _PDCLIB_STRING_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_lib_ext1.h"
#include "pdclib/_PDCLIB_internal.h"
#ifndef _PDCLIB_SIZE_T_DEFINED
#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED
typedef _PDCLIB_size_t size_t;
#endif
#ifndef _PDCLIB_NULL_DEFINED
#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED
#define NULL _PDCLIB_NULL
#endif
/* String function conventions */
/*
In any of the following functions taking a size_t n to specify the length of
an array or size of a memory region, n may be 0, but the pointer arguments to
the call shall still be valid unless otherwise stated.
*/
/* Copying functions */
/* Copy a number of n characters from the memory area pointed to by s2 to the
area pointed to by s1. If the two areas overlap, behaviour is undefined.
Returns the value of s1.
*/
_PDCLIB_PUBLIC void * memcpy( void * _PDCLIB_restrict s1, const void * _PDCLIB_restrict s2, size_t n );
/* Copy a number of n characters from the memory area pointed to by s2 to the
area pointed to by s1. The two areas may overlap.
Returns the value of s1.
*/
_PDCLIB_PUBLIC void * memmove( void * _PDCLIB_restrict s1, const void * _PDCLIB_restrict s2, size_t n );
/* Copy the character array s2 (including terminating '\0' byte) into the
character array s1.
Returns the value of s1.
*/
_PDCLIB_PUBLIC char * strcpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 );
/* Copy a maximum of n characters from the character array s2 into the character
array s1. If s2 is shorter than n characters, '\0' bytes will be appended to
the copy in s1 until n characters have been written. If s2 is longer than n
characters, NO terminating '\0' will be written to s1. If the arrays overlap,
behaviour is undefined.
Returns the value of s1.
*/
_PDCLIB_PUBLIC char * strncpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n );
/* Concatenation functions */
/* Append the contents of the character array s2 (including terminating '\0') to
the character array s1 (first character of s2 overwriting the '\0' of s1). If
the arrays overlap, behaviour is undefined.
Returns the value of s1.
*/
_PDCLIB_PUBLIC char * strcat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 );
/* Append a maximum of n characters from the character array s2 to the character
array s1 (first character of s2 overwriting the '\0' of s1). A terminating
'\0' is ALWAYS appended, even if the full n characters have already been
written. If the arrays overlap, behaviour is undefined.
Returns the value of s1.
*/
_PDCLIB_PUBLIC char * strncat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n );
/* Comparison functions */
/* Compare the first n characters of the memory areas pointed to by s1 and s2.
Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if
s1 > s2.
*/
_PDCLIB_PUBLIC int memcmp( const void * s1, const void * s2, size_t n );
/* Compare the character arrays s1 and s2.
Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if
s1 > s2.
*/
_PDCLIB_PUBLIC int strcmp( const char * s1, const char * s2 );
/* Compare the character arrays s1 and s2, interpreted as specified by the
LC_COLLATE category of the current locale.
Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if
s1 > s2.
TODO: Currently a dummy wrapper for strcmp() as PDCLib does not yet support
locales.
*/
_PDCLIB_PUBLIC int strcoll( const char * s1, const char * s2 );
/* Compare no more than the first n characters of the character arrays s1 and
s2.
Returns 0 if s1 == s2, a negative number if s1 < s2, and a positive number if
s1 > s2.
*/
_PDCLIB_PUBLIC int strncmp( const char * s1, const char * s2, size_t n );
/* Transform the character array s2 as appropriate for the LC_COLLATE setting of
the current locale. If length of resulting string is less than n, store it in
the character array pointed to by s1. Return the length of the resulting
string.
*/
_PDCLIB_PUBLIC size_t strxfrm( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n );
/* Search functions */
/* Search the first n characters in the memory area pointed to by s for the
character c (interpreted as unsigned char).
Returns a pointer to the first instance found, or NULL.
*/
_PDCLIB_PUBLIC void * memchr( const void * s, int c, size_t n );
/* Search the character array s (including terminating '\0') for the character c
(interpreted as char).
Returns a pointer to the first instance found, or NULL.
*/
_PDCLIB_PUBLIC char * strchr( const char * s, int c );
/* Determine the length of the initial substring of character array s1 which
consists only of characters not from the character array s2.
Returns the length of that substring.
*/
_PDCLIB_PUBLIC size_t strcspn( const char * s1, const char * s2 );
/* Search the character array s1 for any character from the character array s2.
Returns a pointer to the first occurrence, or NULL.
*/
_PDCLIB_PUBLIC char * strpbrk( const char * s1, const char * s2 );
/* Search the character array s (including terminating '\0') for the character c
(interpreted as char).
Returns a pointer to the last instance found, or NULL.
*/
_PDCLIB_PUBLIC char * strrchr( const char * s, int c );
/* Determine the length of the initial substring of character array s1 which
consists only of characters from the character array s2.
Returns the length of that substring.
*/
_PDCLIB_PUBLIC size_t strspn( const char * s1, const char * s2 );
/* Search the character array s1 for the substring in character array s2.
Returns a pointer to that sbstring, or NULL. If s2 is of length zero,
returns s1.
*/
_PDCLIB_PUBLIC char * strstr( const char * s1, const char * s2 );
/* In a series of subsequent calls, parse a C string into tokens.
On the first call to strtok(), the first argument is a pointer to the to-be-
parsed C string. On subsequent calls, the first argument is NULL unless you
want to start parsing a new string. s2 holds an array of separator characters
which can differ from call to call. Leading separators are skipped, the first
trailing separator overwritten with '\0'.
Returns a pointer to the next token.
WARNING: This function uses static storage, and as such is not reentrant.
*/
_PDCLIB_PUBLIC char * strtok( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 );
/* Miscellaneous functions */
/* Write the character c (interpreted as unsigned char) to the first n
characters of the memory area pointed to by s.
Returns s.
*/
_PDCLIB_PUBLIC void * memset( void * s, int c, size_t n );
/* Map an error number to a (locale-specific) error message string. Error
numbers are typically errno values, but any number is mapped to a message.
TODO: PDCLib does not yet support locales.
*/
_PDCLIB_PUBLIC char * strerror( int errnum );
/* Returns the length of the string s (excluding terminating '\0').
*/
_PDCLIB_PUBLIC size_t strlen( const char * s );
/* Annex K -- Bounds-checking interfaces */
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0
#ifndef _PDCLIB_ERRNO_T_DEFINED
#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED
typedef int errno_t;
#endif
#ifndef _PDCLIB_RSIZE_T_DEFINED
#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED
typedef _PDCLIB_size_t rsize_t;
#endif
/* Copy a number of n characters from the memory area pointed to by s2 to the
area pointed to by s1 of size s1max.
Returns zero if successful, non-zero otherwise.
The following conditions will be considered runtime constraint violations:
- s1 or s2 being NULL.
- s1max or n being > RSIZE_MAX.
- n > s1max (not enough space in s1).
- copying between overlapping objects.
In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX
then the first s1max characters of s1 will be set to zero.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t memcpy_s( void * _PDCLIB_restrict s1, rsize_t s1max, const void * _PDCLIB_restrict s2, rsize_t n );
/* Copy a number of n characters from the memory area pointed to by s2 to the
area pointed to by s1 of size s1max. The two areas may overlap.
Returns zero if successful, non-zero otherwise.
The following conditions will be considered runtime constraint violations:
- s1 or s2 being NULL.
- s1max or n being > RSIZE_MAX.
- n > s1max (not enough space in s1).
In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX
then the first s1max characters of s1 will be set to zero.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t memmove_s( void * _PDCLIB_restrict s1, rsize_t s1max, const void * _PDCLIB_restrict s2, rsize_t n );
/* Copy the character array s2 (including terminating '\0' byte) into the
character array s1.
Returns zero if successful, non-zero otherwise.
The following conditions will be considered runtime constraint violations:
- s1 or s2 being NULL.
- s1max being zero or > RSIZE_MAX.
- s1max not greater than strnlen_s( s2, s1max ) (not enough space in s1).
- copying between overlapping objects.
In case of a constraint violation, if s1 is not NULL and s1max <= RSIZE_MAX
then s1[0] will be set to '\0'.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t strcpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 );
/* Copy a maximum of n characters from the character array s2 into the character
array s1. If s2 is longer than n, s1[n] will be set to '\0'.
Returns zero if successful, non-zero otherwise.
ATTENTION ATTENTION ATTENTION
This function differs in two fundamental ways from strncpy():
- remaining space in s1 will NOT be zeroed. Their value is unspecified.
- s1 WILL be zero-terminated even if there is not enough space to hold
all n characters from s2.
THANK YOU FOR YOUR ATTENTION.
The following conditions will be considered runtime constraint violations:
- s1 or s2 being NULL.
- s1max or n being > RSIZE_MAX.
- s1max being zero.
- n >= s1max and s1max <= strnlen_s( s2, s1max ) (not enough space in s1).
- copying between overlapping objects.
In case of a constraint violation, if s1 is not NULL and s1max is greater
zero and <= RSIZE_MAX, s1[0] will be set to '\0'.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t strncpy_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2, rsize_t n );
/* Append the contents of the character array s2 (including terminating '\0') to
the character array s1 (first character of s2 overwriting the '\0' of s1).
Elements following the terminating null character (if any) take unspecified
values.
Returns zero if successful, non-zero otherwise.
The following conditions will be considered runtime constraint violations:
- s1 or s2 being NULL.
- s1max being > RSIZE_MAX.
- s1max being zero.
- not enough space in s1 for both s1 and the characters copied from s2.
- copying between overlapping objects.
In case of a constraint violation, if s1 is not NULL and s1max is greater
zero and <= RSIZE_MAX, s1[0] will be set to '\0'.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t strcat_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2 );
/* Append a maximum of n characters from the character array s2 to the
character array s1 (first character of s2 overwriting the '\0' of s1). A
terminating '\0' is ALWAYS appended, even if the full n characters have
already been written.
Elements following the terminating null character (if any) take unspecified
values.
Returns zero if successful, non-zero otherwise.
The following conditions will be considered runtime constraint violations:
- s1 or s2 being NULL.
- s1max or n being > RSIZE_MAX.
- s1max being zero.
- not enough space in s1 for both s1 and the characters copied from s2.
- copying between overlapping objects.
In case of a constraint violation, if s1 is not NULL and s1max is greater
zero and <= RSIZE_MAX, s1[0] will be set to '\0'.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t strncat_s( char * _PDCLIB_restrict s1, rsize_t s1max, const char * _PDCLIB_restrict s2, rsize_t n );
/* In a series of subsequent calls, parse a C string into tokens.
On the first call to strtok(), the first argument is a pointer to the to-be-
parsed C string of size *s1max. On subsequent calls, the first argument is
NULL unless you want to start parsing a new string. s2 holds an array of
separator characters which can differ from call to call. Leading separators
are skipped, the first trailing separator overwritten with '\0'.
Returns a pointer to the next token.
The following conditions will be considered runtime constraint violations:
- s1max, s2, or ptr being NULL.
- s1max or n being > RSIZE_MAX.
- s1max being zero.
- not enough space in s1 for both s1 and the characters copied from s2.
- copying between overlapping objects.
In case of a constraint violation, if s1 is not NULL and s1max is greater
zero and <= RSIZE_MAX, s1[0] will be set to '\0'.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC char * strtok_s( char * _PDCLIB_restrict s1, rsize_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr );
/* Write the character c (interpreted as unsigned char) to the first n
characters of the memory area pointed to by s of size smax.
Returns zero if successful, non-zero otherwise.
The following conditions will be considered runtime constraint violations:
- s being NULL.
- smax or n being > RSIZE_MAX.
- n being > smax.
In case of a constraint violation, if s is not NULL and smax is <= RSIZE_MAX
the value of c (interpreted as unsigned char) is written to the first smax
characters of s.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t memset_s( void * s, rsize_t smax, int c, rsize_t n );
/* Map an error number to a (locale-specific) error message string. Error
numbers are typically errno values, but any number is mapped to a message.
TODO: PDCLib does not yet support locales.
If the length of the mapped string is < maxsize, the string is copied to s.
Otherwise, if maxsize is greater than zero, as much of the string as does
fit is copied, and s[maxsize-1] set to '\0'. If maxsize is greater than 3,
the partial string is made to end in "...".
Returns zero if the string was copied successfully in full, non-zero
otherwise.
The following conditions will be considered runtime constraint violations:
- s being NULL.
- maxsize being zero or > RSIZE_MAX.
In case of a constraint violation, s is not modified.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t strerror_s( char * s, rsize_t maxsize, errno_t errnum );
/* Map an error number to a (locale-specific) error message string, the same
way as strerror_s() would do. Error numbers are typically errno values,
but any number is mapped to a message.
TODO: PDCLib does not yet support locales.
Returns the length of the mapped string.
*/
_PDCLIB_PUBLIC size_t strerrorlen_s( errno_t errnum );
/* Returns the length of the string s (excluding terminating '\0').
If there is no null character in the first maxsize characters of s,
rerturns maxsize. If s is NULL, returns zero.
At most the first maxsize characters of s shall be accessed by the
function.
*/
_PDCLIB_PUBLIC size_t strnlen_s( const char * s, size_t maxsize );
#endif
#ifdef __cplusplus
}
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_STRING_H
#include _PDCLIB_EXTEND_STRING_H
#endif
#endif

View File

@ -0,0 +1,260 @@
/* Threads <threads.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This header does not include any platform-specific information, but as
a whole is optional (depending on whether threads are supported or not,
ref. __STDC_NO_THREADS__), which is why it is located in the example
platform instead of the general include directory.
*/
#ifndef _PDCLIB_THREADS_H
#define _PDCLIB_THREADS_H _PDCLIB_THREADS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <time.h>
#if __STDC_NO_THREADS__ == 1
#error __STDC_NO_THREADS__ defined but <threads.h> included. Something is wrong about your setup.
#endif
#if __STDC_VERSION__ >= 201112L
/* The rest of <threads.h> can work with a pre-C11 compiler just fine. */
#define thread_local _Thread_local
#endif
/* Initializing value for an object of type once_flag */
#define ONCE_FLAG_INIT _PDCLIB_ONCE_FLAG_INIT
/* Maximum number of times destructors are called on thread termination */
#define TSS_DTOR_ITERATIONS _PDCLIB_TSS_DTOR_ITERATIONS
/* Condition variable */
typedef _PDCLIB_cnd_t cnd_t;
/* Thread */
typedef _PDCLIB_thrd_t thrd_t;
/* Thread-specific storage */
typedef _PDCLIB_tss_t tss_t;
/* Mutex */
typedef _PDCLIB_mtx_t mtx_t;
/* TSS destructor */
typedef void ( *tss_dtor_t )( void * );
/* Thread start function */
typedef int ( *thrd_start_t )( void * );
/* Flag for use with call_once() */
typedef _PDCLIB_once_flag once_flag;
/* TODO: Documentation. */
enum
{
mtx_plain,
mtx_recursive,
mtx_timed
};
/* TODO: Documentation. */
enum
{
thrd_timedout,
thrd_success,
thrd_busy,
thrd_error,
thrd_nomem
};
/* Initialization functions */
/* Ensure that func is called only the first time call_once() is called
for a given flag.
*/
_PDCLIB_PUBLIC void call_once( once_flag * flag, void ( *func )( void ) );
/* Condition variable functions */
/* Unblock threads waiting on given condition.
Returns thrd_success if successful, thrd_error if the request could not
be honored.
*/
_PDCLIB_PUBLIC int cnd_broadcast( cnd_t * cond );
/* Destroy condition variable.
No threads may be waiting on a condition when it is destroyed.
*/
_PDCLIB_PUBLIC void cnd_destroy( cnd_t * cond );
/* Initialize condition variable.
Returns thrd_success if successful, thrd_nomem if out of memory, and
thrd_error if the request could not be honored.
Initializes the variable in a way that a thread calling cnd_wait() on it
would block.
*/
_PDCLIB_PUBLIC int cnd_init( cnd_t * cond );
/* Unblock one thread waiting on the condition variable.
Returns thrd_success if successful, thrd_error if the request could not
be honored.
*/
_PDCLIB_PUBLIC int cnd_signal( cnd_t * cond );
/* TODO: Documentation.
Returns thrd_success if successful, thrd_timedout if the specified time
is reached without acquiring the resource, or thrd_error if the request
could not be honored.
*/
_PDCLIB_PUBLIC int cnd_timedwait( cnd_t * _PDCLIB_restrict cond, mtx_t * _PDCLIB_restrict mtx, const struct timespec * _PDCLIB_restrict ts );
/* TODO: Documentation.
Returns thrd_success if successful, thrd_error if the request could not
be honored.
*/
int cnd_wait( cnd_t * cond, mtx_t * mtx );
/* Mutex functions */
/* Destroy mutex variable.
No threads may be waiting on a mutex when it is destroyed.
*/
_PDCLIB_PUBLIC void mtx_destroy( mtx_t * mtx );
/* Initialize mutex variable.
Returns thrd_success if successful, thrd_error if the request could not
be honored.
Type must have one of the following values:
mtx_plain -- non-recursive mutex
mtx_timed -- non-recursive mutex supporting timeout
mtx_plain | mtx_recursive -- recursive mutex
mtx_timed | mtx_recursive -- recursive mutex supporting timeout
*/
_PDCLIB_PUBLIC int mtx_init( mtx_t * mtx, int type );
/* Try to lock the given mutex (blocking).
Returns thrd_success if successful, thrd_error if the request could not
be honored.
If the given mutex is non-recursive, it must not be already locked by
the calling thread.
*/
_PDCLIB_PUBLIC int mtx_lock( mtx_t * mtx );
/* TODO: Documentation.
Returns thrd_success if successful, thrd_timedout if the specified time
is reached without acquiring the resource, or thrd_error if the request
could not be honored.
*/
_PDCLIB_PUBLIC int mtx_timedlock( mtx_t * _PDCLIB_restrict mtx, const struct timespec * _PDCLIB_restrict ts );
/* Try to lock the given mutex (non-blocking).
Returns thrd_success if successful, thrd_busy if the resource is already
locked, or thrd_error if the request could not be honored.
*/
_PDCLIB_PUBLIC int mtx_trylock( mtx_t * mtx );
/* Unlock the given mutex.
Returns thrd_success if successful, thrd_error if the request could not
be honored.
The given mutex must be locked by the calling thread.
*/
_PDCLIB_PUBLIC int mtx_unlock( mtx_t * mtx );
/* Thread functions */
/* Create a new thread.
Returns thrd_success if successful, thrd_nomem if out of memory, and
thrd_error if the request could not be honored.
Create a new thread executing func( arg ), and sets thr to identify
the created thread. (Identifiers may be reused afer a thread exited
and was either detached or joined.)
*/
_PDCLIB_PUBLIC int thrd_create( thrd_t * thr, thrd_start_t func, void * arg );
/* Identify the calling thread.
Returns the identifier of the calling thread.
*/
_PDCLIB_PUBLIC thrd_t thrd_current( void );
/* Notify the OS to destroy all resources of a given thread once it
terminates.
Returns thrd_success if successful, thrd_error if the request could not
be honored.
The given thread must not been previously detached or joined.
*/
_PDCLIB_PUBLIC int thrd_detach( thrd_t thr );
/* Compare two thread identifiers for equality.
Returns nonzero if both parameters identify the same thread, zero
otherwise.
*/
_PDCLIB_PUBLIC int thrd_equal( thrd_t thr0, thrd_t thr1 );
/* Terminate calling thread, set result code to res.
When the last thread of a program terminates the program shall terminate
normally as if by exit( EXIT_SUCCESS ).
FIXME: The result code setting is NOT implemented correctly at this point.
The value is indeterminate.
*/
_PDCLIB_PUBLIC _PDCLIB_Noreturn void thrd_exit( int res ) _PDCLIB_NORETURN;
/* Join the given thread with the calling thread.
Returns thrd_success if successful, thrd_error if the request could not
be honored.
Function blocks until the given thread terminates. If res is not NULL,
the given thread's result code will be stored at that address.
*/
_PDCLIB_PUBLIC int thrd_join( thrd_t thr, int * res );
/* Suspend the calling thread for the given duration or until a signal not
being ignored is received.
Returns zero if the requested time has elapsed, -1 if interrupted by a
signal, negative if the request failed.
If remaining is not NULL, and the sleeping thread received a signal that
is not being ignored, the remaining time (duration minus actually elapsed
time) shall be stored at that address.
*/
_PDCLIB_PUBLIC int thrd_sleep( const struct timespec * duration, struct timespec * remaining );
/* Permit other threads to run. */
_PDCLIB_PUBLIC void thrd_yield( void );
/* Thread-specific storage functions */
/* Initialize thread-specific storage, with optional destructor
Returns thrd_success if successful, thrd_error otherwise (in this case
key is set to an undefined value).
*/
_PDCLIB_PUBLIC int tss_create( tss_t * key, tss_dtor_t dtor );
/* Release all resources of a given thread-specific storage. */
_PDCLIB_PUBLIC void tss_delete( tss_t key );
/* Returns the value for the current thread associated with the given key.
*/
_PDCLIB_PUBLIC void * tss_get( tss_t key );
/* Sets the value associated with the given key for the current thread.
Returns thrd_success if successful, thrd_error if the request could not
be honored.
*/
_PDCLIB_PUBLIC int tss_set( tss_t key, void * val );
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_THREADS_H
#include _PDCLIB_EXTEND_THREADS_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,191 @@
/* Date and time <time.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_TIME_H
#define _PDCLIB_TIME_H _PDCLIB_TIMEH
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_lib_ext1.h"
#include "pdclib/_PDCLIB_internal.h"
#ifndef _PDCLIB_SIZE_T_DEFINED
#define _PDCLIB_SIZE_T_DEFINED _PDCLIB_SIZE_T_DEFINED
typedef _PDCLIB_size_t size_t;
#endif
#ifndef _PDCLIB_NULL_DEFINED
#define _PDCLIB_NULL_DEFINED _PDCLIB_NULL_DEFINED
#define NULL _PDCLIB_NULL
#endif
/* See comments in _PDCLIB_config.h on the semantics of time_t and clock_t. */
typedef _PDCLIB_time_t time_t;
typedef _PDCLIB_clock_t clock_t;
#define CLOCKS_PER_SEC _PDCLIB_CLOCKS_PER_SEC
#define TIME_UTC _PDCLIB_TIME_UTC
/* Implementor's note: If you change this structure, and are using Pthread
threading support, check auxiliary/pthread/pthread_readout.c for its
twin. It is imperative that Pthread and PDCLib use identical layouts for
struct timespec, as they are implicitly cast from one to the other. This
cannot be checked for in this header (as we may not include host system
headers here), so the assert()s are in pthread_readout.c (which, in turn,
cannot include *this* header, which is why this admonishment to keep the
definitions in sync exists...).
*/
struct timespec
{
time_t tv_sec;
long tv_nsec;
};
struct tm
{
int tm_sec; /* 0-60 */
int tm_min; /* 0-59 */
int tm_hour; /* 0-23 */
int tm_mday; /* 1-31 */
int tm_mon; /* 0-11 */
int tm_year; /* years since 1900 */
int tm_wday; /* 0-6 */
int tm_yday; /* 0-365 */
int tm_isdst; /* >0 DST, 0 no DST, <0 information unavailable */
};
/* Returns the number of "clocks" in processor time since the invocation
of the program. Divide by CLOCKS_PER_SEC to get the value in seconds.
Returns -1 if the value cannot be represented in the return type or is
not available.
*/
_PDCLIB_PUBLIC clock_t clock( void );
/* Returns the difference between two calendar times in seconds. */
_PDCLIB_PUBLIC double difftime( time_t time1, time_t time0 );
/* Normalizes the values in the broken-down time pointed to by timeptr.
Returns the calender time specified by the broken-down time.
*/
_PDCLIB_PUBLIC time_t mktime( struct tm * timeptr );
/* Returns the current calender time. If timer is not a NULL pointer, stores
the current calender time at that address as well.
*/
_PDCLIB_PUBLIC time_t time( time_t * timer );
/* Sets the interval pointed to by ts to the current calender time, based
on the specified base.
Returns base, if successful, otherwise zero.
*/
_PDCLIB_PUBLIC int timespec_get( struct timespec * ts, int base );
/* Converts the broken-down time pointed to by timeptr into a string in the
form "Sun Sep 16 01:03:52 1973\n\0".
*/
_PDCLIB_PUBLIC char * asctime( const struct tm * timeptr );
/* Equivalent to asctime( localtime( timer ) ). */
_PDCLIB_PUBLIC char * ctime( const time_t * timer );
/* Converts the calender time pointed to by timer into a broken-down time
expressed as UTC.
Returns a pointer to the broken-down time, or a NULL pointer if it
cannot be represented.
*/
_PDCLIB_PUBLIC struct tm * gmtime( const time_t * timer );
/* Converts the calender time pointed to by timer into a broken-down time
expressed as local time.
Returns a pointer to the broken-down time, or a NULL pointer if if
cannot be represented.
*/
_PDCLIB_PUBLIC struct tm * localtime( const time_t * timer );
/* Writes the broken-down time pointed to by timeptr into the character
array pointed to by s. The string pointed to by format controls the
exact output. No more than maxsize charactrs will be written.
Returns the number of characters written (excluding the terminating
null character), or zero on failure.
*/
_PDCLIB_PUBLIC size_t strftime( char * _PDCLIB_restrict s, size_t maxsize, const char * _PDCLIB_restrict format, const struct tm * _PDCLIB_restrict timeptr );
/* Annex K -- Bounds-checking interfaces */
#if ( __STDC_WANT_LIB_EXT1__ + 0 ) != 0
#ifndef _PDCLIB_ERRNO_T_DEFINED
#define _PDCLIB_ERRNO_T_DEFINED _PDCLIB_ERRNO_T_DEFINED
typedef int errno_t;
#endif
#ifndef _PDCLIB_RSIZE_T_DEFINED
#define _PDCLIB_RSIZE_T_DEFINED _PDCLIB_RSIZE_T_DEFINED
typedef _PDCLIB_size_t rsize_t;
#endif
/* Converts the broken-down time pointed to by timeptr into a string in the
form "Sun Sep 16 01:03:52 1973\n\0", which is stored in buffer s of maxsize.
Returns zero if the time was successfully converted and stored, non-zero
otherwise.
The following conditions will be considered runtime constraint violations:
- s or timeptr being NULL.
- maxsize being < 26 or > RSIZE_MAX.
- the broken-down time pointed to by timeptr not being normalized.
- the year represented by the broken-down time pointed to by timeptr
being < 0 or > 9999.
In case of a constraint violation, the time will not be converted. If
s is not NULL and maxsize is neither zero nor > RSIZE_MAX, s[0] will be
set to '\0'.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC errno_t asctime_s( char * s, rsize_t maxsize, const struct tm * timeptr );
/* Equivalent to asctime_s( s, maxsize, localtime( timer ) ). */
_PDCLIB_PUBLIC errno_t ctime_s( char * s, rsize_t maxsize, const time_t * timer );
/* Converts the calender time pointed to by timer into a broken-down time
expressed as UTC, which gets stored in the result struct.
Returns a pointer to the broken-down time, or a NULL pointer if if
cannot be represented or stored.
The following conditions will be considered runtime constraint violations:
- timer or result being NULL.
In case of a constraint violation, the time will not be converted.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC struct tm * gmtime_s( const time_t * _PDCLIB_restrict timer, struct tm * _PDCLIB_restrict result );
/* Converts the calender time pointed to by timer into a broken-down time
expressed as local time, which gets stored in the result struct.
Returns a pointer to the broken-down time, or a NULL pointer if if
cannot be represented or stored.
The following conditions will be considered runtime constraint violations:
- timer or result being NULL.
In case of a constraint violation, the time will not be converted.
The currently active constraint violation handler function will be called
(see set_constraint_handler_s()).
*/
_PDCLIB_PUBLIC struct tm * localtime_s( const time_t * _PDCLIB_restrict timer, struct tm * _PDCLIB_restrict result );
#endif
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_TIME_H
#include _PDCLIB_EXTEND_TIME_H
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,152 @@
/* Wide character classification and mapping utilities <wctype.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef _PDCLIB_WCTYPE_H
#define _PDCLIB_WCTYPE_H _PDCLIB_WCTYPE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "pdclib/_PDCLIB_internal.h"
typedef _PDCLIB_wint_t wint_t;
typedef int wctrans_t;
typedef int wctype_t;
#ifndef _PDCLIB_WEOF_DEFINED
#define _PDCLIB_WEOF_DEFINED _PDCLIB_WEOF_DEFINED
#define WEOF (wint_t)-1
#endif
/* Wide character classification functions */
/* Returns iswalpha( wc ) || iswdigit( wc ) */
_PDCLIB_PUBLIC int iswalnum( wint_t wc );
/* Returns true for wide characters for which either isupper( wc ) or
islower( wc ) is true, as well as a set of locale-specific wide
characters which are neither control characters, digits, punctuation,
or whitespace.
*/
_PDCLIB_PUBLIC int iswalpha( wint_t wc );
/* Returns true if the character iswspace() and used for separating words
within a line of text. In the "C" locale, only L' ' and L'\t' are
considered blanks.
*/
_PDCLIB_PUBLIC int iswblank( wint_t wc );
/* Returns true if the wide character is a control character. */
_PDCLIB_PUBLIC int iswcntrl( wint_t wc );
/* Returns true if the wide character is a decimal digit. Locale-
independent. */
_PDCLIB_PUBLIC int iswdigit( wint_t wc );
/* Returns iswprint( wc ) && ! iswspace( wc ).
NOTE: This definition differs from that of isgraph() in <ctype.h>,
which considers only ' ', not all isspace() characters.
*/
_PDCLIB_PUBLIC int iswgraph( wint_t wc );
/* Returns true for lowerspace wide characters, as well as a set of
locale-specific wide characters which are neither control charcters,
digits, punctuation, or whitespace.
*/
_PDCLIB_PUBLIC int iswlower( wint_t wc );
/* Returns true for every printing wide character. */
_PDCLIB_PUBLIC int iswprint( wint_t wc );
/* Returns true for a locale-specific set of punctuation characters that
are neither whitespace nor alphanumeric.
*/
_PDCLIB_PUBLIC int iswpunct( wint_t wc );
/* Returns true for a locale-specific set of whitespace characters that
are neither alphanumeric, graphic, or punctuation.
*/
_PDCLIB_PUBLIC int iswspace( wint_t wc );
/* Returns true for upperspace wide characters, as well as a set of
locale-specific wide characters which are neither control charcters,
digits, punctuation, or whitespace.
*/
_PDCLIB_PUBLIC int iswupper( wint_t wc );
/* Returns true if the wide character is a hexadecimal digit. Locale-
independent. */
_PDCLIB_PUBLIC int iswxdigit( wint_t wc );
/* Extensible wide character classification functions */
/* Returns true if the wide character wc has the property described by
desc (which was retrieved by a previous call to wctype() without
changing the LC_CTYPE locale setting between the two calls).
*/
_PDCLIB_PUBLIC int iswctype( wint_t wc, wctype_t desc );
/* Returns a description object for a named character property, to be
used as parameter to the iswctype() function. Supported property
names are:
"alnum" -- alphanumeric, as per iswalnum()
"alpha" -- alphabetic, as per iswalpha()
"blank" -- blank, as per iswblank()
"cntrl" -- control, as per iswcntrl()
"digit" -- decimal digit, as per iswdigit()
"graph" -- graphic, as per iswgraph()
"lower" -- lowercase, as per iswlower()
"print" -- printing, as per iswprint()
"punct" -- punctuation, as per iswprint()
"space" -- whitespace, as per iswspace()
"upper" -- uppercase, as per iswupper()
"xdigit" -- hexadecimal digit, as per iswxdigit()
For unsupported properties, the function returns zero.
*/
_PDCLIB_PUBLIC wctype_t wctype( const char * property );
/* Wide character case mapping utilities */
/* Converts an uppercase letter to a corresponding lowercase letter. Input for
which no corresponding lowercase letter exists remains unchanged.
*/
_PDCLIB_PUBLIC wint_t towlower( wint_t wc );
/* Converts a lowercase letter to a corresponding uppercase letter. Input for
which no corresponding uppercase letter exists remains unchanged.
*/
_PDCLIB_PUBLIC wint_t towupper( wint_t wc );
/* Extensible wide character case mapping utilities */
/* Converts the wide character wc according to the transition described
by desc (which was retrieved by a previous call to wctrans() without
changing the LC_CTYPE locale setting between the two calls).
*/
_PDCLIB_PUBLIC wint_t towctrans( wint_t wc, wctrans_t desc );
/* Returns a description object for a named character transformation, to
be used as parameter to the towctrans() function. Supported transformation
properties are:
"tolower" -- lowercase mapping, as per towlower()
"toupper" -- uppercase mapping, as per towupper()
For unsupported properties, the function returns zero.
*/
_PDCLIB_PUBLIC wctrans_t wctrans( const char * property );
/* Extension hook for downstream projects that want to have non-standard
extensions to standard headers.
*/
#ifdef _PDCLIB_EXTEND_WCTYPE_H
#include _PDCLIB_EXTEND_WCTYPE_H
#endif
#ifdef __cplusplus
}
#endif
#endif

46
extlib/pdlibc/memcmp.c Normal file
View File

@ -0,0 +1,46 @@
/* memcmp( const void *, const void *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h>
#ifndef REGTEST
int memcmp( const void * s1, const void * s2, size_t n )
{
const unsigned char * p1 = ( const unsigned char * ) s1;
const unsigned char * p2 = ( const unsigned char * ) s2;
while ( n-- )
{
if ( *p1 != *p2 )
{
return *p1 - *p2;
}
++p1;
++p2;
}
return 0;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
const char xxxxx[] = "xxxxx";
TESTCASE( memcmp( abcde, abcdx, 5 ) < 0 );
TESTCASE( memcmp( abcde, abcdx, 4 ) == 0 );
TESTCASE( memcmp( abcde, xxxxx, 0 ) == 0 );
TESTCASE( memcmp( xxxxx, abcde, 1 ) > 0 );
return 0;
}
#endif

64
extlib/pdlibc/strncat.c Normal file
View File

@ -0,0 +1,64 @@
/* strncat( char *, const char *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h>
#ifndef REGTEST
char * strncat( char * s1, const char * s2, size_t n )
{
char * rc = s1;
while ( *s1 )
{
++s1;
}
while ( n && ( *s1++ = *s2++ ) )
{
--n;
}
if ( n == 0 )
{
*s1 = '\0';
}
return rc;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
char s[] = "xx\0xxxxxx";
TESTCASE( strncat( s, abcde, 10 ) == s );
TESTCASE( s[2] == 'a' );
TESTCASE( s[6] == 'e' );
TESTCASE( s[7] == '\0' );
TESTCASE( s[8] == 'x' );
s[0] = '\0';
TESTCASE( strncat( s, abcdx, 10 ) == s );
TESTCASE( s[4] == 'x' );
TESTCASE( s[5] == '\0' );
TESTCASE( strncat( s, "\0", 10 ) == s );
TESTCASE( s[5] == '\0' );
TESTCASE( s[6] == 'e' );
TESTCASE( strncat( s, abcde, 0 ) == s );
TESTCASE( s[5] == '\0' );
TESTCASE( s[6] == 'e' );
TESTCASE( strncat( s, abcde, 3 ) == s );
TESTCASE( s[5] == 'a' );
TESTCASE( s[7] == 'c' );
TESTCASE( s[8] == '\0' );
return TEST_RESULTS;
}
#endif

55
extlib/pdlibc/strncmp.c Normal file
View File

@ -0,0 +1,55 @@
/* strncmp( const char *, const char *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h>
#ifndef REGTEST
int strncmp( const char * s1, const char * s2, size_t n )
{
while ( n && *s1 && ( *s1 == *s2 ) )
{
++s1;
++s2;
--n;
}
if ( n == 0 )
{
return 0;
}
else
{
return ( *( unsigned char * )s1 - * ( unsigned char * )s2 );
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
char cmpabcde[] = "abcde\0f";
char cmpabcd_[] = "abcde\xfc";
char empty[] = "";
char x[] = "x";
TESTCASE( strncmp( abcde, cmpabcde, 5 ) == 0 );
TESTCASE( strncmp( abcde, cmpabcde, 10 ) == 0 );
TESTCASE( strncmp( abcde, abcdx, 5 ) < 0 );
TESTCASE( strncmp( abcdx, abcde, 5 ) > 0 );
TESTCASE( strncmp( empty, abcde, 5 ) < 0 );
TESTCASE( strncmp( abcde, empty, 5 ) > 0 );
TESTCASE( strncmp( abcde, abcdx, 4 ) == 0 );
TESTCASE( strncmp( abcde, x, 0 ) == 0 );
TESTCASE( strncmp( abcde, x, 1 ) < 0 );
TESTCASE( strncmp( abcde, cmpabcd_, 10 ) < 0 );
return TEST_RESULTS;
}
#endif

59
extlib/pdlibc/strncpy.c Normal file
View File

@ -0,0 +1,59 @@
/* strncpy( char *, const char *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h>
#ifndef REGTEST
char * strncpy( char * s1, const char * s2, size_t n )
{
char * rc = s1;
while ( n && ( *s1++ = *s2++ ) )
{
/* Cannot do "n--" in the conditional as size_t is unsigned and we have
to check it again for >0 in the next loop below, so we must not risk
underflow.
*/
--n;
}
/* Checking against 1 as we missed the last --n in the loop above. */
while ( n-- > 1 )
{
*s1++ = '\0';
}
return rc;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
char s[] = "xxxxxxx";
TESTCASE( strncpy( s, "", 1 ) == s );
TESTCASE( s[0] == '\0' );
TESTCASE( s[1] == 'x' );
TESTCASE( strncpy( s, abcde, 6 ) == s );
TESTCASE( s[0] == 'a' );
TESTCASE( s[4] == 'e' );
TESTCASE( s[5] == '\0' );
TESTCASE( s[6] == 'x' );
TESTCASE( strncpy( s, abcde, 7 ) == s );
TESTCASE( s[6] == '\0' );
TESTCASE( strncpy( s, "xxxx", 3 ) == s );
TESTCASE( s[0] == 'x' );
TESTCASE( s[2] == 'x' );
TESTCASE( s[3] == 'd' );
return TEST_RESULTS;
}
#endif