[libc] Bring libc in-tree

Moving libc from its separate repo into this one, minor resulting build
fixes, and a hacky way to add -I for libc headers in builds.
This commit is contained in:
2020-08-23 17:21:08 -07:00
parent 28b800a497
commit 95a35cd0bf
216 changed files with 21033 additions and 12 deletions

View File

@@ -2,7 +2,6 @@
/// \file avl_tree.h
/// Templated container class for an AVL tree
#include <algorithm>
#include <stdint.h>
#include "kutil/assert.h"
#include "kutil/slab_allocated.h"
@@ -72,7 +71,7 @@ private:
{
int left = height(m_left);
int right = height(m_right);
m_height = std::max(left, right) + 1;
m_height = left > right ? left : right;
return left - right;
}

View File

@@ -2,7 +2,6 @@
/// \file vector.h
/// Definition of a simple dynamic vector collection for use in kernel space
#include <algorithm>
#include <utility>
#include "kutil/memory.h"
@@ -175,7 +174,7 @@ public:
void set_capacity(size_t capacity)
{
T *new_array = reinterpret_cast<T*>(kalloc(capacity * sizeof(T)));
size_t size = std::min(capacity, m_size);
size_t size = capacity > m_size ? m_size : capacity;
kutil::memcpy(new_array, m_elements, size * sizeof(T));

View File

@@ -0,0 +1,5 @@
global _PDCLIB_Exit
_PDCLIB_Exit:
; arg should already be in rdi
mov rax, 0x11 ; Exit syscall
syscall

View File

@@ -0,0 +1,13 @@
/* isalnum( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isalnum( int c )
{
return ( isdigit( c ) || isalpha( c ) );
}

View File

@@ -0,0 +1,13 @@
/* isalpha( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isalpha( int c )
{
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_ALPHA );
}

View File

@@ -0,0 +1,13 @@
/* isblank( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isblank( int c )
{
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_BLANK );
}

View File

@@ -0,0 +1,13 @@
/* iscntrl( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int iscntrl( int c )
{
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_CNTRL );
}

View File

@@ -0,0 +1,13 @@
/* isdigit( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isdigit( int c )
{
return ( c >= _PDCLIB_lc_ctype.digits_low && c <= _PDCLIB_lc_ctype.digits_high );
}

View File

@@ -0,0 +1,13 @@
/* isgraph( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isgraph( int c )
{
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_GRAPH );
}

View File

@@ -0,0 +1,13 @@
/* islower( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int islower( int c )
{
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_LOWER );
}

View File

@@ -0,0 +1,14 @@
/* isprint( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isprint( int c )
{
/* FIXME: Space as of current locale charset, not source charset. */
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_GRAPH ) || ( c == ' ' );
}

View File

@@ -0,0 +1,13 @@
/* ispunct( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int ispunct( int c )
{
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_PUNCT );
}

View File

@@ -0,0 +1,13 @@
/* isspace( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isspace( int c )
{
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_SPACE );
}

View File

@@ -0,0 +1,13 @@
/* isupper( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isupper( int c )
{
return ( _PDCLIB_lc_ctype.entry[c].flags & _PDCLIB_CTYPE_UPPER );
}

View File

@@ -0,0 +1,15 @@
/* isxdigit( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int isxdigit( int c )
{
return ( isdigit( c )
|| ( c >= _PDCLIB_lc_ctype.Xdigits_low && c <= _PDCLIB_lc_ctype.Xdigits_high )
|| ( c >= _PDCLIB_lc_ctype.xdigits_low && c <= _PDCLIB_lc_ctype.xdigits_high ) );
}

View File

@@ -0,0 +1,13 @@
/* tolower( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int tolower( int c )
{
return _PDCLIB_lc_ctype.entry[c].lower;
}

View File

@@ -0,0 +1,13 @@
/* toupper( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <locale.h>
int toupper( int c )
{
return _PDCLIB_lc_ctype.entry[c].upper;
}

View File

@@ -0,0 +1,29 @@
#pragma once
/* 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.
*/
#include "j6libc/aux.h"
#include "j6libc/cpp.h"
CPP_CHECK_BEGIN
void _PDCLIB_assert( const char * const, const char * const, const char * const );
/* If NDEBUG is set, assert() is a null operation. */
#undef assert
#ifdef NDEBUG
#define assert( ignore ) ( (void) 0 )
#else
#define assert( expression ) ( ( expression ) ? (void) 0 \
: _PDCLIB_assert( "Assertion failed: " #expression \
", function ", __func__, \
", file " __FILE__ \
", line " _PDCLIB_symbol2string( __LINE__ ) \
"." _PDCLIB_endl ) )
#endif
CPP_CHECK_END

View File

@@ -0,0 +1,96 @@
#pragma once
/* 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.
*/
#include "j6libc/int.h"
#include "j6libc/cpp.h"
CPP_CHECK_BEGIN
/* 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 ) */
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.
*/
int isalpha( int c );
/* Returns true if the character isspace() and used for seperating words within
a line of text. In the "C" locale, only ' ' and '\t' are considered blanks.
*/
int isblank( int c );
/* Returns true if the character is a control character. */
int iscntrl( int c );
/* Returns true if the character is a decimal digit. Locale-independent. */
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 ' '.
*/
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().
*/
int islower( int c );
/* Returns true for every printing character including space (' '). */
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.
*/
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.
*/
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().
*/
int isupper( int c );
/* Returns true for any hexadecimal-digit character. Locale-independent. */
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.
*/
int tolower( int c );
/* Converts a lowercase letter to a corresponding uppercase letter. Input that
is not a lowercase letter remains unchanged.
*/
int toupper( int c );
CPP_CHECK_END

View File

@@ -0,0 +1,15 @@
#pragma once
/* 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.
*/
#include "j6libc/int.h"
#define errno (*_PDCLIB_errno_func())
#define ERANGE _PDCLIB_ERANGE
#define EDOM _PDCLIB_EDOM
#define ENOMEM _PDCLIB_ENOMEM
#define EINVAL _PDCLIB_EINVAL

View File

@@ -0,0 +1,71 @@
#pragma once
/* 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.
*/
#include "j6libc/config.h"
#define FLT_ROUNDS _PDCLIB_FLT_ROUNDS
#define FLT_EVAL_METHOD _PDCLIB_FLT_EVAL_METHOD
#define DECIMAL_DIG _PDCLIB_DECIMAL_DIG
/* Radix of exponent representation */
#define FLT_RADIX __FLT_RADIX__
/* Number of base-FLT_RADIX digits in the significand of a float */
#define FLT_MANT_DIG __FLT_MANT_DIG__
/* Number of decimal digits of precision in a float */
#define FLT_DIG __FLT_DIG__
/* Difference between 1.0 and the minimum float greater than 1.0 */
#define FLT_EPSILON __FLT_EPSILON__
/* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */
#define FLT_MIN_EXP __FLT_MIN_EXP__
/* Minimum normalised float */
#define FLT_MIN __FLT_MIN__
/* Minimum int x such that 10**x is a normalised float */
#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
/* Maximum int x such that FLT_RADIX**(x-1) is a representable float */
#define FLT_MAX_EXP __FLT_MAX_EXP__
/* Maximum float */
#define FLT_MAX __FLT_MAX__
/* Maximum int x such that 10**x is a representable float */
#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__
/* Number of base-FLT_RADIX digits in the significand of a double */
#define DBL_MANT_DIG __DBL_MANT_DIG__
/* Number of decimal digits of precision in a double */
#define DBL_DIG __DBL_DIG__
/* Difference between 1.0 and the minimum double greater than 1.0 */
#define DBL_EPSILON __DBL_EPSILON__
/* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */
#define DBL_MIN_EXP __DBL_MIN_EXP__
/* Minimum normalised double */
#define DBL_MIN __DBL_MIN__
/* Minimum int x such that 10**x is a normalised double */
#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__
/* Maximum int x such that FLT_RADIX**(x-1) is a representable double */
#define DBL_MAX_EXP __DBL_MAX_EXP__
/* Maximum double */
#define DBL_MAX __DBL_MAX__
/* Maximum int x such that 10**x is a representable double */
#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
/* Number of base-FLT_RADIX digits in the significand of a long double */
#define LDBL_MANT_DIG __LDBL_MANT_DIG__
/* Number of decimal digits of precision in a long double */
#define LDBL_DIG __LDBL_DIG__
/* Difference between 1.0 and the minimum long double greater than 1.0 */
#define LDBL_EPSILON __LDBL_EPSILON__
/* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */
#define LDBL_MIN_EXP __LDBL_MIN_EXP__
/* Minimum normalised long double */
#define LDBL_MIN __LDBL_MIN__
/* Minimum int x such that 10**x is a normalised long double */
#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
/* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */
#define LDBL_MAX_EXP __LDBL_MAX_EXP__
/* Maximum long double */
#define LDBL_MAX __LDBL_MAX__
/* Maximum int x such that 10**x is a representable long double */
#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__

View File

@@ -0,0 +1,250 @@
#pragma once
/* 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.
*/
#include "j6libc/cpp.h"
#include <stdint.h>
CPP_CHECK_BEGIN
typedef struct _PDCLIB_imaxdiv_t imaxdiv_t;
#define PRId8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, d ) )
#define PRId16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, d ) )
#define PRId32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, d ) )
#define PRId64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, d ) )
#define PRIdLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, d ) )
#define PRIdLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, d ) )
#define PRIdLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, d ) )
#define PRIdLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, d ) )
#define PRIdFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, d ) )
#define PRIdFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, d ) )
#define PRIdFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, d ) )
#define PRIdFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, d ) )
#define PRIdMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, d ) )
#define PRIdPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, d ) )
#define PRIi8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, i ) )
#define PRIi16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, i ) )
#define PRIi32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, i ) )
#define PRIi64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, i ) )
#define PRIiLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, i ) )
#define PRIiLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, i ) )
#define PRIiLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, i ) )
#define PRIiLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, i ) )
#define PRIiFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, i ) )
#define PRIiFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, i ) )
#define PRIiFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, i ) )
#define PRIiFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, i ) )
#define PRIiMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, i ) )
#define PRIiPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, i ) )
#define PRIo8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, o ) )
#define PRIo16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, o ) )
#define PRIo32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, o ) )
#define PRIo64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, o ) )
#define PRIoLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, o ) )
#define PRIoLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, o ) )
#define PRIoLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, o ) )
#define PRIoLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, o ) )
#define PRIoFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, o ) )
#define PRIoFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, o ) )
#define PRIoFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, o ) )
#define PRIoFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, o ) )
#define PRIoMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, o ) )
#define PRIoPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, o ) )
#define PRIu8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, u ) )
#define PRIu16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, u ) )
#define PRIu32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, u ) )
#define PRIu64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, u ) )
#define PRIuLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, u ) )
#define PRIuLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, u ) )
#define PRIuLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, u ) )
#define PRIuLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, u ) )
#define PRIuFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, u ) )
#define PRIuFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, u ) )
#define PRIuFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, u ) )
#define PRIuFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, u ) )
#define PRIuMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, u ) )
#define PRIuPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, u ) )
#define PRIx8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, x ) )
#define PRIx16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, x ) )
#define PRIx32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, x ) )
#define PRIx64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, x ) )
#define PRIxLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, x ) )
#define PRIxLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, x ) )
#define PRIxLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, x ) )
#define PRIxLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, x ) )
#define PRIxFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, x ) )
#define PRIxFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, x ) )
#define PRIxFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, x ) )
#define PRIxFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, x ) )
#define PRIxMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, x ) )
#define PRIxPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, x ) )
#define PRIX8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, X ) )
#define PRIX16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, X ) )
#define PRIX32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, X ) )
#define PRIX64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, X ) )
#define PRIXLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, X ) )
#define PRIXLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, X ) )
#define PRIXLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, X ) )
#define PRIXLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, X ) )
#define PRIXFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, X ) )
#define PRIXFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, X ) )
#define PRIXFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, X ) )
#define PRIXFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, X ) )
#define PRIXMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, X ) )
#define PRIXPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, X ) )
#define SCNd8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, d ) )
#define SCNd16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, d ) )
#define SCNd32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, d ) )
#define SCNd64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, d ) )
#define SCNdLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, d ) )
#define SCNdLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, d ) )
#define SCNdLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, d ) )
#define SCNdLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, d ) )
#define SCNdFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, d ) )
#define SCNdFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, d ) )
#define SCNdFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, d ) )
#define SCNdFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, d ) )
#define SCNdMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, d ) )
#define SCNdPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, d ) )
#define SCNi8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, i ) )
#define SCNi16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, i ) )
#define SCNi32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, i ) )
#define SCNi64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, i ) )
#define SCNiLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, i ) )
#define SCNiLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, i ) )
#define SCNiLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, i ) )
#define SCNiLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, i ) )
#define SCNiFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, i ) )
#define SCNiFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, i ) )
#define SCNiFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, i ) )
#define SCNiFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, i ) )
#define SCNiMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, i ) )
#define SCNiPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, i ) )
#define SCNo8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, o ) )
#define SCNo16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, o ) )
#define SCNo32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, o ) )
#define SCNo64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, o ) )
#define SCNoLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, o ) )
#define SCNoLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, o ) )
#define SCNoLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, o ) )
#define SCNoLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, o ) )
#define SCNoFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, o ) )
#define SCNoFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, o ) )
#define SCNoFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, o ) )
#define SCNoFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, o ) )
#define SCNoMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, o ) )
#define SCNoPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, o ) )
#define SCNu8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, u ) )
#define SCNu16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, u ) )
#define SCNu32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, u ) )
#define SCNu64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, u ) )
#define SCNuLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, u ) )
#define SCNuLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, u ) )
#define SCNuLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, u ) )
#define SCNuLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, u ) )
#define SCNuFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, u ) )
#define SCNuFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, u ) )
#define SCNuFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, u ) )
#define SCNuFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, u ) )
#define SCNuMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, u ) )
#define SCNuPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, u ) )
#define SCNx8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, x ) )
#define SCNx16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, x ) )
#define SCNx32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, x ) )
#define SCNx64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, x ) )
#define SCNxLEAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_8_CONV, x ) )
#define SCNxLEAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_16_CONV, x ) )
#define SCNxLEAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_32_CONV, x ) )
#define SCNxLEAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_64_CONV, x ) )
#define SCNxFAST8 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST8_CONV, x ) )
#define SCNxFAST16 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST16_CONV, x ) )
#define SCNxFAST32 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST32_CONV, x ) )
#define SCNxFAST64 _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_FAST64_CONV, x ) )
#define SCNxMAX _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_MAX_CONV, x ) )
#define SCNxPTR _PDCLIB_symbol2string( _PDCLIB_concat( _PDCLIB_PTR_CONV, x ) )
/* 7.8.2 Functions for greatest-width integer types */
/* Calculate the absolute value of j */
intmax_t imaxabs( intmax_t j );
/* Return quotient (quot) and remainder (rem) of an integer division in the
imaxdiv_t struct.
*/
imaxdiv_t imaxdiv( intmax_t numer, intmax_t denom );
/* Seperate 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.
*/
intmax_t strtoimax( const char * restrict nptr, char * * restrict endptr, int base );
uintmax_t strtoumax( const char * restrict nptr, char * * restrict endptr, int base );
/* TODO: wcstoimax(), wcstoumax() */
CPP_CHECK_END

View File

@@ -0,0 +1,18 @@
#pragma once
/* 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.
*/
#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 ^=

View File

@@ -0,0 +1,57 @@
#pragma once
/* Auxiliary PDCLib code <aux.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* -------------------------------------------------------------------------- */
/* 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). */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* 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
#ifdef __cplusplus
#define restrict __restrict__
#endif
#ifndef __STDC_HOSTED__
#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)!
#elif __STDC_HOSTED__ == 0
#define _PDCLIB_HOSTED 0
#elif __STDC_HOSTED__ == 1
#define _PDCLIB_HOSTED 1
#else
#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)!
#endif
/* -------------------------------------------------------------------------- */
/* Helper macros: */
/* _PDCLIB_cc( x, y ) concatenates two preprocessor tokens without extending */
/* _PDCLIB_concat( x, y ) concatenates two preprocessor tokens with extending */
/* _PDCLIB_static_assert( e, m ) does a compile-time assertion of expression */
/* e, with m as the failure message. */
/* _PDCLIB_TYPE_SIGNED( type ) resolves to true if type is signed. */
/* _PDCLIB_TWOS_COMPLEMENT( type ) resolves to true if two's complement is */
/* used for type. */
/* -------------------------------------------------------------------------- */
#define _PDCLIB_cc( x, y ) x ## y
#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y )
#define _PDCLIB_static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) }
#define _PDCLIB_TYPE_SIGNED( type ) (((type) -1) < 0)
#define _PDCLIB_TWOS_COMPLEMENT( type ) ((type) ~ (type) 0 < 0 )
#define _PDCLIB_symbol2value( x ) #x
#define _PDCLIB_symbol2string( x ) _PDCLIB_symbol2value( x )

View File

@@ -0,0 +1,336 @@
#pragma once
/* Internal PDCLib configuration <config.h>
(Generic Template)
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <j6libc/int_widths.h>
/* -------------------------------------------------------------------------- */
/* Misc */
/* -------------------------------------------------------------------------- */
/* The character (sequence) your platform uses as newline. */
#define _PDCLIB_endl "\n"
/* 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 );
/* -------------------------------------------------------------------------- */
/* Integers */
/* -------------------------------------------------------------------------- */
/* Assuming 8-bit char, two's-complement architecture here. 'short' being */
/* 16 bit, 'int' being either 16, 32 or 64 bit, 'long' being either 32 or 64 */
/* bit (but 64 bit only if 'int' is 32 bit), and 'long long' being 64 bit if */
/* 'long' is not, 64 or 128 bit otherwise. */
/* Author is quite willing to support other systems but would like to hear of */
/* interest in such support and details on the to-be-supported architecture */
/* first, before going to lengths about it. */
/* -------------------------------------------------------------------------- */
/* Set to 0 if your 'char' type is unsigned. */
#ifdef __CHAR_UNSIGNED__
#define _PDCLIB_CHAR_SIGNED 0
#else
#define _PDCLIB_CHAR_SIGNED 1
#endif
/* Width of the integer types short, int, long, and long long, in bytes. */
/* SHRT == 2, INT >= SHRT, LONG >= INT >= 4, LLONG >= LONG - check your */
/* compiler manuals. */
#define _PDCLIB_SHRT_BYTES 2
#define _PDCLIB_INT_BYTES 4
#ifdef __LP64__
#define _PDCLIB_LONG_BYTES 8
#else
#define _PDCLIB_LONG_BYTES 4
#endif
#define _PDCLIB_LLONG_BYTES 8
/* <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;
};
/* <inttypes.h> defines imaxdiv(), which is equivalent to the div() function */
/* family (see further above) with intmax_t as basis. */
struct _PDCLIB_imaxdiv_t
{
intmax_t quot;
intmax_t rem;
};
/* -------------------------------------------------------------------------- */
/* Time types */
/* -------------------------------------------------------------------------- */
/* See <time.h> for a couple of comments on these types and their semantics. */
#define _PDCLIB_time long
#define _PDCLIB_clock long
#define _PDCLIB_CLOCKS_PER_SEC 1000000
#define _PDCLIB_TIME_UTC 1
/* -------------------------------------------------------------------------- */
/* 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
/* Whether the implementation uses exact-width precision (0), promotes float
to double (1), or promotes float and double to long double (2). (-1)
signifies indeterminable behaviour, any other value implementation-specific
behaviour.
*/
#define _PDCLIB_FLT_EVAL_METHOD -1
/* "Number of the decimal digits (n), such that any floating-point number in the
widest supported floating type with p(max) radix (b) digits can be rounded to
a floating-point number with (n) decimal digits and back again without change
to the value p(max) log(10)b if (b) is a power of 10, [1 + p(max) log(10)b]
otherwise."
64bit IEC 60559 double format (53bit mantissa) is DECIMAL_DIG 17.
80bit IEC 60559 double-extended format (64bit mantissa) is DECIMAL_DIG 21.
*/
#define _PDCLIB_DECIMAL_DIG 17
/* -------------------------------------------------------------------------- */
/* 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__ )
/* 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 config.h. Using the existing one as-is will not work.
#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 glue.h. */
/* -------------------------------------------------------------------------- */
/* Memory management -------------------------------------------------------- */
/* Set this to the page size of your OS. If your OS does not support paging, set
to an appropriate value. (Too small, and malloc() will call the kernel too
often. Too large, and you will waste memory.)
*/
#define _PDCLIB_PAGESIZE 4096
/* Set this to the minimum memory node size. Any malloc() for a smaller size
will be satisfied by a malloc() of this size instead (to avoid excessive
fragmentation).
*/
#define _PDCLIB_MINALLOC 8
/* I/O ---------------------------------------------------------------------- */
/* The type of the file descriptor returned by _PDCLIB_open(). */
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 can open simultaneously. Must
be at least 8. Depends largely on how the bookkeeping is done by fopen() /
freopen() / fclose(). The example implementation limits the number of open
files only by 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, we 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); anything larger would make applications relying on
this capability dependent on implementation-defined behaviour (not good).
*/
#define _PDCLIB_UNGETCBUFSIZE 1
/* 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
to "translate" between errno values used by the hosting operating system 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 the 'errno == EISDIR', and set '_PDCLIB_errno = _PDCLIB_EPERM'. Anyone
using PDCLib's <errno.h> will "see" EPERM instead of EISDIR (the _PDCLIB_*
prefix removed by <errno.h> mechanics).
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, as to avoid confusion.
The standard only defines three distinct errno values: ERANGE, EDOM, and
EILSEQ. The standard leaves it up to "the implementation" whether there are
any more beyond those three. There is some controversy as to whether errno is
such a good idea at all, so you might want to come up with a different error
reporting facility for your platform. Since errno values beyond the three
defined by the standard are not portable anyway (unless you look at POSIX),
having your own error reporting facility would not hurt anybody either.
*/
#define _PDCLIB_ERANGE 1
#define _PDCLIB_EDOM 2
#define _PDCLIB_EILSEQ 3
#define _PDCLIB_ENOMEM 12
#define _PDCLIB_EINVAL 22
/* The following is not strictly "configuration", but there is no better place
to explain it than here.
PDCLib strives to be as generic as possible, so by default it does NOT define
any values beyond the three standard ones above, even where it would have
been prudent and convenient to do so. Any errno "caught" from the host OS,
and some internal error conditions as well, are all lumped together into the
value of '_PDCLIB_ERROR'.
'_PDCLIB_ERROR' is STRICLY meant as a PLACEHOLDER only.
You should NEVER ship an adaption of PDCLib still using that particular
value. You should NEVER write code that *tests* for that value. Indeed it is
not even conforming, since errno values should be defined as beginning with
an uppercase 'E', and there is no mechanics in <errno.h> to unmask that
particular value (for exactly that reason).
There also is no error message available for this value through either the
strerror() or perror() functions. It is being reported as "unknown" error.
The idea is that you scan the source of PDCLib for occurrences of this macro
and replace _PDCLIB_ERROR with whatever additional errno value you came up
with for your platform.
If you cannot find it within you to do that, tell your clients to check for
an errno value larger than zero. That, at least, would be standard compliant
(and fully portable).
*/
#define _PDCLIB_ERROR 4
/* The maximum value that errno can be set to. 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.) */
/* Default is 4 (0, ERANGE, EDOM, EILSEQ). */
#define _PDCLIB_ERRNO_MAX 4
/* 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

View File

@@ -0,0 +1,9 @@
#pragma once
#ifdef __cplusplus
#define CPP_CHECK_BEGIN extern "C" {
#define CPP_CHECK_END }
#else
#define CPP_CHECK_BEGIN
#define CPP_CHECK_END
#endif

View File

@@ -0,0 +1,67 @@
#pragma once
/* OS glue functions declaration <glue.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include "j6libc/int.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 config.h. */
/* -------------------------------------------------------------------------- */
/* stdlib.h */
/* A system call that terminates the calling process, returning a given status
to the environment.
*/
_Noreturn void _PDCLIB_Exit( int status );
/* A system call that adds n pages of memory to the process heap (if n is
positive), or releases n pages from the process heap (if n is negative).
Return a (void *) pointing to the *former* end-of-heap if successful, NULL
otherwise.
*/
void * _PDCLIB_allocpages( int n );
/* 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_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.
*/
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.
*/
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.
*/
int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, int64_t offset, int whence );
/* A system call that closes a file identified by given file descriptor. Return
zero on success, non-zero otherwise.
*/
int _PDCLIB_close( _PDCLIB_fd_t fd );
/* 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.
*/
int _PDCLIB_rename( const char * old, const char * new );

View File

@@ -0,0 +1,347 @@
#pragma once
/* PDCLib internal integer logic <int.h>
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* -------------------------------------------------------------------------- */
/* 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 <stdbool.h>
#include "j6libc/config.h"
#include "j6libc/cpp.h"
#include "j6libc/aux.h"
#include "j6libc/int_widths.h"
#include "j6libc/size_t.h"
#include "j6libc/wchar_t.h"
CPP_CHECK_BEGIN
/* -------------------------------------------------------------------------- */
/* 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 8u
#define _PDCLIB_FWRITE 16u
#define _PDCLIB_FAPPEND 32u
#define _PDCLIB_FRW 64u
#define _PDCLIB_FBIN 128u
/* Internal flags, made to fit the same status field as the flags above. */
/* -------------------------------------------------------------------------- */
/* free() the buffer memory on closing (false for user-supplied buffer) */
#define _PDCLIB_FREEBUFFER 512u
/* stream has encountered error / EOF */
#define _PDCLIB_ERRORFLAG 1024u
#define _PDCLIB_EOFFLAG 2048u
/* stream is wide-oriented */
#define _PDCLIB_WIDESTREAM 4096u
/* stream is byte-oriented */
#define _PDCLIB_BYTESTREAM 8192u
/* file associated with stream should be remove()d on closing (tmpfile()) */
#define _PDCLIB_DELONCLOSE 16384u
/* stream handle should not be free()d on close (stdin, stdout, stderr) */
#define _PDCLIB_STATIC 32768u
/* Position / status structure for getpos() / fsetpos(). */
struct _PDCLIB_fpos_t
{
uint64_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 */
size_t bufsize; /* Size of buffer */
size_t bufidx; /* Index of current position in buffer */
size_t bufend; /* Index of last pre-read character in buffer */
struct _PDCLIB_fpos_t pos; /* Offset and multibyte parsing state */
size_t ungetidx; /* Number of ungetc()'ed characters */
unsigned char * ungetbuf; /* ungetc() buffer */
unsigned int status; /* Status flags; see above */
/* multibyte parsing status to be added later */
char * filename; /* Name the current stream has been opened with */
struct _PDCLIB_file_t * next; /* Pointer to next struct (internal) */
};
/* -------------------------------------------------------------------------- */
/* Various <time.h> internals */
/* -------------------------------------------------------------------------- */
typedef _PDCLIB_time _PDCLIB_time_t;
typedef _PDCLIB_clock _PDCLIB_clock_t;
/* -------------------------------------------------------------------------- */
/* 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 );
};
/* Structures required by malloc(), realloc(), and free(). */
struct _PDCLIB_headnode_t
{
struct _PDCLIB_memnode_t * first;
struct _PDCLIB_memnode_t * last;
};
struct _PDCLIB_memnode_t
{
size_t size;
struct _PDCLIB_memnode_t * next;
};
/* Status structure required by _PDCLIB_print(). */
struct _PDCLIB_status_t
{
int base; /* base to which the value shall be converted */
int_fast32_t flags; /* flags and length modifiers */
size_t n; /* print: maximum characters to be written */
/* scan: number matched conversion specifiers */
size_t i; /* number of characters read/written */
size_t current;/* chars read/written in the CURRENT conversion */
char * s; /* *sprintf(): target buffer */
/* *sscanf(): source string */
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(). */
intmax_t _PDCLIB_atomax( const char * s );
/* Two helper functions used by strtol(), strtoul() and long long variants. */
const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base );
uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, uintmax_t error, uintmax_t limval, int limdigit, char * sign );
/* 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.
*/
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
*/
const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status );
/* Parsing any fopen() style filemode string into a number of flags. */
unsigned int _PDCLIB_filemode( const char * mode );
/* 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.
*/
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.
*/
int _PDCLIB_prepwrite( struct _PDCLIB_file_t * stream );
/* Closing all streams on program exit */
void _PDCLIB_closeall( void );
/* Check if a given year is a leap year. Parameter is offset to 1900. */
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.
*/
char * _PDCLIB_load_lines( struct _PDCLIB_file_t * fh, size_t lines );
/* -------------------------------------------------------------------------- */
/* errno */
/* -------------------------------------------------------------------------- */
/* 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>.
*/
extern int _PDCLIB_errno;
/* A mechanism for delayed evaluation. (Not sure if this is really necessary, so
no detailed documentation on the "why".)
*/
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 << __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;
struct _PDCLIB_lc_ctype_entry_t
{
uint16_t flags;
unsigned char upper;
unsigned char lower;
};
struct _PDCLIB_lc_ctype_t
{
int alloced;
int digits_low;
int digits_high;
int Xdigits_low;
int Xdigits_high;
int xdigits_low;
int xdigits_high;
struct _PDCLIB_lc_ctype_entry_t * entry;
};
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;
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;
struct _PDCLIB_lc_lconv_numeric_t * _PDCLIB_load_lc_numeric( const char * path, const char * locale );
struct _PDCLIB_lc_lconv_monetary_t * _PDCLIB_load_lc_monetary( const char * path, const char * locale );
struct _PDCLIB_lc_collate_t * _PDCLIB_load_lc_collate( const char * path, const char * locale );
struct _PDCLIB_lc_ctype_t * _PDCLIB_load_lc_ctype( const char * path, const char * locale );
struct _PDCLIB_lc_time_t * _PDCLIB_load_lc_time( const char * path, const char * locale );
struct _PDCLIB_lc_messages_t * _PDCLIB_load_lc_messages( const char * path, const char * locale );
/* -------------------------------------------------------------------------- */
/* Sanity checks */
/* -------------------------------------------------------------------------- */
_PDCLIB_static_assert( sizeof( short ) == _PDCLIB_SHRT_BYTES, "Compiler disagrees on _PDCLIB_SHRT_BYTES." );
_PDCLIB_static_assert( sizeof( int ) == _PDCLIB_INT_BYTES, "Compiler disagrees on _PDCLIB_INT_BYTES." );
_PDCLIB_static_assert( sizeof( long ) == _PDCLIB_LONG_BYTES, "Compiler disagrees on _PDCLIB_LONG_BYTES." );
_PDCLIB_static_assert( sizeof( long long ) == _PDCLIB_LLONG_BYTES, "Compiler disagrees on _PDCLIB_LLONG_BYTES." );
_PDCLIB_static_assert( ( (char)-1 < 0 ) == _PDCLIB_CHAR_SIGNED, "Compiler disagrees on _PDCLIB_CHAR_SIGNED." );
_PDCLIB_static_assert( sizeof( sizeof( int ) ) == sizeof( size_t ), "Compiler disagrees on size_t." );
_PDCLIB_static_assert( sizeof( wchar_t ) == sizeof( L'x' ), "Compiler disagrees on _PDCLIB_wchar." );
_PDCLIB_static_assert( sizeof( void * ) == sizeof( intptr_t ), "Compiler disagrees on intptr." );
_PDCLIB_static_assert( sizeof( &_PDCLIB_digits[1] - &_PDCLIB_digits[0] ) == sizeof( ptrdiff_t ), "Compiler disagrees on ptrdiff_t." );
CPP_CHECK_END

View File

@@ -0,0 +1,57 @@
#pragma once
/* Type definitions: fixed-width integral types */
/* 7.18.1.1 Exact-width integer types. */
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
/* 7.18.1.2 Minimum-width integer types */
/* You are allowed to add more types here, e.g. int_least24_t. For the standard
types, int_leastN_t is equivalent to the corresponding exact type intN_t by
definition.
*/
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ 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 __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
/* 7.18.1.4 Integer types capable of holding object pointers */
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
/* 7.18.1.5 Greatest-width integer types */
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;

View File

@@ -0,0 +1,14 @@
#pragma once
#if __has_include("__stddef_max_align_t.h")
#include "__stddef_max_align_t.h"
#elif __BIGGEST_ALIGNMENT__ == __SIZEOF_LONG_DOUBLE__
typedef long double max_align_t;
#elif __BIGGEST_ALIGNMENT__ == __SIZEOF_DOUBLE__
typedef double max_align_t;
#elif __BIGGEST_ALIGNMENT__ == __SIZEOF_LONG_LONG__
typedef long long max_align_t;
#else
#error Can't figure out size of max_align_t!
#endif

View File

@@ -0,0 +1,6 @@
#pragma once
/* Constant definition: NULL */
#ifndef NULL
#define NULL 0
#endif

View File

@@ -0,0 +1,14 @@
#pragma once
/* Type definition: sig_atomic_t */
#if __is_identifier(sig_atomic_t)
#if __SIG_ATOMIC_WIDTH__ == 16
typedef int16_t sig_atomic_t;
#elif __SIG_ATOMIC_WIDTH__ == 32
typedef int32_t sig_atomic_t;
#elif __SIG_ATOMIC_WIDTH__ == 64
typedef int64_t sig_atomic_t;
#else
#error "Unknown size of sig_atomic_t" __SIG_ATOMIC_WIDTH__
#endif
#endif

View File

@@ -0,0 +1,6 @@
#pragma once
/* Type definition: size_t */
#if __is_identifier(size_t)
typedef __SIZE_TYPE__ size_t;
#endif

View File

@@ -0,0 +1,6 @@
#pragma once
/* Type definition: wchar_t */
#if __is_identifier(wchar_t)
typedef __WCHAR_TYPE__ wchar_t;
#endif

View File

@@ -0,0 +1,6 @@
#pragma once
/* Type definitions: wctype_t wctrans_t */
typedef uint32_t wctrans_t;
typedef uint32_t wctype_t ;

View File

@@ -0,0 +1,5 @@
#pragma once
/* Type definition: wint_t */
typedef __WINT_TYPE__ wint_t;

View File

@@ -0,0 +1,36 @@
#pragma once
/* 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.
*/
#include "j6libc/int.h"
/* TODO: Defined to 1 as multibyte characters are not supported yet. */
#define MB_LEN_MAX 1
#define SCHAR_MAX __SCHAR_MAX__
#define SCHAR_MIN ((-SCHAR_MAX) - 1)
#define UCHAR_MAX (((unsigned char)SCHAR_MAX << 1) | 1)
#define CHAR_BIT __CHAR_BIT__
#define CHAR_MAX SCHAR_MAX
#define CHAR_MIN SCHAR_MIN
#define SHRT_MAX __SHRT_MAX__
#define SHRT_MIN ((-SHRT_MAX) - 1)
#define USHRT_MAX (((unsigned short)SHRT_MAX << 1) | 1)
#define INT_MAX __INT_MAX__
#define INT_MIN ((-INT_MAX) - 1)
#define UINT_MAX (((unsigned int)INT_MAX << 1) | 1)
#define LONG_MAX __LONG_MAX__
#define LONG_MIN ((-LONG_MAX) - 1)
#define ULONG_MAX (((unsigned long)LONG_MAX << 1) | 1)
#define LLONG_MAX __LONG_LONG_MAX__
#define LLONG_MIN ((-LLONG_MAX) - 1)
#define ULLONG_MAX (((unsigned long long)LLONG_MAX << 1) | 1)

View File

@@ -0,0 +1,96 @@
#pragma once
/* 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.
*/
#include "j6libc/cpp.h"
#include "j6libc/int.h"
#include "j6libc/null.h"
CPP_CHECK_BEGIN
/* The structure returned by localeconv().
The values for *_sep_by_space:
0 - no space
1 - if symbol and sign are adjacent, a space seperates them from the value;
otherwise a space seperates the symbol from the value
2 - if symbol and sign are adjacent, a space seperates them; otherwise a
space seperates 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 seperating 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 seperated by space from pos. qty. */ /* LC_MONETARY */
char n_sep_by_space; /* if it is seperated 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.
*/
char * setlocale( int category, const char * locale );
/* Returns a struct lconv initialized to the values appropriate for the current
locale setting.
*/
struct lconv * localeconv( void );
CPP_CHECK_END

View File

@@ -0,0 +1,86 @@
#pragma once
/* Signal 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.
*/
#include "j6libc/config.h"
#include "j6libc/cpp.h"
#include "j6libc/sig_atomic_t.h"
CPP_CHECK_BEGIN
/* 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
typedef void (*sighandler_t)(int);
/* 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 (sighandler_t)0
#define SIG_ERR (sighandler_t)-1
#define SIG_IGN (sighandler_t)1
/* 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.
*/
sighandler_t signal( int sig, sighandler_t func );
/* 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. */
int raise( int sig );
CPP_CHECK_END

View File

@@ -0,0 +1,12 @@
#pragma once
/* 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.
*/
#define alignas _Alignas
#define alignof _Alignof
#define __alignas_is_defined 1
#define __alignof_is_defined 1

View File

@@ -0,0 +1,15 @@
#pragma once
/* 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.
*/
#include "j6libc/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 )

View File

@@ -0,0 +1,14 @@
#pragma once
/* 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 __cplusplus
#define bool _Bool
#define true 1
#define false 0
#endif
#define __bool_true_false_are_defined 1

View File

@@ -0,0 +1,22 @@
#pragma once
/* 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.
*/
#include "j6libc/int.h"
#include "j6libc/null.h"
#include "j6libc/max_align_t.h"
#include "j6libc/size_t.h"
#include "j6libc/wchar_t.h"
typedef __PTRDIFF_TYPE__ ptrdiff_t;
#if ! __has_include("__stddef_max_align_t.h")
typedef long double max_align_t;
#endif
#ifndef offsetof
#define offsetof( type, member ) _PDCLIB_offsetof( type, member )
#endif

View File

@@ -0,0 +1,151 @@
#pragma once
/* 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.
*/
/* 7.18.2 Limits of specified-width integer types */
#include <j6libc/int.h>
#include <j6libc/int_widths.h>
#ifdef __cplusplus
#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 */
#define INT8_MAX __INT8_MAX__
#define INT8_MIN ((-INT8_MAX) - 1)
#define UINT8_MAX __UINT8_MAX__
#define INT16_MAX __INT16_MAX__
#define INT16_MIN ((-INT16_MAX) - 1)
#define UINT16_MAX __UINT16_MAX__
#define INT32_MAX __INT32_MAX__
#define INT32_MIN ((-INT32_MAX) - 1)
#define UINT32_MAX __UINT32_MAX__
#define INT64_MAX __INT64_MAX__
#define INT64_MIN ((-INT64_MAX) - 1)
#define UINT64_MAX __UINT64_MAX__
/* 7.18.2.2 Limits of minimum-width integer types */
/* For the standard widths, least and exact types are equivalent.
You are allowed to add more types here, e.g. int_least24_t.
*/
#define INT_LEAST8_MAX __INT_LEAST8_MAX__
#define INT_LEAST8_MIN ((-INT_LEAST8_MAX) - 1)
#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
#define INT_LEAST16_MAX __INT_LEAST16_MAX__
#define INT_LEAST16_MIN ((-INT_LEAST16_MAX) - 1)
#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
#define INT_LEAST32_MAX __INT_LEAST32_MAX__
#define INT_LEAST32_MIN ((-INT_LEAST32_MAX) - 1)
#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
#define INT_LEAST64_MAX __INT_LEAST64_MAX__
#define INT_LEAST64_MIN ((-INT_LEAST64_MAX) - 1)
#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
/* 7.18.2.3 Limits of fastest minimum-width integer types */
#define INT_FAST8_MAX __INT_FAST8_MAX__
#define INT_FAST8_MIN ((-INT_FAST8_MAX) - 1)
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
#define INT_FAST16_MAX __INT_FAST16_MAX__
#define INT_FAST16_MIN ((-INT_FAST16_MAX) - 1)
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
#define INT_FAST32_MAX __INT_FAST32_MAX__
#define INT_FAST32_MIN ((-INT_FAST32_MAX) - 1)
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
#define INT_FAST64_MAX __INT_FAST64_MAX__
#define INT_FAST64_MIN ((-INT_FAST64_MAX) - 1)
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
/* 7.18.2.4 Limits of integer types capable of holding object pointers */
#define INTPTR_MAX __INTPTR_MAX__
#define INTPTR_MIN ((-INTPTR_MAX) - 1)
#define UINTPTR_MAX __UINTPTR_MAX__
/* 7.18.2.5 Limits of greatest-width integer types */
#define INTMAX_MAX __INTMAX_MAX__
#define INTMAX_MIN ((-INTMAX_MAX) - 1)
#define UINTMAX_MAX __UINTMAX_MAX__
/* 7.18.3 Limits of other integer types */
#define PTRDIFF_MAX __PTRDIFF_MAX__
#define PTRDIFF_MIN ((-PTRDIFF_MAX) - 1)
#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
#define SIG_ATOMIC_MIN ((-SIG_ATOMIC_MAX) - 1)
#define SIZE_MAX __SIZE_MAX__
#define WCHAR_MAX __WCHAR_MAX__
#define WCHAR_MIN ((-WCHAR_MAX) - 1)
#define WINT_MAX __WINT_MAX__
#define WINT_MIN ((-WINT_MAX) - 1)
#endif
/* 7.18.4 Macros for integer constants */
#ifdef __cplusplus
#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 */
/* As the minimum-width types - for the required widths of 8, 16, 32, and 64
bits - are expressed in terms of the exact-width types, the mechanism for
these macros is to append the literal of that exact-width type to the macro
parameter.
This is considered a hack, as the author is not sure his understanding of
the requirements of this macro is correct. Any input appreciated.
*/
/* Expand to an integer constant of specified value and type int_leastN_t */
#define INT8_C( value ) _PDCLIB_concat( value, __INT8_C_SUFFIX__ )
#define INT16_C( value ) _PDCLIB_concat( value, __INT16_C_SUFFIX__ )
#define INT32_C( value ) _PDCLIB_concat( value, __INT32_C_SUFFIX__ )
#define INT64_C( value ) _PDCLIB_concat( value, __INT64_C_SUFFIX__ )
/* Expand to an integer constant of specified value and type uint_leastN_t */
#define UINT8_C( value ) _PDCLIB_concat( value, __UINT8_C_SUFFIX__ )
#define UINT16_C( value ) _PDCLIB_concat( value, __UINT16_C_SUFFIX__ )
#define UINT32_C( value ) _PDCLIB_concat( value, __UINT32_C_SUFFIX__ )
#define UINT64_C( value ) _PDCLIB_concat( value, __UINT64_C_SUFFIX__ )
/* 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_concat( value, __INTMAX_C_SUFFIX__ )
/* Expand to an integer constant of specified value and type uintmax_t */
#define UINTMAX_C( value ) _PDCLIB_concat( value, __UINTMAX_C_SUFFIX__ )
#endif

View File

@@ -0,0 +1,779 @@
#pragma once
/* 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.
*/
#include "j6libc/cpp.h"
#include "j6libc/int.h"
#include "j6libc/null.h"
#include "j6libc/size_t.h"
CPP_CHECK_BEGIN
/* See setvbuf(), third argument */
#define _IOFBF 1
#define _IOLBF 2
#define _IONBF 4
/* The following are platform-dependant, and defined in 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").
*/
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).
*/
int rename( const char * src, const char * dst );
/* 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()).
*/
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().
*/
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.
*/
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.
*/
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.
*/
FILE * fopen( const char * restrict filename, const char * 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.)
*/
FILE * freopen( const char * restrict filename, const char * restrict mode, FILE * 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 ).
*/
void setbuf( FILE * restrict stream, char * 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.
*/
int setvbuf( FILE * restrict stream, char * 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.
*/
int fprintf( FILE * restrict stream, const char * 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.
*/
int fscanf( FILE * restrict stream, const char * restrict format, ... );
/* Equivalent to fprintf( stdout, format, ... ). */
int printf( const char * restrict format, ... );
/* Equivalent to fscanf( stdin, format, ... ). */
int scanf( const char * 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.
*/
int snprintf( char * restrict s, size_t n, const char * restrict format, ... );
/* Equivalent to fprintf( stdout, format, ... ), except that the result is
written into the buffer pointed to by s, instead of stdout.
*/
int sprintf( char * restrict s, const char * restrict format, ... );
/* Equivalent to fscanf( stdin, format, ... ), except that the input is read
from the buffer pointed to by s, instead of stdin.
*/
int sscanf( const char * restrict s, const char * 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>.
*/
int vfprintf( FILE * restrict stream, const char * 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>.
*/
int vfscanf( FILE * restrict stream, const char * 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>.
*/
int vprintf( const char * 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>.
*/
int vscanf( const char * 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>.
*/
int vsnprintf( char * restrict s, size_t n, const char * 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>.
*/
int vsprintf( char * restrict s, const char * 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>.
*/
int vsscanf( const char * restrict s, const char * 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.
*/
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.
*/
char * fgets( char * restrict s, int n, FILE * 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.
*/
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.
*/
int fputs( const char * restrict s, FILE * restrict stream );
/* Equivalent to fgetc( stream ), but may be overloaded by a macro that
evaluates its parameter more than once.
*/
int getc( FILE * stream );
/* Equivalent to fgetc( stdin ). */
int getchar( void );
/* Equivalent to fputc( c, stream ), but may be overloaded by a macro that
evaluates its parameter more than once.
*/
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.
*/
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.
*/
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.
*/
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.
*/
size_t fread( void * restrict ptr, size_t size, size_t nmemb, FILE * 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.
*/
size_t fwrite( const void * restrict ptr, size_t size, size_t nmemb, FILE * 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().
*/
int fgetpos( FILE * restrict stream, fpos_t * 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.
*/
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().
*/
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().
*/
long int ftell( FILE * stream );
/* Equivalent to (void)fseek( stream, 0L, SEEK_SET ), except that the error
indicator for the stream is also cleared.
*/
void rewind( FILE * stream );
/* Error-handling functions */
/* Clear the end-of-file and error indicators for the given stream. */
void clearerr( FILE * stream );
/* Return zero if the end-of-file indicator for the given stream is not set,
nonzero otherwise.
*/
int feof( FILE * stream );
/* Return zero if the error indicator for the given stream is not set, nonzero
otherwise.
*/
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).
*/
void perror( const char * s );
CPP_CHECK_END

View File

@@ -0,0 +1,232 @@
#pragma once
/* 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.
*/
#include "j6libc/cpp.h"
#include "j6libc/int.h"
#include "j6libc/null.h"
#include "j6libc/size_t.h"
#include "j6libc/wchar_t.h"
CPP_CHECK_BEGIN
/* Numeric conversion functions */
/* TODO: atof(), strtof(), strtod(), strtold() */
double atof( const char * nptr );
double strtod( const char * restrict nptr, char * * restrict endptr );
float strtof( const char * restrict nptr, char * * restrict endptr );
long double strtold( const char * restrict nptr, char * * restrict endptr );
/* Seperate 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.
*/
long int strtol( const char * restrict nptr, char * * restrict endptr, int base );
long long int strtoll( const char * restrict nptr, char * * restrict endptr, int base );
unsigned long int strtoul( const char * restrict nptr, char * * restrict endptr, int base );
unsigned long long int strtoull( const char * restrict nptr, char * * 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.)
*/
int atoi( const char * nptr );
long int atol( const char * nptr );
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;)
*/
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.
*/
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.
*/
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.
*/
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.
*/
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().
*/
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.
*/
void abort( 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.
*/
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.
*/
void exit( int status );
/* Normal process termination. Functions registered by atexit() (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.
*/
void _Exit( int status );
/* 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.
*/
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.
*/
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 the first matching element found, or NULL
if no match is found.
*/
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.
*/
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.
*/
int abs( int j );
long int labs( long int j );
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.
*/
div_t div( int numer, int denom );
ldiv_t ldiv( long int numer, long int denom );
lldiv_t lldiv( long long int numer, long long int denom );
/* TODO: Multibyte / wide character conversion functions */
/* TODO: Macro MB_CUR_MAX */
int mblen( const char * s, size_t n );
int mbtowc( wchar_t * restrict pwc, const char * restrict s, size_t n );
int wctomb( char * s, wchar_t wc );
size_t mbstowcs( wchar_t * restrict pwcs, const char * restrict s, size_t n );
size_t wcstombs( char * restrict s, const wchar_t * restrict pwcs, size_t n );
CPP_CHECK_END

View File

@@ -0,0 +1,8 @@
#pragma once
/* _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.
*/
#define noreturn _Noreturn

View File

@@ -0,0 +1,178 @@
#pragma once
/* 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.
*/
#include "j6libc/cpp.h"
#include "j6libc/int.h"
#include "j6libc/null.h"
#include "j6libc/size_t.h"
CPP_CHECK_BEGIN
/* 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.
*/
void * memcpy( void * restrict s1, const void * 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.
*/
void * memmove( void * restrict s1, const void * restrict s2, size_t n );
/* Copy the character array s2 (including terminating '\0' byte) into the
character array s1.
Returns the value of s1.
*/
char * strcpy( char * restrict s1, const char * 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.
*/
char * strncpy( char * restrict s1, const char * 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.
*/
char * strcat( char * restrict s1, const char * restrict s2 );
/* Append a maximum of n characters from the character array s1 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.
*/
char * strncat( char * restrict s1, const char * 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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
size_t strxfrm( char * restrict s1, const char * 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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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 seperator characters
which can differ from call to call. Leading seperators are skipped, the first
trailing seperator overwritten with '\0'.
Returns a pointer to the next token.
WARNING: This function uses static storage, and as such is not reentrant.
*/
char * strtok( char * restrict s1, const char * 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.
*/
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.
*/
char * strerror( int errnum );
/* Returns the length of the string s (excluding terminating '\0').
*/
size_t strlen( const char * s );
CPP_CHECK_END

View File

@@ -0,0 +1,105 @@
#pragma once
/* 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.
*/
#include "j6libc/cpp.h"
#include "j6libc/int.h"
#include "j6libc/null.h"
#include "j6libc/size_t.h"
CPP_CHECK_BEGIN
/* These are defined to be "real types capable of representing types", with
"range and precision of times representable in [them being] implementation-
defined".
As part of struct timespec (see below), time_t is further defined as "a
linear count of seconds", with potentially different semantics from a
"normal" time_t.
For sake of simplicity, we used just that (common) definition of "seconds
since epoch" as integer.
*/
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
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.
*/
clock_t clock( void );
/* Returns the difference between two calendar times in seconds. */
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.
*/
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.
*/
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.
*/
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".
*/
char * asctime( const struct tm * timeptr );
/* Equivalent to asctime( localtime( timer ) ). */
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.
*/
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.
*/
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.
*/
size_t strftime( char * restrict s, size_t maxsize, const char * restrict format, const struct tm * restrict timeptr );
CPP_CHECK_END

View File

@@ -0,0 +1,91 @@
#pragma once
/* Wide character functions <wchar.h>
*/
#include "j6libc/cpp.h"
#include "j6libc/int.h"
#include "j6libc/null.h"
#include "j6libc/size_t.h"
#include "j6libc/wchar_t.h"
#include "j6libc/wctype_t.h"
#include "j6libc/wint_t.h"
#include <stdarg.h>
#include <stdio.h>
CPP_CHECK_BEGIN
typedef unsigned long mbstate_t;
wint_t btowc(int);
int fwprintf(FILE *, const wchar_t *, ...);
int fwscanf(FILE *, const wchar_t *, ...);
int iswalnum(wint_t);
int iswalpha(wint_t);
int iswcntrl(wint_t);
int iswdigit(wint_t);
int iswgraph(wint_t);
int iswlower(wint_t);
int iswprint(wint_t);
int iswpunct(wint_t);
int iswspace(wint_t);
int iswupper(wint_t);
int iswxdigit(wint_t);
int iswctype(wint_t, wctype_t);
wint_t fgetwc(FILE *);
wchar_t *fgetws(wchar_t *, int, FILE *);
wint_t fputwc(wchar_t, FILE *);
int fputws(const wchar_t *, FILE *);
int fwide(FILE *, int);
wint_t getwc(FILE *);
wint_t getwchar(void);
int mbsinit(const mbstate_t *);
size_t mbrlen(const char *, size_t, mbstate_t *);
size_t mbrtowc(wchar_t *, const char *, size_t, mbstate_t *);
size_t mbsrtowcs(wchar_t *, const char **, size_t, mbstate_t *);
wint_t putwc(wchar_t, FILE *);
wint_t putwchar(wchar_t);
int swprintf(wchar_t *, size_t, const wchar_t *, ...);
int swscanf(const wchar_t *, const wchar_t *, ...);
wint_t towlower(wint_t);
wint_t towupper(wint_t);
wint_t ungetwc(wint_t, FILE *);
int vfwprintf(FILE *, const wchar_t *, va_list);
int vwprintf(const wchar_t *, va_list);
int vswprintf(wchar_t *, size_t, const wchar_t *, va_list);
size_t wcrtomb(char *, wchar_t, mbstate_t *);
wchar_t *wcscat(wchar_t *, const wchar_t *);
wchar_t *wcschr(const wchar_t *, wchar_t);
int wcscmp(const wchar_t *, const wchar_t *);
int wcscoll(const wchar_t *, const wchar_t *);
wchar_t *wcscpy(wchar_t *, const wchar_t *);
size_t wcscspn(const wchar_t *, const wchar_t *);
size_t wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *);
size_t wcslen(const wchar_t *);
wchar_t *wcsncat(wchar_t *, const wchar_t *, size_t);
int wcsncmp(const wchar_t *, const wchar_t *, size_t);
wchar_t *wcsncpy(wchar_t *, const wchar_t *, size_t);
wchar_t *wcspbrk(const wchar_t *, const wchar_t *);
wchar_t *wcsrchr(const wchar_t *, wchar_t);
size_t wcsrtombs(char *, const wchar_t **, size_t, mbstate_t *);
size_t wcsspn(const wchar_t *, const wchar_t *);
wchar_t *wcsstr(const wchar_t *, const wchar_t *);
double wcstod(const wchar_t *, wchar_t **);
wchar_t *wcstok(wchar_t *, const wchar_t *, wchar_t **);
long int wcstol(const wchar_t *, wchar_t **, int);
unsigned long int wcstoul(const wchar_t *, wchar_t **, int);
wchar_t *wcswcs(const wchar_t *, const wchar_t *);
int wcswidth(const wchar_t *, size_t);
size_t wcsxfrm(wchar_t *, const wchar_t *, size_t);
int wctob(wint_t);
wctype_t wctype(const char *);
int wcwidth(wchar_t);
wchar_t *wmemchr(const wchar_t *, wchar_t, size_t);
int wmemcmp(const wchar_t *, const wchar_t *, size_t);
wchar_t *wmemcpy(wchar_t *, const wchar_t *, size_t);
wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t);
wchar_t *wmemset(wchar_t *, wchar_t, size_t);
int wprintf(const wchar_t *, ...);
int wscanf(const wchar_t *, ...);
CPP_CHECK_END

View File

@@ -0,0 +1,138 @@
#pragma once
/* 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.
*/
#include "j6libc/cpp.h"
#include "j6libc/int.h"
#include "j6libc/wint_t.h"
CPP_CHECK_BEGIN
// wctrans_t
// 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 ) */
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.
*/
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.
*/
int iswblank( wint_t wc );
/* Returns true if the wide character is a control character. */
int iswcntrl( wint_t wc );
/* Returns true if the wide character is a decimal digit. Locale-
independent. */
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.
*/
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.
*/
int iswlower( wint_t wc );
/* Returns true for every printing wide character. */
int iswprint( wint_t wc );
/* Returns true for a locale-specific set of punctuation characters that
are neither whitespace nor alphanumeric.
*/
int iswpunct( wint_t wc );
/* Returns true for a locale-specific set of whitespace characters that
are neither alphanumeric, graphic, or punctuation.
*/
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.
*/
int iswupper( wint_t wc );
/* Returns true if the wide character is a hexadecimal digit. Locale-
independent. */
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).
*/
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.
*/
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.
*/
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.
*/
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).
*/
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.
*/
wctrans_t wctrans( const char * property );
CPP_CHECK_END

View File

@@ -0,0 +1,12 @@
/* imaxabs( intmax_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <inttypes.h>
intmax_t imaxabs( intmax_t j )
{
return ( j >= 0 ) ? j : -j;
}

View File

@@ -0,0 +1,15 @@
/* lldiv( long long int, long long int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <inttypes.h>
imaxdiv_t imaxdiv( intmax_t numer, intmax_t denom )
{
imaxdiv_t rc;
rc.quot = numer / denom;
rc.rem = numer % denom;
return rc;
}

View File

@@ -0,0 +1,27 @@
/* strtoimax( const char *, char * *, int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <limits.h>
#include <inttypes.h>
#include <stddef.h>
intmax_t strtoimax( const char * restrict nptr, char ** restrict endptr, int base )
{
intmax_t rc;
char sign = '+';
const char * p = _PDCLIB_strtox_prelim( nptr, &sign, &base );
if ( base < 2 || base > 36 ) return 0;
if ( sign == '+' )
{
rc = (intmax_t)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)INTMAX_MAX, (uintmax_t)( INTMAX_MAX / base ), (int)( INTMAX_MAX % base ), &sign );
}
else
{
rc = (intmax_t)_PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)INTMAX_MIN, (uintmax_t)( INTMAX_MIN / -base ), (int)( -( INTMAX_MIN % base ) ), &sign );
}
if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) nptr;
return ( sign == '+' ) ? rc : -rc;
}

View File

@@ -0,0 +1,20 @@
/* strtoumax( const char *, char * *, int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <limits.h>
#include <inttypes.h>
#include <stddef.h>
uintmax_t strtoumax( const char * restrict nptr, char ** restrict endptr, int base )
{
uintmax_t rc;
char sign = '+';
const char * p = _PDCLIB_strtox_prelim( nptr, &sign, &base );
if ( base < 2 || base > 36 ) return 0;
rc = _PDCLIB_strtox_main( &p, (unsigned)base, (uintmax_t)UINTMAX_MAX, (uintmax_t)( UINTMAX_MAX / base ), (int)( UINTMAX_MAX % base ), &sign );
if ( endptr != NULL ) *endptr = ( p != NULL ) ? (char *) p : (char *) nptr;
return ( sign == '+' ) ? rc : -rc;
}

View File

@@ -0,0 +1,10 @@
This directory holds various "internals" of PDCLib:
- definitions of helper functions not specified by the standard (hidden in the
_PDCLIB_* namespace);
- definitions of data objects, both internal (like _PDCLIB_digits) and specified by
the standard (_PDCLIB_errno);
- test drivers for functionality that does not have its own implementation
file to put the test driver in (stdarg).

View File

@@ -0,0 +1,16 @@
/* _PDCLIB_allocpages( int const )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is an example implementation of _PDCLIB_allocpages() fit for use with
POSIX kernels.
*/
#include "j6libc/glue.h"
void * _PDCLIB_allocpages( int const n )
{
return 0;
}

View File

@@ -0,0 +1,19 @@
/* _PDCLIB_assert( const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "j6libc/aux.h"
void _PDCLIB_assert( const char * const message1, const char * const function, const char * const message2 )
{
fputs( message1, stderr );
fputs( function, stderr );
fputs( message2, stderr );
abort();
}

View File

@@ -0,0 +1,25 @@
/* _PDCLIB_atomax( const char * )
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>
#include <ctype.h>
intmax_t _PDCLIB_atomax( const char * s )
{
intmax_t rc = 0;
char sign = '+';
const char * x;
/* TODO: In other than "C" locale, additional patterns may be defined */
while ( isspace( *s ) ) ++s;
if ( *s == '+' ) ++s;
else if ( *s == '-' ) sign = *(s++);
/* TODO: Earlier version was missing tolower() but was not caught by tests */
while ( ( x = memchr( _PDCLIB_digits, tolower(*(s++)), 10 ) ) != NULL )
{
rc = rc * 10 + ( x - _PDCLIB_digits );
}
return ( sign == '+' ) ? rc : -rc;
}

View File

@@ -0,0 +1,16 @@
/* _PDCLIB_close( _PDCLIB_fd_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is an example implementation of _PDCLIB_close() fit for use with POSIX
kernels.
*/
#include "j6libc/glue.h"
int _PDCLIB_close( int fd )
{
return -1;
}

View File

@@ -0,0 +1,21 @@
/* _PDCLIB_closeall( void )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
void _PDCLIB_closeall( void )
{
struct _PDCLIB_file_t * stream = _PDCLIB_filelist;
struct _PDCLIB_file_t * next;
while ( stream != NULL )
{
next = stream->next;
fclose( stream );
stream = next;
}
}

View File

@@ -0,0 +1,12 @@
/* _PDCLIB_digits
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include "j6libc/int.h"
const char _PDCLIB_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
/* For _PDCLIB/print.c only; obsolete with ctype.h */
const char _PDCLIB_Xdigits[] = "0123456789ABCDEF";

View File

@@ -0,0 +1,14 @@
/* _PDCLIB_errno
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include "j6libc/int.h"
int _PDCLIB_errno = 0;
int * _PDCLIB_errno_func()
{
return &_PDCLIB_errno;
}

View File

@@ -0,0 +1,54 @@
/* _PDCLIB_filemode( const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stddef.h>
/* Helper function that parses the C-style mode string passed to fopen() into
the PDCLib flags FREAD, FWRITE, FAPPEND, FRW (read-write) and FBIN (binary
mode).
*/
unsigned int _PDCLIB_filemode( const char * const mode )
{
unsigned rc = 0;
size_t i;
switch ( mode[0] )
{
case 'r':
rc |= _PDCLIB_FREAD;
break;
case 'w':
rc |= _PDCLIB_FWRITE;
break;
case 'a':
rc |= _PDCLIB_FAPPEND | _PDCLIB_FWRITE;
break;
default:
/* Other than read, write, or append - invalid */
return 0;
}
for ( i = 1; i < 4; ++i )
{
switch ( mode[i] )
{
case '+':
if ( rc & _PDCLIB_FRW ) return 0; /* Duplicates are invalid */
rc |= _PDCLIB_FRW;
break;
case 'b':
if ( rc & _PDCLIB_FBIN ) return 0; /* Duplicates are invalid */
rc |= _PDCLIB_FBIN;
break;
case '\0':
/* End of mode */
return rc;
default:
/* Other than read/write or binary - invalid. */
return 0;
}
}
/* Longer than three chars - invalid. */
return 0;
}

View File

@@ -0,0 +1,19 @@
/* _PDCLIB_fillbuffer( struct _PDCLIB_file_t * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is an example implementation of _PDCLIB_fillbuffer() fit for
use with POSIX kernels.
*/
#include <stdio.h>
#include "j6libc/glue.h"
int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream )
{
_PDCLIB_errno = _PDCLIB_ERROR;
stream->status |= _PDCLIB_ERRORFLAG;
return EOF;
}

View File

@@ -0,0 +1,19 @@
/* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is an example implementation of _PDCLIB_flushbuffer() fit for
use with POSIX kernels.
*/
#include <stdio.h>
#include "j6libc/glue.h"
int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream )
{
_PDCLIB_errno = _PDCLIB_ERROR;
stream->status |= _PDCLIB_ERRORFLAG;
return EOF;
}

View File

@@ -0,0 +1,14 @@
/* _PDCLIB_is_leap( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include "j6libc/int.h"
int _PDCLIB_is_leap( int year_offset )
{
/* year given as offset from 1900, matching tm.tm_year in <time.h> */
long long year = year_offset + 1900ll;
return ( ( year % 4 ) == 0 && ( ( year % 25 ) != 0 || ( year % 400 ) == 0 ) );
}

View File

@@ -0,0 +1,44 @@
/* _PDCLIB_load_lc_collate( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "j6libc/int.h"
struct _PDCLIB_lc_collate_t * _PDCLIB_load_lc_collate( const char * path, const char * locale )
{
struct _PDCLIB_lc_collate_t * rc = NULL;
const char * extension = "_collate.dat";
char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
if ( file )
{
FILE * fh;
strcpy( file, path );
strcat( file, locale );
strcat( file, extension );
if ( ( fh = fopen( file, "rb" ) ) != NULL )
{
if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_collate_t ) ) ) != NULL )
{
/* TODO: Collation data */
rc->alloced = 1;
}
fclose( fh );
}
free( file );
}
return rc;
}

View File

@@ -0,0 +1,74 @@
/* _PDCLIB_load_lc_ctype( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <inttypes.h>
#include <limits.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "j6libc/int.h"
struct _PDCLIB_lc_ctype_t * _PDCLIB_load_lc_ctype( const char * path, const char * locale )
{
struct _PDCLIB_lc_ctype_t * rc = NULL;
const char * extension = "_ctype.dat";
char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
if ( file )
{
FILE * fh;
strcpy( file, path );
strcat( file, locale );
strcat( file, extension );
if ( ( fh = fopen( file, "rb" ) ) != NULL )
{
if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_ctype_t ) ) ) != NULL )
{
struct _PDCLIB_lc_ctype_entry_t * entry;
if ( ( entry = malloc( sizeof( struct _PDCLIB_lc_ctype_entry_t ) * _PDCLIB_CHARSET_SIZE + 1 ) ) != NULL )
{
rc->entry = entry + 1;
rc->entry[ -1 ].flags = rc->entry[ -1 ].upper = rc->entry[ -1 ].lower = 0;
if ( fscanf( fh, "%x %x %x %x %x %x", &rc->digits_low, &_PDCLIB_lc_ctype.digits_high, &_PDCLIB_lc_ctype.Xdigits_low, &_PDCLIB_lc_ctype.Xdigits_high, &_PDCLIB_lc_ctype.xdigits_low, &_PDCLIB_lc_ctype.xdigits_high ) == 6 )
{
size_t i;
for ( i = 0; i < _PDCLIB_CHARSET_SIZE; ++i )
{
if ( fscanf( fh, "%hx %hhx %hhx", &rc->entry[ i ].flags, &rc->entry[ i ].upper, &rc->entry[ i ].lower ) != 3 )
{
fclose( fh );
free( file );
free( rc->entry - 1 );
free( rc );
return NULL;
}
}
}
rc->alloced = 1;
}
else
{
free( rc );
}
}
fclose( fh );
}
free( file );
}
return rc;
}

View File

@@ -0,0 +1,60 @@
/* _PDCLIB_load_lc_messages( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "j6libc/int.h"
struct _PDCLIB_lc_messages_t * _PDCLIB_load_lc_messages( const char * path, const char * locale )
{
struct _PDCLIB_lc_messages_t * rc = NULL;
const char * extension = "_messages.dat";
char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
if ( file )
{
FILE * fh;
strcpy( file, path );
strcat( file, locale );
strcat( file, extension );
if ( ( fh = fopen( file, "rb" ) ) != NULL )
{
if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_messages_t ) ) ) != NULL )
{
char * data = _PDCLIB_load_lines( fh, _PDCLIB_ERRNO_MAX );
if ( data != NULL )
{
size_t i;
for ( i = 0; i < _PDCLIB_ERRNO_MAX; ++i )
{
rc->errno_texts[ i ] = data;
data += strlen( data ) + 1;
}
rc->alloced = 1;
}
else
{
free( rc );
rc = NULL;
}
}
fclose( fh );
}
free( file );
}
return rc;
}

View File

@@ -0,0 +1,90 @@
/* _PDCLIB_load_lc_monetary( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "j6libc/int.h"
struct _PDCLIB_lc_lconv_monetary_t * _PDCLIB_load_lc_monetary( const char * path, const char * locale )
{
struct _PDCLIB_lc_lconv_monetary_t * rc = NULL;
const char * extension = "_monetary.dat";
char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
if ( file )
{
FILE * fh;
strcpy( file, path );
strcat( file, locale );
strcat( file, extension );
if ( ( fh = fopen( file, "rb" ) ) != NULL )
{
if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_lconv_monetary_t ) ) ) != NULL )
{
char buffer[ 14 ];
char * data = _PDCLIB_load_lines( fh, 7 );
if ( data != NULL )
{
if ( fread( buffer, 1, 14, fh ) == 14 )
{
rc->mon_decimal_point = data;
data += strlen( data ) + 1;
rc->mon_thousands_sep = data;
data += strlen( data ) + 1;
rc->mon_grouping = data;
data += strlen( data ) + 1;
rc->positive_sign = data;
data += strlen( data ) + 1;
rc->negative_sign = data;
data += strlen( data ) + 1;
rc->currency_symbol = data;
data += strlen( data ) + 1;
rc->int_curr_symbol = data;
rc->frac_digits = buffer[ 0 ];
rc->p_cs_precedes = buffer[ 1 ];
rc->n_cs_precedes = buffer[ 2 ];
rc->p_sep_by_space = buffer[ 3 ];
rc->n_sep_by_space = buffer[ 4 ];
rc->p_sign_posn = buffer[ 5 ];
rc->n_sign_posn = buffer[ 6 ];
rc->int_frac_digits = buffer[ 7 ];
rc->int_p_cs_precedes = buffer[ 8 ];
rc->int_n_cs_precedes = buffer[ 9 ];
rc->int_p_sep_by_space = buffer[ 10 ];
rc->int_n_sep_by_space = buffer[ 11 ];
rc->int_p_sign_posn = buffer[ 12 ];
rc->int_n_sign_posn= buffer[ 13 ];
}
else
{
free( data );
free( rc );
rc = NULL;
}
}
else
{
free( rc );
rc = NULL;
}
}
fclose( fh );
}
free( file );
}
return rc;
}

View File

@@ -0,0 +1,56 @@
/* _PDCLIB_load_lc_numeric( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "j6libc/int.h"
struct _PDCLIB_lc_lconv_numeric_t * _PDCLIB_load_lc_numeric( const char * path, const char * locale )
{
struct _PDCLIB_lc_lconv_numeric_t * rc = NULL;
const char * extension = "_numeric.dat";
char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
if ( file )
{
FILE * fh;
strcpy( file, path );
strcat( file, locale );
strcat( file, extension );
if ( ( fh = fopen( file, "rb" ) ) != NULL )
{
if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_lconv_numeric_t ) ) ) != NULL )
{
char * data = _PDCLIB_load_lines( fh, 3 );
if ( data != NULL )
{
rc->decimal_point = data;
data += strlen( data ) + 1;
rc->thousands_sep = data;
data += strlen( data ) + 1;
rc->grouping = data;
}
else
{
free( rc );
rc = NULL;
}
}
fclose( fh );
}
free( file );
}
return rc;
}

View File

@@ -0,0 +1,79 @@
/* _PDCLIB_load_lc_time( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "j6libc/int.h"
struct _PDCLIB_lc_time_t * _PDCLIB_load_lc_time( const char * path, const char * locale )
{
struct _PDCLIB_lc_time_t * rc = NULL;
const char * extension = "_time.dat";
char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
if ( file )
{
FILE * fh;
strcpy( file, path );
strcat( file, locale );
strcat( file, extension );
if ( ( fh = fopen( file, "rb" ) ) != NULL )
{
if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_time_t ) ) ) != NULL )
{
char * data = _PDCLIB_load_lines( fh, 44 );
if ( data != NULL )
{
size_t i;
for ( i = 0; i < 12; ++i )
{
rc->month_name_abbr[ i ] = data;
data += strlen( data ) + 1;
}
for ( i = 0; i < 12; ++i )
{
rc->month_name_full[ i ] = data;
data += strlen( data ) + 1;
}
for ( i = 0; i < 7; ++i )
{
rc->day_name_abbr[ i ] = data;
data += strlen( data ) + 1;
}
for ( i = 0; i < 7; ++i )
{
rc->day_name_full[ i ] = data;
data += strlen( data ) + 1;
}
rc->alloced = 1;
}
else
{
free( rc );
rc = NULL;
}
}
fclose( fh );
}
free( file );
}
return rc;
}

View File

@@ -0,0 +1,48 @@
/* _PDCLIB_load_lines( FILE *, 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 <stdio.h>
#include <stdlib.h>
char * _PDCLIB_load_lines( FILE * fh, size_t lines )
{
size_t required = 0;
long pos = ftell( fh );
char * rc = NULL;
int c;
/* Count the number of characters */
while ( lines && ( c = fgetc( fh ) ) != EOF )
{
if ( c == '\n' )
{
--lines;
}
++required;
}
if ( ! feof( fh ) )
{
if ( ( rc = malloc( required ) ) != NULL )
{
size_t i;
fseek( fh, pos, SEEK_SET );
fread( rc, 1, required, fh );
for ( i = 0; i < required; ++i )
{
if ( rc[ i ] == '\n' )
{
rc[ i ] = '\0';
}
}
}
}
return rc;
}

View File

@@ -0,0 +1,17 @@
/* _PDCLIB_open( const char * const, int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is an example implementation of _PDCLIB_open() fit for use with POSIX
kernels.
*/
#include "j6libc/glue.h"
int _PDCLIB_open( const char * const filename, unsigned int mode )
{
_PDCLIB_errno = _PDCLIB_ERROR;
return -1;
}

View File

@@ -0,0 +1,34 @@
/* _PDCLIB_prepread( struct _PDCLIB_file_t * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include "j6libc/glue.h"
int _PDCLIB_prepread( struct _PDCLIB_file_t * stream )
{
if ( ( stream->bufidx > stream->bufend ) ||
( stream->status & ( _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_ERRORFLAG | _PDCLIB_WIDESTREAM | _PDCLIB_EOFFLAG ) ) ||
! ( stream->status & ( _PDCLIB_FREAD | _PDCLIB_FRW ) ) )
{
/* Function called on illegal (e.g. output) stream.
See comments on implementation-defined errno values in
<config.h>.
*/
_PDCLIB_errno = _PDCLIB_ERROR;
stream->status |= _PDCLIB_ERRORFLAG;
return EOF;
}
stream->status |= _PDCLIB_FREAD | _PDCLIB_BYTESTREAM;
if ( ( stream->bufidx == stream->bufend ) && ( stream->ungetidx == 0 ) )
{
return _PDCLIB_fillbuffer( stream );
}
else
{
return 0;
}
}

View File

@@ -0,0 +1,25 @@
/* _PDCLIB_prepwrite( struct _PDCLIB_file_t * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
int _PDCLIB_prepwrite( struct _PDCLIB_file_t * stream )
{
if ( ( stream->bufidx < stream->bufend ) || ( stream->ungetidx > 0 ) ||
( stream->status & ( _PDCLIB_FREAD | _PDCLIB_ERRORFLAG | _PDCLIB_WIDESTREAM | _PDCLIB_EOFFLAG ) ) ||
! ( stream->status & ( _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) ) )
{
/* Function called on illegal (e.g. input) stream.
See the comments on implementation-defined errno values in
<config.h>.
*/
_PDCLIB_errno = _PDCLIB_ERROR;
stream->status |= _PDCLIB_ERRORFLAG;
return EOF;
}
stream->status |= _PDCLIB_FWRITE | _PDCLIB_BYTESTREAM;
return 0;
}

View File

@@ -0,0 +1,624 @@
/* _PDCLIB_print( const char *, struct _PDCLIB_status_t * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
/* Using an integer's bits as flags for both the conversion flags and length
modifiers.
*/
/* FIXME: one too many flags to work on a 16-bit machine, join some (e.g. the
width flags) into a combined field.
*/
#define E_minus (1<<0)
#define E_plus (1<<1)
#define E_alt (1<<2)
#define E_space (1<<3)
#define E_zero (1<<4)
#define E_done (1<<5)
#define E_char (1<<6)
#define E_short (1<<7)
#define E_long (1<<8)
#define E_llong (1<<9)
#define E_intmax (1<<10)
#define E_size (1<<11)
#define E_ptrdiff (1<<12)
#define E_pointer (1<<13)
#define E_ldouble (1<<14)
#define E_lower (1<<15)
#define E_unsigned (1<<16)
/* 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 )
static void intformat( intmax_t value, struct _PDCLIB_status_t * status )
{
/* At worst, we need two prefix characters (hex prefix). */
char preface[3] = "\0";
size_t preidx = 0;
if ( status->prec < 0 )
{
status->prec = 1;
}
if ( ( status->flags & E_alt ) && ( status->base == 16 || status->base == 8 ) && ( value != 0 ) )
{
/* Octal / hexadecimal prefix for "%#" conversions */
preface[ preidx++ ] = '0';
if ( status->base == 16 )
{
preface[ preidx++ ] = ( status->flags & E_lower ) ? 'x' : 'X';
}
}
if ( value < 0 )
{
/* Negative sign for negative values - at all times. */
preface[ preidx++ ] = '-';
}
else if ( ! ( status->flags & E_unsigned ) )
{
/* plus sign / extra space are only for unsigned conversions */
if ( status->flags & E_plus )
{
preface[ preidx++ ] = '+';
}
else if ( status->flags & E_space )
{
preface[ preidx++ ] = ' ';
}
}
{
/* At this point, status->current has the number of digits queued up.
Determine if we have a precision requirement to pad those.
*/
size_t prec_pads = ( (size_t)status->prec > status->current ) ? ( (size_t)status->prec - status->current ) : 0;
if ( ! ( status->flags & ( E_minus | E_zero ) ) )
{
/* Space padding is only done if no zero padding or left alignment
is requested. Calculate the number of characters that WILL be
printed, including any prefixes determined above.
*/
/* The number of characters to be printed, plus prefixes if any. */
/* This line contained probably the most stupid, time-wasting bug
I've ever perpetrated. Greetings to Samface, DevL, and all
sceners at Breakpoint 2006.
*/
size_t characters = preidx + ( ( status->current > (size_t)status->prec ) ? status->current : (size_t)status->prec );
if ( status->width > characters )
{
size_t i;
for ( i = 0; i < status->width - characters; ++i )
{
PUT( ' ' );
++(status->current);
}
}
}
/* Now we did the padding, do the prefixes (if any). */
preidx = 0;
while ( preface[ preidx ] != '\0' )
{
PUT( preface[ preidx++ ] );
++(status->current);
}
/* Do the precision padding if necessary. */
while ( prec_pads-- > 0 )
{
PUT( '0' );
++(status->current);
}
if ( ( ! ( status->flags & E_minus ) ) && ( status->flags & E_zero ) )
{
/* If field is not left aligned, and zero padding is requested, do
so.
*/
while ( status->current < status->width )
{
PUT( '0' );
++(status->current);
}
}
}
}
static void int2base( intmax_t value, struct _PDCLIB_status_t * status )
{
/* This function recursively converts a given integer value to a character
stream. The conversion is done under the control of a given status struct
and written either to a character string or a stream, depending on that
same status struct. The status struct also keeps the function from exceeding
snprintf() limits, and enables any necessary padding / prefixing of the
output once the number of characters to be printed is known, which happens
at the lowermost recursion level.
*/
/* Special case: zero value, zero precision -- no output (but padding) */
if ( status->current == 0 && value == 0 && status->prec == 0 )
{
intformat( value, status );
}
else
{
/* Registering the character being printed at the end of the function here
already so it will be taken into account when the deepestmost recursion
does the prefix / padding stuff.
*/
++(status->current);
if ( ( value / status->base ) != 0 )
{
/* More digits to be done - recurse deeper */
int2base( value / status->base, status );
}
else
{
/* We reached the last digit, the deepest point of our recursion, and
only now know how long the number to be printed actually is. Now we
have to do the sign, prefix, width, and precision padding stuff
before printing the numbers while we resurface from the recursion.
*/
intformat( value, status );
}
/* Recursion tail - print the current digit. */
int digit = value % status->base;
if ( digit < 0 )
{
digit *= -1;
}
if ( status->flags & E_lower )
{
/* Lowercase letters. Same array used for strto...(). */
PUT( _PDCLIB_digits[ digit ] );
}
else
{
/* Uppercase letters. Array only used here, only 0-F. */
PUT( _PDCLIB_Xdigits[ digit ] );
}
}
}
static void uint2base( uintmax_t value, struct _PDCLIB_status_t * status )
{
/* This function recursively converts a given integer value to a character
stream. The conversion is done under the control of a given status struct
and written either to a character string or a stream, depending on that
same status struct. The status struct also keeps the function from exceeding
snprintf() limits, and enables any necessary padding / prefixing of the
output once the number of characters to be printed is known, which happens
at the lowermost recursion level.
*/
/* Special case: zero value, zero precision -- no output (but padding) */
if ( status->current == 0 && value == 0 && status->prec == 0 )
{
intformat( value, status );
}
else
{
/* Registering the character being printed at the end of the function here
already so it will be taken into account when the deepestmost recursion
does the prefix / padding stuff.
*/
++(status->current);
if ( ( value / status->base ) != 0 )
{
/* More digits to be done - recurse deeper */
uint2base( value / status->base, status );
}
else
{
/* We reached the last digit, the deepest point of our recursion, and
only now know how long the number to be printed actually is. Now we
have to do the sign, prefix, width, and precision padding stuff
before printing the numbers while we resurface from the recursion.
*/
intformat( value, status );
}
/* Recursion tail - print the current digit. */
int digit = value % status->base;
if ( digit < 0 )
{
digit *= -1;
}
if ( status->flags & E_lower )
{
/* Lowercase letters. Same array used for strto...(). */
PUT( _PDCLIB_digits[ digit ] );
}
else
{
/* Uppercase letters. Array only used here, only 0-F. */
PUT( _PDCLIB_Xdigits[ digit ] );
}
}
}
static void stringformat( const char * s, struct _PDCLIB_status_t * status )
{
if ( status->flags & E_char )
{
status->prec = 1;
}
else
{
if ( status->prec < 0 )
{
status->prec = strlen( s );
}
else
{
int i;
for ( i = 0; i < status->prec; ++i )
{
if ( s[i] == 0 )
{
status->prec = i;
break;
}
}
}
}
if ( ! ( status->flags & E_minus ) && ( status->width > (size_t)status->prec ) )
{
while ( status->current < ( status->width - status->prec ) )
{
PUT( ' ' );
++(status->current);
}
}
while ( status->prec > 0 )
{
PUT( *(s++) );
--(status->prec);
++(status->current);
}
if ( status->flags & E_minus )
{
while ( status->width > status->current )
{
PUT( ' ' );
++(status->current);
}
}
}
const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status )
{
const char * orig_spec = spec;
if ( *(++spec) == '%' )
{
/* %% -> print single '%' */
PUT( *spec );
return ++spec;
}
/* Initializing status structure */
status->flags = 0;
status->base = 0;
status->current = 0;
status->width = 0;
status->prec = EOF;
/* First come 0..n flags */
do
{
switch ( *spec )
{
case '-':
/* left-aligned output */
status->flags |= E_minus;
++spec;
break;
case '+':
/* positive numbers prefixed with '+' */
status->flags |= E_plus;
++spec;
break;
case '#':
/* alternative format (leading 0x for hex, 0 for octal) */
status->flags |= E_alt;
++spec;
break;
case ' ':
/* positive numbers prefixed with ' ' */
status->flags |= E_space;
++spec;
break;
case '0':
/* right-aligned padding done with '0' instead of ' ' */
status->flags |= E_zero;
++spec;
break;
default:
/* not a flag, exit flag parsing */
status->flags |= E_done;
break;
}
} while ( ! ( status->flags & E_done ) );
/* Optional field width */
if ( *spec == '*' )
{
/* Retrieve width value from argument stack */
int width = va_arg( status->arg, int );
if ( width < 0 )
{
status->flags |= E_minus;
status->width = abs( width );
}
else
{
status->width = width;
}
++spec;
}
else
{
/* If a width is given, strtol() will return its value. If not given,
strtol() will return zero. In both cases, endptr will point to the
rest of the conversion specifier - just what we need.
*/
status->width = (int)strtol( spec, (char**)&spec, 10 );
}
/* Optional precision */
if ( *spec == '.' )
{
++spec;
if ( *spec == '*' )
{
/* Retrieve precision value from argument stack. A negative value
is as if no precision is given - as precision is initalized to
EOF (negative), there is no need for testing for negative here.
*/
status->prec = va_arg( status->arg, int );
++spec;
}
else
{
char * endptr;
status->prec = (int)strtol( spec, &endptr, 10 );
if ( spec == endptr )
{
/* Decimal point but no number - equals zero */
status->prec = 0;
}
spec = endptr;
}
/* Having a precision cancels out any zero flag. */
status->flags &= ~E_zero;
}
/* Optional length modifier
We step one character ahead in any case, and step back only if we find
there has been no length modifier (or step ahead another character if it
has been "hh" or "ll").
*/
switch ( *(spec++) )
{
case 'h':
if ( *spec == 'h' )
{
/* hh -> char */
status->flags |= E_char;
++spec;
}
else
{
/* h -> short */
status->flags |= E_short;
}
break;
case 'l':
if ( *spec == 'l' )
{
/* ll -> long long */
status->flags |= E_llong;
++spec;
}
else
{
/* k -> long */
status->flags |= E_long;
}
break;
case 'j':
/* j -> intmax_t, which might or might not be long long */
status->flags |= E_intmax;
break;
case 'z':
/* z -> size_t, which might or might not be unsigned int */
status->flags |= E_size;
break;
case 't':
/* t -> ptrdiff_t, which might or might not be long */
status->flags |= E_ptrdiff;
break;
case 'L':
/* L -> long double */
status->flags |= E_ldouble;
break;
default:
--spec;
break;
}
/* Conversion specifier */
switch ( *spec )
{
case 'd':
/* FALLTHROUGH */
case 'i':
status->base = 10;
break;
case 'o':
status->base = 8;
status->flags |= E_unsigned;
break;
case 'u':
status->base = 10;
status->flags |= E_unsigned;
break;
case 'x':
status->base = 16;
status->flags |= ( E_lower | E_unsigned );
break;
case 'X':
status->base = 16;
status->flags |= E_unsigned;
break;
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
break;
case 'a':
case 'A':
break;
case 'c':
/* TODO: wide chars. */
{
char c[1];
c[0] = (char)va_arg( status->arg, int );
status->flags |= E_char;
stringformat( c, status );
return ++spec;
}
case 's':
/* TODO: wide chars. */
stringformat( va_arg( status->arg, char * ), status );
return ++spec;
case 'p':
status->base = 16;
status->flags |= ( E_lower | E_unsigned | E_alt | E_pointer );
break;
case 'n':
{
int * val = va_arg( status->arg, int * );
*val = status->i;
return ++spec;
}
default:
/* No conversion specifier. Bad conversion. */
return orig_spec;
}
/* Do the actual output based on our findings */
if ( status->base != 0 )
{
/* Integer conversions */
/* TODO: Check for invalid flag combinations. */
if ( status->flags & E_unsigned )
{
uintmax_t value;
switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_size | E_pointer | E_intmax ) )
{
case E_char:
value = (uintmax_t)(unsigned char)va_arg( status->arg, int );
break;
case E_short:
value = (uintmax_t)(unsigned short)va_arg( status->arg, int );
break;
case 0:
value = (uintmax_t)va_arg( status->arg, unsigned int );
break;
case E_long:
value = (uintmax_t)va_arg( status->arg, unsigned long );
break;
case E_llong:
value = (uintmax_t)va_arg( status->arg, unsigned long long );
break;
case E_size:
value = (uintmax_t)va_arg( status->arg, size_t );
break;
case E_pointer:
value = (uintmax_t)(uintptr_t)va_arg( status->arg, void * );
break;
case E_intmax:
value = va_arg( status->arg, uintmax_t );
break;
default:
puts( "UNSUPPORTED PRINTF FLAG COMBINATION" );
return NULL;
}
uint2base(value, status);
}
else
{
intmax_t value;
switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_intmax ) )
{
case E_char:
value = (intmax_t)(char)va_arg( status->arg, int );
break;
case E_short:
value = (intmax_t)(short)va_arg( status->arg, int );
break;
case 0:
value = (intmax_t)va_arg( status->arg, int );
break;
case E_long:
value = (intmax_t)va_arg( status->arg, long );
break;
case E_llong:
value = (intmax_t)va_arg( status->arg, long long );
break;
case E_ptrdiff:
value = (intmax_t)va_arg( status->arg, ptrdiff_t );
break;
case E_intmax:
value = va_arg( status->arg, intmax_t );
break;
default:
puts( "UNSUPPORTED PRINTF FLAG COMBINATION" );
return NULL;
}
int2base(value, status);
}
if ( status->flags & E_minus )
{
while ( status->current < status->width )
{
PUT( ' ' );
++(status->current);
}
}
if ( status->i >= status->n && status->n > 0 )
{
status->s[status->n - 1] = '\0';
}
}
return ++spec;
}

View File

@@ -0,0 +1,18 @@
/* _PDCLIB_rename( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is an example implementation of _PDCLIB_rename() fit for use with
POSIX kernels.
*/
#include <stdio.h>
#include "j6libc/glue.h"
int _PDCLIB_rename( const char * old, const char * new )
{
_PDCLIB_errno = _PDCLIB_ERROR;
return EOF;
}

View File

@@ -0,0 +1,4 @@
#include <stdint.h>
void *sbrk(intptr_t) __attribute__ ((weak));
void *sbrk(intptr_t i) { return 0; }

View File

@@ -0,0 +1,595 @@
/* _PDCLIB_scan( const char *, struct _PDCLIB_status_t * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <ctype.h>
#include <string.h>
#include <stddef.h>
#include <limits.h>
/* Using an integer's bits as flags for both the conversion flags and length
modifiers.
*/
#define E_suppressed 1<<0
#define E_char 1<<6
#define E_short 1<<7
#define E_long 1<<8
#define E_llong 1<<9
#define E_intmax 1<<10
#define E_size 1<<11
#define E_ptrdiff 1<<12
#define E_pointer 1<<13
#define E_ldouble 1<<14
#define E_unsigned 1<<16
/* Helper function to get a character from the string or stream, whatever is
used for input. When reading from a string, returns EOF on end-of-string
so that handling of the return value can be uniform for both streams and
strings.
*/
static int GET( struct _PDCLIB_status_t * status )
{
int rc = EOF;
if ( status->stream != NULL )
{
rc = getc( status->stream );
}
else
{
rc = ( *status->s == '\0' ) ? EOF : (unsigned char)*((status->s)++);
}
if ( rc != EOF )
{
++(status->i);
++(status->current);
}
return rc;
}
/* Helper function to put a read character back into the string or stream,
whatever is used for input.
*/
static void UNGET( int c, struct _PDCLIB_status_t * status )
{
if ( status->stream != NULL )
{
ungetc( c, status->stream ); /* TODO: Error? */
}
else
{
--(status->s);
}
--(status->i);
--(status->current);
}
/* Helper function to check if a character is part of a given scanset */
static int IN_SCANSET( const char * scanlist, const char * end_scanlist, int rc )
{
/* SOLAR */
int previous = -1;
while ( scanlist != end_scanlist )
{
if ( ( *scanlist == '-' ) && ( previous != -1 ) )
{
/* possible scangroup ("a-z") */
if ( ++scanlist == end_scanlist )
{
/* '-' at end of scanlist does not describe a scangroup */
return rc == '-';
}
while ( ++previous <= (unsigned char)*scanlist )
{
if ( previous == rc )
{
return 1;
}
}
previous = -1;
}
else
{
/* not a scangroup, check verbatim */
if ( rc == (unsigned char)*scanlist )
{
return 1;
}
previous = (unsigned char)(*scanlist++);
}
}
return 0;
}
const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
{
/* generic input character */
int rc;
const char * prev_spec;
const char * orig_spec = spec;
int value_parsed;
if ( *(++spec) == '%' )
{
/* %% -> match single '%' */
rc = GET( status );
switch ( rc )
{
case EOF:
/* input error */
if ( status->n == 0 )
{
status->n = -1;
}
return NULL;
case '%':
return ++spec;
default:
UNGET( rc, status );
break;
}
}
/* Initializing status structure */
status->flags = 0;
status->base = -1;
status->current = 0;
status->width = 0;
status->prec = 0;
/* '*' suppresses assigning parsed value to variable */
if ( *spec == '*' )
{
status->flags |= E_suppressed;
++spec;
}
/* If a width is given, strtol() will return its value. If not given,
strtol() will return zero. In both cases, endptr will point to the
rest of the conversion specifier - just what we need.
*/
prev_spec = spec;
status->width = (int)strtol( spec, (char**)&spec, 10 );
if ( spec == prev_spec )
{
status->width = SIZE_MAX;
}
/* Optional length modifier
We step one character ahead in any case, and step back only if we find
there has been no length modifier (or step ahead another character if it
has been "hh" or "ll").
*/
switch ( *(spec++) )
{
case 'h':
if ( *spec == 'h' )
{
/* hh -> char */
status->flags |= E_char;
++spec;
}
else
{
/* h -> short */
status->flags |= E_short;
}
break;
case 'l':
if ( *spec == 'l' )
{
/* ll -> long long */
status->flags |= E_llong;
++spec;
}
else
{
/* l -> long */
status->flags |= E_long;
}
break;
case 'j':
/* j -> intmax_t, which might or might not be long long */
status->flags |= E_intmax;
break;
case 'z':
/* z -> size_t, which might or might not be unsigned int */
status->flags |= E_size;
break;
case 't':
/* t -> ptrdiff_t, which might or might not be long */
status->flags |= E_ptrdiff;
break;
case 'L':
/* L -> long double */
status->flags |= E_ldouble;
break;
default:
--spec;
break;
}
/* Conversion specifier */
/* whether valid input had been parsed */
value_parsed = 0;
switch ( *spec )
{
case 'd':
status->base = 10;
break;
case 'i':
status->base = 0;
break;
case 'o':
status->base = 8;
status->flags |= E_unsigned;
break;
case 'u':
status->base = 10;
status->flags |= E_unsigned;
break;
case 'x':
status->base = 16;
status->flags |= E_unsigned;
break;
case 'f':
case 'F':
case 'e':
case 'E':
case 'g':
case 'G':
case 'a':
case 'A':
break;
case 'c':
{
char * c = va_arg( status->arg, char * );
/* for %c, default width is one */
if ( status->width == SIZE_MAX )
{
status->width = 1;
}
/* reading until width reached or input exhausted */
while ( ( status->current < status->width ) &&
( ( rc = GET( status ) ) != EOF ) )
{
*(c++) = rc;
value_parsed = 1;
}
/* width or input exhausted */
if ( value_parsed )
{
++status->n;
return ++spec;
}
else
{
/* input error, no character read */
if ( status->n == 0 )
{
status->n = -1;
}
return NULL;
}
}
case 's':
{
char * c = va_arg( status->arg, char * );
while ( ( status->current < status->width ) &&
( ( rc = GET( status ) ) != EOF ) )
{
if ( isspace( rc ) )
{
UNGET( rc, status );
if ( value_parsed )
{
/* matching sequence terminated by whitespace */
*c = '\0';
++status->n;
return ++spec;
}
else
{
/* matching error */
return NULL;
}
}
else
{
/* match */
value_parsed = 1;
*(c++) = rc;
}
}
/* width or input exhausted */
if ( value_parsed )
{
*c = '\0';
++status->n;
return ++spec;
}
else
{
/* input error, no character read */
if ( status->n == 0 )
{
status->n = -1;
}
return NULL;
}
}
case '[':
{
const char * endspec = spec;
int negative_scanlist = 0;
char * c;
if ( *(++endspec) == '^' )
{
negative_scanlist = 1;
++endspec;
}
spec = endspec;
do
{
/* TODO: This can run beyond a malformed format string */
++endspec;
} while ( *endspec != ']' );
/* read according to scanlist, equiv. to %s above */
c = va_arg( status->arg, char * );
while ( ( status->current < status->width ) &&
( ( rc = GET( status ) ) != EOF ) )
{
if ( negative_scanlist )
{
if ( IN_SCANSET( spec, endspec, rc ) )
{
UNGET( rc, status );
break;
}
}
else
{
if ( ! IN_SCANSET( spec, endspec, rc ) )
{
UNGET( rc, status );
break;
}
}
value_parsed = 1;
*(c++) = rc;
}
if ( value_parsed )
{
*c = '\0';
++status->n;
return ++endspec;
}
else
{
if ( rc == EOF )
{
status->n = -1;
}
return NULL;
}
}
case 'p':
status->base = 16;
status->flags |= E_pointer;
break;
case 'n':
{
int * val = va_arg( status->arg, int * );
*val = status->i;
return ++spec;
}
default:
/* No conversion specifier. Bad conversion. */
return orig_spec;
}
if ( status->base != -1 )
{
/* integer conversion */
uintmax_t value = 0; /* absolute value read */
int prefix_parsed = 0;
int sign = 0;
while ( ( status->current < status->width ) &&
( ( rc = GET( status ) ) != EOF ) )
{
if ( isspace( rc ) )
{
if ( sign )
{
/* matching sequence terminated by whitespace */
UNGET( rc, status );
break;
}
else
{
/* leading whitespace not counted against width */
status->current--;
}
}
else if ( ! sign )
{
/* no sign parsed yet */
switch ( rc )
{
case '-':
sign = -1;
break;
case '+':
sign = 1;
break;
default:
/* not a sign; put back character */
sign = 1;
UNGET( rc, status );
break;
}
}
else if ( ! prefix_parsed )
{
/* no prefix (0x... for hex, 0... for octal) parsed yet */
prefix_parsed = 1;
if ( rc != '0' )
{
/* not a prefix; if base not yet set, set to decimal */
if ( status->base == 0 )
{
status->base = 10;
}
UNGET( rc, status );
}
else
{
/* starts with zero, so it might be a prefix. */
/* check what follows next (might be 0x...) */
if ( ( status->current < status->width ) &&
( ( rc = GET( status ) ) != EOF ) )
{
if ( tolower( rc ) == 'x' )
{
/* 0x... would be prefix for hex base... */
if ( ( status->base == 0 ) ||
( status->base == 16 ) )
{
status->base = 16;
}
else
{
/* ...unless already set to other value */
UNGET( rc, status );
value_parsed = 1;
}
}
else
{
/* 0... but not 0x.... would be octal prefix */
UNGET( rc, status );
if ( status->base == 0 )
{
status->base = 8;
}
/* in any case we have read a zero */
value_parsed = 1;
}
}
else
{
/* failed to read beyond the initial zero */
value_parsed = 1;
break;
}
}
}
else
{
char * digitptr = memchr( _PDCLIB_digits, tolower( rc ), status->base );
if ( digitptr == NULL )
{
/* end of input item */
UNGET( rc, status );
break;
}
value *= status->base;
value += digitptr - _PDCLIB_digits;
value_parsed = 1;
}
}
/* width or input exhausted, or non-matching character */
if ( ! value_parsed )
{
/* out of input before anything could be parsed - input error */
/* FIXME: if first character does not match, value_parsed is not set - but it is NOT an input error */
if ( ( status->n == 0 ) && ( rc == EOF ) )
{
status->n = -1;
}
return NULL;
}
/* convert value to target type and assign to parameter */
if ( ! ( status->flags & E_suppressed ) )
{
switch ( status->flags & ( E_char | E_short | E_long | E_llong |
E_intmax | E_size | E_ptrdiff | E_pointer |
E_unsigned ) )
{
case E_char:
*( va_arg( status->arg, char * ) ) = (char)( value * sign );
break;
case E_char | E_unsigned:
*( va_arg( status->arg, unsigned char * ) ) = (unsigned char)( value * sign );
break;
case E_short:
*( va_arg( status->arg, short * ) ) = (short)( value * sign );
break;
case E_short | E_unsigned:
*( va_arg( status->arg, unsigned short * ) ) = (unsigned short)( value * sign );
break;
case 0:
*( va_arg( status->arg, int * ) ) = (int)( value * sign );
break;
case E_unsigned:
*( va_arg( status->arg, unsigned int * ) ) = (unsigned int)( value * sign );
break;
case E_long:
*( va_arg( status->arg, long * ) ) = (long)( value * sign );
break;
case E_long | E_unsigned:
*( va_arg( status->arg, unsigned long * ) ) = (unsigned long)( value * sign );
break;
case E_llong:
*( va_arg( status->arg, long long * ) ) = (long long)( value * sign );
break;
case E_llong | E_unsigned:
*( va_arg( status->arg, unsigned long long * ) ) = (unsigned long long)( value * sign );
break;
case E_intmax:
*( va_arg( status->arg, intmax_t * ) ) = (intmax_t)( value * sign );
break;
case E_intmax | E_unsigned:
*( va_arg( status->arg, uintmax_t * ) ) = (uintmax_t)( value * sign );
break;
case E_size:
/* E_size always implies unsigned */
*( va_arg( status->arg, size_t * ) ) = (size_t)( value * sign );
break;
case E_ptrdiff:
/* E_ptrdiff always implies signed */
*( va_arg( status->arg, ptrdiff_t * ) ) = (ptrdiff_t)( value * sign );
break;
case E_pointer:
/* E_pointer always implies unsigned */
*( uintptr_t* )( va_arg( status->arg, void * ) ) = (uintptr_t)( value * sign );
break;
default:
puts( "UNSUPPORTED SCANF FLAG COMBINATION" );
return NULL; /* behaviour unspecified */
}
++(status->n);
}
return ++spec;
}
/* TODO: Floats. */
return NULL;
}

View File

@@ -0,0 +1,7 @@
/* _PDCLIB_seed
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
unsigned long int _PDCLIB_seed = 1;

View File

@@ -0,0 +1,18 @@
/* int64_t _PDCLIB_seek( FILE *, int64_t, int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is an example implementation of _PDCLIB_seek() fit for use with POSIX
kernels.
*/
#include <stdio.h>
#include "j6libc/glue.h"
int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, int64_t offset, int whence )
{
_PDCLIB_errno = _PDCLIB_ERROR;
return EOF;
}

View File

@@ -0,0 +1,412 @@
/* _PDCLIB_stdinit
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is an example initialization of stdin, stdout and stderr to the integer
file descriptors 0, 1, and 2, respectively. This applies for a great variety
of operating systems, including POSIX compliant ones.
*/
#include <stdio.h>
#include <locale.h>
#include <limits.h>
/* In a POSIX system, stdin / stdout / stderr are equivalent to the (int) file
descriptors 0, 1, and 2 respectively.
*/
/* TODO: This is proof-of-concept, requires finetuning. */
static char _PDCLIB_sin_buffer[BUFSIZ];
static char _PDCLIB_sout_buffer[BUFSIZ];
static char _PDCLIB_serr_buffer[BUFSIZ];
static unsigned char _PDCLIB_sin_ungetbuf[_PDCLIB_UNGETCBUFSIZE];
static unsigned char _PDCLIB_sout_ungetbuf[_PDCLIB_UNGETCBUFSIZE];
static unsigned char _PDCLIB_serr_ungetbuf[_PDCLIB_UNGETCBUFSIZE];
static struct _PDCLIB_file_t _PDCLIB_serr = { 2, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL };
static struct _PDCLIB_file_t _PDCLIB_sout = { 1, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr };
static struct _PDCLIB_file_t _PDCLIB_sin = { 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout };
struct _PDCLIB_file_t * stdin = &_PDCLIB_sin;
struct _PDCLIB_file_t * stdout = &_PDCLIB_sout;
struct _PDCLIB_file_t * stderr = &_PDCLIB_serr;
/* FIXME: This approach is a possible attack vector. */
struct _PDCLIB_file_t * _PDCLIB_filelist = &_PDCLIB_sin;
/* "C" locale - defaulting to ASCII-7.
1 kByte (+ 4 byte) of <ctype.h> data.
Each line: flags, lowercase, uppercase, collation.
*/
static struct _PDCLIB_lc_ctype_entry_t _ctype_entries[ _PDCLIB_CHARSET_SIZE + 1 ] = {
{ /* EOF */ 0, 0, 0 },
{ /* NUL */ _PDCLIB_CTYPE_CNTRL, 0x00, 0x00 },
{ /* SOH */ _PDCLIB_CTYPE_CNTRL, 0x01, 0x01 },
{ /* STX */ _PDCLIB_CTYPE_CNTRL, 0x02, 0x02 },
{ /* ETX */ _PDCLIB_CTYPE_CNTRL, 0x03, 0x03 },
{ /* EOT */ _PDCLIB_CTYPE_CNTRL, 0x04, 0x04 },
{ /* ENQ */ _PDCLIB_CTYPE_CNTRL, 0x05, 0x05 },
{ /* ACK */ _PDCLIB_CTYPE_CNTRL, 0x06, 0x06 },
{ /* BEL */ _PDCLIB_CTYPE_CNTRL, 0x07, 0x07 },
{ /* BS */ _PDCLIB_CTYPE_CNTRL, 0x08, 0x08 },
{ /* HT */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_BLANK | _PDCLIB_CTYPE_SPACE, 0x09, 0x09 },
{ /* LF */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0A, 0x0A },
{ /* VT */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0B, 0x0B },
{ /* FF */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0C, 0x0C },
{ /* CR */ _PDCLIB_CTYPE_CNTRL | _PDCLIB_CTYPE_SPACE, 0x0D, 0x0D },
{ /* SO */ _PDCLIB_CTYPE_CNTRL, 0x0E, 0x0E },
{ /* SI */ _PDCLIB_CTYPE_CNTRL, 0x0F, 0x0F },
{ /* DLE */ _PDCLIB_CTYPE_CNTRL, 0x10, 0x10 },
{ /* DC1 */ _PDCLIB_CTYPE_CNTRL, 0x11, 0x11 },
{ /* DC2 */ _PDCLIB_CTYPE_CNTRL, 0x12, 0x12 },
{ /* DC3 */ _PDCLIB_CTYPE_CNTRL, 0x13, 0x13 },
{ /* DC4 */ _PDCLIB_CTYPE_CNTRL, 0x14, 0x14 },
{ /* NAK */ _PDCLIB_CTYPE_CNTRL, 0x15, 0x15 },
{ /* SYN */ _PDCLIB_CTYPE_CNTRL, 0x16, 0x16 },
{ /* ETB */ _PDCLIB_CTYPE_CNTRL, 0x17, 0x17 },
{ /* CAN */ _PDCLIB_CTYPE_CNTRL, 0x18, 0x18 },
{ /* EM */ _PDCLIB_CTYPE_CNTRL, 0x19, 0x19 },
{ /* SUB */ _PDCLIB_CTYPE_CNTRL, 0x1A, 0x1A },
{ /* ESC */ _PDCLIB_CTYPE_CNTRL, 0x1B, 0x1B },
{ /* FS */ _PDCLIB_CTYPE_CNTRL, 0x1C, 0x1C },
{ /* GS */ _PDCLIB_CTYPE_CNTRL, 0x1D, 0x1D },
{ /* RS */ _PDCLIB_CTYPE_CNTRL, 0x1E, 0x1E },
{ /* US */ _PDCLIB_CTYPE_CNTRL, 0x1F, 0x1F },
{ /* SP */ _PDCLIB_CTYPE_BLANK | _PDCLIB_CTYPE_SPACE, 0x20, 0x20 },
{ /* '!' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x21, 0x21 },
{ /* '"' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x22, 0x22 },
{ /* '#' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x23, 0x23 },
{ /* '$' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x24, 0x24 },
{ /* '%' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x25, 0x25 },
{ /* '&' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x26, 0x26 },
{ /* ''' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x27, 0x27 },
{ /* '(' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x28, 0x28 },
{ /* ')' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x29, 0x29 },
{ /* '*' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2A, 0x2A },
{ /* '+' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2B, 0x2B },
{ /* ',' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2C, 0x2C },
{ /* '-' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2D, 0x2D },
{ /* '.' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2E, 0x2E },
{ /* '/' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x2F, 0x2F },
{ /* '0' */ _PDCLIB_CTYPE_GRAPH, 0x30, 0x30 },
{ /* '1' */ _PDCLIB_CTYPE_GRAPH, 0x31, 0x31 },
{ /* '2' */ _PDCLIB_CTYPE_GRAPH, 0x32, 0x32 },
{ /* '3' */ _PDCLIB_CTYPE_GRAPH, 0x33, 0x33 },
{ /* '4' */ _PDCLIB_CTYPE_GRAPH, 0x34, 0x34 },
{ /* '5' */ _PDCLIB_CTYPE_GRAPH, 0x35, 0x35 },
{ /* '6' */ _PDCLIB_CTYPE_GRAPH, 0x36, 0x36 },
{ /* '7' */ _PDCLIB_CTYPE_GRAPH, 0x37, 0x37 },
{ /* '8' */ _PDCLIB_CTYPE_GRAPH, 0x38, 0x38 },
{ /* '9' */ _PDCLIB_CTYPE_GRAPH, 0x39, 0x39 },
{ /* ':' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3A, 0x3A },
{ /* ';' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3B, 0x3B },
{ /* '<' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3C, 0x3C },
{ /* '=' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3D, 0x3D },
{ /* '>' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3E, 0x3E },
{ /* '?' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x3F, 0x3F },
{ /* '@' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x40, 0x40 },
{ /* 'A' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x41, 0x61 },
{ /* 'B' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x42, 0x62 },
{ /* 'C' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x43, 0x63 },
{ /* 'D' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x44, 0x64 },
{ /* 'E' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x45, 0x65 },
{ /* 'F' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x46, 0x66 },
{ /* 'G' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x47, 0x67 },
{ /* 'H' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x48, 0x68 },
{ /* 'I' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x49, 0x69 },
{ /* 'J' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4A, 0x6A },
{ /* 'K' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4B, 0x6B },
{ /* 'L' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4C, 0x6C },
{ /* 'M' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4D, 0x6D },
{ /* 'N' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4E, 0x6E },
{ /* 'O' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x4F, 0x6F },
{ /* 'P' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x50, 0x70 },
{ /* 'Q' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x51, 0x71 },
{ /* 'R' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x52, 0x72 },
{ /* 'S' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x53, 0x73 },
{ /* 'T' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x54, 0x74 },
{ /* 'U' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x55, 0x75 },
{ /* 'V' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x56, 0x76 },
{ /* 'W' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x57, 0x77 },
{ /* 'X' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x58, 0x78 },
{ /* 'Y' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x59, 0x79 },
{ /* 'Z' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x5A, 0x7A },
{ /* '[' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5B, 0x5B },
{ /* '\' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5C, 0x5C },
{ /* ']' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5D, 0x5D },
{ /* '^' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5E, 0x5E },
{ /* '_' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x5F, 0x5F },
{ /* '`' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x60, 0x60 },
{ /* 'a' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x41, 0x61 },
{ /* 'b' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x42, 0x62 },
{ /* 'c' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x43, 0x63 },
{ /* 'd' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x44, 0x64 },
{ /* 'e' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x45, 0x65 },
{ /* 'f' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x46, 0x66 },
{ /* 'g' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x47, 0x67 },
{ /* 'h' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x48, 0x68 },
{ /* 'i' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x49, 0x69 },
{ /* 'j' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4A, 0x6A },
{ /* 'k' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4B, 0x6B },
{ /* 'l' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4C, 0x6C },
{ /* 'm' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4D, 0x6D },
{ /* 'n' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4E, 0x6E },
{ /* 'o' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x4F, 0x6F },
{ /* 'p' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x50, 0x70 },
{ /* 'q' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x51, 0x71 },
{ /* 'r' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x52, 0x72 },
{ /* 's' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x53, 0x73 },
{ /* 't' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x54, 0x74 },
{ /* 'u' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x55, 0x75 },
{ /* 'v' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x56, 0x76 },
{ /* 'w' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x57, 0x77 },
{ /* 'x' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x58, 0x78 },
{ /* 'y' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x59, 0x79 },
{ /* 'z' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x5A, 0x7A },
{ /* '{' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7B, 0x7B },
{ /* '|' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7C, 0x7C },
{ /* '}' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7D, 0x7D },
{ /* '~' */ _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_PUNCT, 0x7E, 0x7E },
{ /* DEL */ _PDCLIB_CTYPE_CNTRL, 0x7F, 0x7F },
{ 0x00, 0x80, 0x80 },
{ 0x00, 0x81, 0x81 },
{ 0x00, 0x82, 0x82 },
{ 0x00, 0x83, 0x83 },
{ 0x00, 0x84, 0x84 },
{ 0x00, 0x85, 0x85 },
{ 0x00, 0x86, 0x86 },
{ 0x00, 0x87, 0x87 },
{ 0x00, 0x88, 0x88 },
{ 0x00, 0x89, 0x89 },
{ 0x00, 0x8A, 0x8A },
{ 0x00, 0x8B, 0x8B },
{ 0x00, 0x8C, 0x8C },
{ 0x00, 0x8D, 0x8D },
{ 0x00, 0x8E, 0x8E },
{ 0x00, 0x8F, 0x8F },
{ 0x00, 0x90, 0x90 },
{ 0x00, 0x91, 0x91 },
{ 0x00, 0x92, 0x92 },
{ 0x00, 0x93, 0x93 },
{ 0x00, 0x94, 0x94 },
{ 0x00, 0x95, 0x95 },
{ 0x00, 0x96, 0x96 },
{ 0x00, 0x97, 0x97 },
{ 0x00, 0x98, 0x98 },
{ 0x00, 0x99, 0x99 },
{ 0x00, 0x9A, 0x9A },
{ 0x00, 0x9B, 0x9B },
{ 0x00, 0x9C, 0x9C },
{ 0x00, 0x9D, 0x9D },
{ 0x00, 0x9E, 0x9E },
{ 0x00, 0x9F, 0x9F },
{ 0x00, 0xA0, 0xA0 },
{ 0x00, 0xA1, 0xA1 },
{ 0x00, 0xA2, 0xA2 },
{ 0x00, 0xA3, 0xA3 },
{ 0x00, 0xA4, 0xA4 },
{ 0x00, 0xA5, 0xA5 },
{ 0x00, 0xA6, 0xA6 },
{ 0x00, 0xA7, 0xA7 },
{ 0x00, 0xA8, 0xA8 },
{ 0x00, 0xA9, 0xA9 },
{ 0x00, 0xAA, 0xAA },
{ 0x00, 0xAB, 0xAB },
{ 0x00, 0xAC, 0xAC },
{ 0x00, 0xAD, 0xAD },
{ 0x00, 0xAE, 0xAE },
{ 0x00, 0xAF, 0xAF },
{ 0x00, 0xB0, 0xB0 },
{ 0x00, 0xB1, 0xB1 },
{ 0x00, 0xB2, 0xB2 },
{ 0x00, 0xB3, 0xB3 },
{ 0x00, 0xB4, 0xB4 },
{ 0x00, 0xB5, 0xB5 },
{ 0x00, 0xB6, 0xB6 },
{ 0x00, 0xB7, 0xB7 },
{ 0x00, 0xB8, 0xB8 },
{ 0x00, 0xB9, 0xB9 },
{ 0x00, 0xBA, 0xBA },
{ 0x00, 0xBB, 0xBB },
{ 0x00, 0xBC, 0xBC },
{ 0x00, 0xBD, 0xBD },
{ 0x00, 0xBE, 0xBE },
{ 0x00, 0xBF, 0xBF },
{ 0x00, 0xC0, 0xC0 },
{ 0x00, 0xC1, 0xC1 },
{ 0x00, 0xC2, 0xC2 },
{ 0x00, 0xC3, 0xC3 },
{ 0x00, 0xC4, 0xC4 },
{ 0x00, 0xC5, 0xC5 },
{ 0x00, 0xC6, 0xC6 },
{ 0x00, 0xC7, 0xC7 },
{ 0x00, 0xC8, 0xC8 },
{ 0x00, 0xC9, 0xC9 },
{ 0x00, 0xCA, 0xCA },
{ 0x00, 0xCB, 0xCB },
{ 0x00, 0xCC, 0xCC },
{ 0x00, 0xCD, 0xCD },
{ 0x00, 0xCE, 0xCE },
{ 0x00, 0xCF, 0xCF },
{ 0x00, 0xD0, 0xD0 },
{ 0x00, 0xD1, 0xD1 },
{ 0x00, 0xD2, 0xD2 },
{ 0x00, 0xD3, 0xD3 },
{ 0x00, 0xD4, 0xD4 },
{ 0x00, 0xD5, 0xD5 },
{ 0x00, 0xD6, 0xD6 },
{ 0x00, 0xD7, 0xD7 },
{ 0x00, 0xD8, 0xD8 },
{ 0x00, 0xD9, 0xD9 },
{ 0x00, 0xDA, 0xDA },
{ 0x00, 0xDB, 0xDB },
{ 0x00, 0xDC, 0xDC },
{ 0x00, 0xDD, 0xDD },
{ 0x00, 0xDE, 0xDE },
{ 0x00, 0xDF, 0xDF },
{ 0x00, 0xE0, 0xE0 },
{ 0x00, 0xE1, 0xE1 },
{ 0x00, 0xE2, 0xE2 },
{ 0x00, 0xE3, 0xE3 },
{ 0x00, 0xE4, 0xE4 },
{ 0x00, 0xE5, 0xE5 },
{ 0x00, 0xE6, 0xE6 },
{ 0x00, 0xE7, 0xE7 },
{ 0x00, 0xE8, 0xE8 },
{ 0x00, 0xE9, 0xE9 },
{ 0x00, 0xEA, 0xEA },
{ 0x00, 0xEB, 0xEB },
{ 0x00, 0xEC, 0xEC },
{ 0x00, 0xED, 0xED },
{ 0x00, 0xEE, 0xEE },
{ 0x00, 0xEF, 0xEF },
{ 0x00, 0xF0, 0xF0 },
{ 0x00, 0xF1, 0xF1 },
{ 0x00, 0xF2, 0xF2 },
{ 0x00, 0xF3, 0xF3 },
{ 0x00, 0xF4, 0xF4 },
{ 0x00, 0xF5, 0xF5 },
{ 0x00, 0xF6, 0xF6 },
{ 0x00, 0xF7, 0xF7 },
{ 0x00, 0xF8, 0xF8 },
{ 0x00, 0xF9, 0xF9 },
{ 0x00, 0xFA, 0xFA },
{ 0x00, 0xFB, 0xFB },
{ 0x00, 0xFC, 0xFC },
{ 0x00, 0xFD, 0xFD },
{ 0x00, 0xFE, 0xFE },
{ 0x00, 0xFF, 0xFF }
};
struct _PDCLIB_lc_ctype_t _PDCLIB_lc_ctype = { 0, 0x30, 0x39, 0x41, 0x46, 0x61, 0x66, &_ctype_entries[1] };
struct _PDCLIB_lc_collate_t _PDCLIB_lc_collate = { 0 };
struct lconv _PDCLIB_lconv = {
/* decimal_point */ (char *)".",
/* thousands_sep */ (char *)"",
/* grouping */ (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_MAX,
/* p_cs_precedes */ CHAR_MAX,
/* n_cs_precedes */ CHAR_MAX,
/* p_sep_by_space */ CHAR_MAX,
/* n_sep_by_space */ CHAR_MAX,
/* p_sign_posn */ CHAR_MAX,
/* n_sign_posn */ CHAR_MAX,
/* int_frac_digits */ CHAR_MAX,
/* int_p_cs_precedes */ CHAR_MAX,
/* int_n_cs_precedes */ CHAR_MAX,
/* int_p_sep_by_space */ CHAR_MAX,
/* int_n_sep_by_space */ CHAR_MAX,
/* int_p_sign_posn */ CHAR_MAX,
/* int_n_sign_posn */ CHAR_MAX
};
struct _PDCLIB_lc_numeric_monetary_t _PDCLIB_lc_numeric_monetary = {
&_PDCLIB_lconv,
0, /* numeric_allocated */
0 /* monetary_allocated */
};
struct _PDCLIB_lc_messages_t _PDCLIB_lc_messages = {
0,
/* _PDCLIB_errno_texts */
{
/* no error */ (char *)"",
/* ERANGE */ (char *)"ERANGE (Range error)",
/* EDOM */ (char *)"EDOM (Domain error)",
/* EILSEQ */ (char *)"EILSEQ (Illegal sequence)"
}
};
struct _PDCLIB_lc_time_t _PDCLIB_lc_time = {
0,
/* _PDCLIB_month_name_abbr */
{
(char *)"Jan",
(char *)"Feb",
(char *)"Mar",
(char *)"Apr",
(char *)"May",
(char *)"Jun",
(char *)"Jul",
(char *)"Aug",
(char *)"Sep",
(char *)"Oct",
(char *)"Now",
(char *)"Dec"
},
/* _PDCLIB_month_name_full */
{
(char *)"January",
(char *)"February",
(char *)"March",
(char *)"April",
(char *)"May",
(char *)"June",
(char *)"July",
(char *)"August",
(char *)"September",
(char *)"October",
(char *)"November",
(char *)"December"
},
/* _PDCLIB_day_name_abbr */
{
(char *)"Sun",
(char *)"Mon",
(char *)"Tue",
(char *)"Wed",
(char *)"Thu",
(char *)"Fri",
(char *)"Sat"
},
/* _PDCLIB_day_name_full */
{
(char *)"Sunday",
(char *)"Monday",
(char *)"Tuesday",
(char *)"Wednesday",
(char *)"Thursday",
(char *)"Friday",
(char *)"Saturday"
},
/* date / time format */ (char *)"%a %b %e %T %Y",
/* 12h time format */ (char *)"%I:%M:%S %p",
/* date format */ (char *)"%m/%d/%y",
/* time format */ (char *)"%T",
/* AM / PM designation */
{
(char *)"AM",
(char *)"PM"
}
};

View File

@@ -0,0 +1,42 @@
/* _PDCLIB_strtox_main( const char * *, int, uintmax_t, uintmax_t, int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, uintmax_t error, uintmax_t limval, int limdigit, char * sign )
{
uintmax_t rc = 0;
int digit = -1;
const char * x;
while ( ( x = memchr( _PDCLIB_digits, tolower(**p), base ) ) != NULL )
{
digit = x - _PDCLIB_digits;
if ( ( rc < limval ) || ( ( rc == limval ) && ( digit <= limdigit ) ) )
{
rc = rc * base + (unsigned)digit;
++(*p);
}
else
{
errno = ERANGE;
/* TODO: Only if endptr != NULL - but do we really want *another* parameter? */
/* TODO: Earlier version was missing tolower() here but was not caught by tests */
while ( memchr( _PDCLIB_digits, tolower(**p), base ) != NULL ) ++(*p);
/* TODO: This is ugly, but keeps caller from negating the error value */
*sign = '+';
return error;
}
}
if ( digit == -1 )
{
*p = NULL;
return 0;
}
return rc;
}

View File

@@ -0,0 +1,50 @@
/* _PDCLIB_strtox_prelim( const char *, char *, int * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <ctype.h>
#include <stddef.h>
#include <string.h>
const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base )
{
/* skipping leading whitespace */
while ( isspace( *p ) ) ++p;
/* determining / skipping sign */
if ( *p != '+' && *p != '-' ) *sign = '+';
else *sign = *(p++);
/* determining base */
if ( *p == '0' )
{
++p;
if ( ( *base == 0 || *base == 16 ) && ( *p == 'x' || *p == 'X' ) )
{
*base = 16;
++p;
/* catching a border case here: "0x" followed by a non-digit should
be parsed as the unprefixed zero.
We have to "rewind" the parsing; having the base set to 16 if it
was zero previously does not hurt, as the result is zero anyway.
*/
if ( memchr( _PDCLIB_digits, tolower(*p), *base ) == NULL )
{
p -= 2;
}
}
else if ( *base == 0 )
{
*base = 8;
}
else
{
--p;
}
}
else if ( ! *base )
{
*base = 10;
}
return ( ( *base >= 2 ) && ( *base <= 36 ) ) ? p : NULL;
}

View File

@@ -0,0 +1,12 @@
/* localeconv( void )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <locale.h>
struct lconv * localeconv( void )
{
return _PDCLIB_lc_numeric_monetary.lconv;
}

View File

@@ -0,0 +1,242 @@
/* setlocale( int, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#if 0
static const char * _PDCLIB_LC_category_name[ _PDCLIB_LC_COUNT ] = { NULL, "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC", "LC_TIME", "LC_MESSAGES" };
static const char * _PDCLIB_default_locale( int category )
{
const char * s;
if ( ( s = getenv( "LC_ALL" ) ) == NULL )
{
if ( category == LC_ALL || ( s = getenv( _PDCLIB_LC_category_name[ category ] ) ) == NULL )
{
if ( ( s = getenv( "LANG" ) ) == NULL )
{
s = "C";
}
}
}
return s;
}
#endif
char * setlocale( int category, const char * locale )
{
/* All below is very much work-in-progress, so we do a dumb-dummy
return here.
*/
if ( locale == NULL || ! strcmp( locale, "C" ) )
{
return (char *)"C";
}
else
{
return NULL;
}
#if 0
/* Path to locale data files - _PDCLIB_LOCALE_PATH unless overruled
by the environment variable whose name is defined by preprocessor
symbol _PDCLIB_LOCALE_PATH_ENV (defaulting to PDCLIB_I18N).
Both of these definitions are set in config.h.
*/
const char * path = _PDCLIB_LOCALE_PATH;
struct _PDCLIB_lc_lconv_numeric_t * numeric = NULL;
struct _PDCLIB_lc_lconv_monetary_t * monetary = NULL;
struct _PDCLIB_lc_collate_t * collate = NULL;
struct _PDCLIB_lc_ctype_t * ctype = NULL;
struct _PDCLIB_lc_messages_t * messages = NULL;
struct _PDCLIB_lc_time_t * time = NULL;
char * rc = (char *)locale;
if ( category < 0 || category >= _PDCLIB_LC_COUNT )
{
/* Bad category */
return NULL;
}
if ( locale == NULL )
{
/* NULL - Return current locale settings */
/* TODO */
}
if ( strlen( locale ) == 0 )
{
/* "" - Use default locale */
locale = _PDCLIB_default_locale( category );
}
if ( getenv( _PDCLIB_symbol2string( _PDCLIB_LOCALE_PATH_ENV ) ) != NULL )
{
path = getenv( _PDCLIB_symbol2string( _PDCLIB_LOCALE_PATH_ENV ) );
}
/* We have to do this in two runs. As we might be facing LC_ALL, we
need to be certain all the loads are successful before we start
to overwrite the current locale settings, because there is no way
this function could report a _partial_ success.
*/
/* Run One -- get all the data for the new locale setting */
if ( category == LC_COLLATE || category == LC_ALL )
{
if ( ! ( collate = _PDCLIB_load_lc_collate( path, locale ) ) )
{
rc = NULL;
}
}
if ( category == LC_CTYPE || category == LC_ALL )
{
if ( ! ( ctype = _PDCLIB_load_lc_ctype( path, locale ) ) )
{
rc = NULL;
}
}
if ( category == LC_MONETARY || category == LC_ALL )
{
if ( ! ( monetary = _PDCLIB_load_lc_monetary( path, locale ) ) )
{
rc = NULL;
}
}
if ( category == LC_NUMERIC || category == LC_ALL )
{
if ( ! ( numeric = _PDCLIB_load_lc_numeric( path, locale ) ) )
{
rc = NULL;
}
}
if ( category == LC_TIME || category == LC_ALL )
{
if ( ! ( time = _PDCLIB_load_lc_time( path, locale ) ) )
{
rc = NULL;
}
}
if ( category == LC_MESSAGES || category == LC_ALL )
{
if ( ! ( messages = _PDCLIB_load_lc_messages( path, locale ) ) )
{
rc = NULL;
}
}
/* Run Two -- continue or release resources */
if ( rc != NULL )
{
if ( category == LC_COLLATE || category == LC_ALL )
{
if ( _PDCLIB_lc_collate.alloced )
{
/* free resources */
}
_PDCLIB_lc_collate = *collate;
free( collate );
}
if ( category == LC_CTYPE || category == LC_ALL )
{
if ( _PDCLIB_lc_ctype.alloced )
{
free( _PDCLIB_lc_ctype.entry - 1 );
}
_PDCLIB_lc_ctype = *ctype;
free( ctype );
}
if ( category == LC_MONETARY || category == LC_ALL )
{
if ( _PDCLIB_lc_numeric_monetary.monetary_alloced )
{
free( _PDCLIB_lc_numeric_monetary.lconv->mon_decimal_point );
}
_PDCLIB_lc_numeric_monetary.lconv->mon_decimal_point = monetary->mon_decimal_point;
_PDCLIB_lc_numeric_monetary.lconv->mon_thousands_sep = monetary->mon_thousands_sep;
_PDCLIB_lc_numeric_monetary.lconv->mon_grouping = monetary->mon_grouping;
_PDCLIB_lc_numeric_monetary.lconv->positive_sign = monetary->positive_sign;
_PDCLIB_lc_numeric_monetary.lconv->negative_sign = monetary->negative_sign;
_PDCLIB_lc_numeric_monetary.lconv->currency_symbol = monetary->currency_symbol;
_PDCLIB_lc_numeric_monetary.lconv->int_curr_symbol = monetary->int_curr_symbol;
_PDCLIB_lc_numeric_monetary.lconv->frac_digits = monetary->frac_digits;
_PDCLIB_lc_numeric_monetary.lconv->p_cs_precedes = monetary->p_cs_precedes;
_PDCLIB_lc_numeric_monetary.lconv->n_cs_precedes = monetary->n_cs_precedes;
_PDCLIB_lc_numeric_monetary.lconv->p_sep_by_space = monetary->p_sep_by_space;
_PDCLIB_lc_numeric_monetary.lconv->n_sep_by_space = monetary->n_sep_by_space;
_PDCLIB_lc_numeric_monetary.lconv->p_sign_posn = monetary->p_sign_posn;
_PDCLIB_lc_numeric_monetary.lconv->n_sign_posn = monetary->n_sign_posn;
_PDCLIB_lc_numeric_monetary.lconv->int_frac_digits = monetary->int_frac_digits;
_PDCLIB_lc_numeric_monetary.lconv->int_p_cs_precedes = monetary->int_p_cs_precedes;
_PDCLIB_lc_numeric_monetary.lconv->int_n_cs_precedes = monetary->int_n_cs_precedes;
_PDCLIB_lc_numeric_monetary.lconv->int_p_sep_by_space = monetary->int_p_sep_by_space;
_PDCLIB_lc_numeric_monetary.lconv->int_n_sep_by_space = monetary->int_n_sep_by_space;
_PDCLIB_lc_numeric_monetary.lconv->int_p_sign_posn = monetary->int_p_sign_posn;
_PDCLIB_lc_numeric_monetary.lconv->int_n_sign_posn = monetary->int_n_sign_posn;
_PDCLIB_lc_numeric_monetary.monetary_alloced = 1;
free( monetary );
}
if ( category == LC_NUMERIC || category == LC_ALL )
{
if ( _PDCLIB_lc_numeric_monetary.numeric_alloced )
{
free( _PDCLIB_lc_numeric_monetary.lconv->decimal_point );
}
_PDCLIB_lc_numeric_monetary.lconv->decimal_point = numeric->decimal_point;
_PDCLIB_lc_numeric_monetary.lconv->thousands_sep = numeric->thousands_sep;
_PDCLIB_lc_numeric_monetary.lconv->grouping = numeric->grouping;
_PDCLIB_lc_numeric_monetary.numeric_alloced = 1;
free( numeric );
}
if ( category == LC_TIME || category == LC_ALL )
{
if ( _PDCLIB_lc_time.alloced )
{
free( _PDCLIB_lc_time.month_name_abbr[ 0 ] );
}
_PDCLIB_lc_time = *time;
free( time );
}
if ( category == LC_MESSAGES || category == LC_ALL )
{
if ( _PDCLIB_lc_messages.alloced )
{
free( _PDCLIB_lc_messages.errno_texts[ 0 ] );
}
_PDCLIB_lc_messages = *messages;
free( messages );
}
}
return NULL;
#endif
}

View File

@@ -0,0 +1,63 @@
/* raise( int )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
extern void (*_PDCLIB_sigabrt)( int );
extern void (*_PDCLIB_sigfpe)( int );
extern void (*_PDCLIB_sigill)( int );
extern void (*_PDCLIB_sigint)( int );
extern void (*_PDCLIB_sigsegv)( int );
extern void (*_PDCLIB_sigterm)( int );
int raise( int sig )
{
void (*sighandler)( int ) = NULL;
const char * message;
switch ( sig )
{
case SIGABRT:
sighandler = _PDCLIB_sigabrt;
message = "Abnormal termination (SIGABRT)";
break;
case SIGFPE:
sighandler = _PDCLIB_sigfpe;
message = "Arithmetic exception (SIGFPE)";
break;
case SIGILL:
sighandler = _PDCLIB_sigill;
message = "Illegal instruction (SIGILL)";
break;
case SIGINT:
sighandler = _PDCLIB_sigint;
message = "Interactive attention signal (SIGINT)";
break;
case SIGSEGV:
sighandler = _PDCLIB_sigsegv;
message = "Invalid memory access (SIGSEGV)";
break;
case SIGTERM:
sighandler = _PDCLIB_sigterm;
message = "Termination request (SIGTERM)";
break;
default:
fprintf( stderr, "Unknown signal #%d\n", sig );
_Exit( EXIT_FAILURE );
}
if ( sighandler == SIG_DFL )
{
fputs( message, stderr );
_Exit( EXIT_FAILURE );
}
else if ( sighandler != SIG_IGN )
{
sighandler = signal( sig, SIG_DFL );
sighandler( sig );
}
return 0;
}

View File

@@ -0,0 +1,58 @@
/* signal( int, void (*)( int ) )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <signal.h>
#include <stdlib.h>
void (*_PDCLIB_sigabrt)( int ) = SIG_DFL;
void (*_PDCLIB_sigfpe)( int ) = SIG_DFL;
void (*_PDCLIB_sigill)( int ) = SIG_DFL;
void (*_PDCLIB_sigint)( int ) = SIG_DFL;
void (*_PDCLIB_sigsegv)( int ) = SIG_DFL;
void (*_PDCLIB_sigterm)( int ) = SIG_DFL;
void (*signal( int sig, void (*func)( int ) ) )( int )
{
void (*oldhandler)( int );
if ( sig <= 0 || func == SIG_ERR )
{
return SIG_ERR;
}
switch ( sig )
{
case SIGABRT:
oldhandler = _PDCLIB_sigabrt;
_PDCLIB_sigabrt = func;
break;
case SIGFPE:
oldhandler = _PDCLIB_sigfpe;
_PDCLIB_sigfpe = func;
break;
case SIGILL:
oldhandler = _PDCLIB_sigill;
_PDCLIB_sigill = func;
break;
case SIGINT:
oldhandler = _PDCLIB_sigint;
_PDCLIB_sigint = func;
break;
case SIGSEGV:
oldhandler = _PDCLIB_sigsegv;
_PDCLIB_sigsegv = func;
break;
case SIGTERM:
oldhandler = _PDCLIB_sigterm;
_PDCLIB_sigterm = func;
break;
default:
/* The standard calls for an unspecified "positive value". You
will probably want to define a specific value for this.
*/
_PDCLIB_errno = 1;
return SIG_ERR;
}
return oldhandler;
}

View File

@@ -0,0 +1,12 @@
/* clearerr( FILE * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
void clearerr( struct _PDCLIB_file_t * stream )
{
stream->status &= ~( _PDCLIB_ERRORFLAG | _PDCLIB_EOFFLAG );
}

View File

@@ -0,0 +1,67 @@
/* fclose( FILE * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include <stdlib.h>
#include "j6libc/glue.h"
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
int fclose( struct _PDCLIB_file_t * stream )
{
struct _PDCLIB_file_t * current = _PDCLIB_filelist;
struct _PDCLIB_file_t * previous = NULL;
/* Checking that the FILE handle is actually one we had opened before. */
while ( current != NULL )
{
if ( stream == current )
{
/* Flush buffer */
if ( stream->status & _PDCLIB_FWRITE )
{
if ( _PDCLIB_flushbuffer( stream ) == EOF )
{
/* Flush failed, errno already set */
return EOF;
}
}
/* Close handle */
_PDCLIB_close( stream->handle );
/* Remove stream from list */
if ( previous != NULL )
{
previous->next = stream->next;
}
else
{
_PDCLIB_filelist = stream->next;
}
/* Delete tmpfile() */
if ( stream->status & _PDCLIB_DELONCLOSE )
{
remove( stream->filename );
}
/* Free user buffer (SetVBuf allocated) */
if ( stream->status & _PDCLIB_FREEBUFFER )
{
free( stream->buffer );
}
/* Free stream */
if ( ! ( stream->status & _PDCLIB_STATIC ) )
{
free( stream );
}
return 0;
}
previous = current;
current = current->next;
}
/* See the comments on implementation-defined errno values in
<config.h>.
*/
_PDCLIB_errno = _PDCLIB_ERROR;
return -1;
}

View File

@@ -0,0 +1,12 @@
/* feof( FILE * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
int feof( struct _PDCLIB_file_t * stream )
{
return stream->status & _PDCLIB_EOFFLAG;
}

View File

@@ -0,0 +1,12 @@
/* ferror( FILE * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
int ferror( struct _PDCLIB_file_t * stream )
{
return stream->status & _PDCLIB_ERRORFLAG;
}

View File

@@ -0,0 +1,36 @@
/* fflush( FILE * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include "j6libc/glue.h"
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
int fflush( struct _PDCLIB_file_t * stream )
{
if ( stream == NULL )
{
int rc = 0;
stream = _PDCLIB_filelist;
/* TODO: Check what happens when fflush( NULL ) encounters write errors, in other libs */
while ( stream != NULL )
{
if ( stream->status & _PDCLIB_FWRITE )
{
if ( _PDCLIB_flushbuffer( stream ) == EOF )
{
rc = EOF;
}
}
stream = stream->next;
}
return rc;
}
else
{
return _PDCLIB_flushbuffer( stream );
}
}

View File

@@ -0,0 +1,21 @@
/* fgetc( FILE * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include "j6libc/glue.h"
int fgetc( struct _PDCLIB_file_t * stream )
{
if ( _PDCLIB_prepread( stream ) == EOF )
{
return EOF;
}
if ( stream->ungetidx > 0 )
{
return (unsigned char)stream->ungetbuf[ --(stream->ungetidx) ];
}
return (unsigned char)stream->buffer[stream->bufidx++];
}

View File

@@ -0,0 +1,15 @@
/* fgetpos( FILE * , fpos_t * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
int fgetpos( struct _PDCLIB_file_t * restrict stream, struct _PDCLIB_fpos_t * restrict pos )
{
pos->offset = stream->pos.offset + stream->bufidx - stream->ungetidx;
pos->status = stream->pos.status;
/* TODO: Add mbstate. */
return 0;
}

View File

@@ -0,0 +1,42 @@
/* fgets( char *, int, FILE * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include "j6libc/glue.h"
char * fgets( char * restrict s, int size, struct _PDCLIB_file_t * restrict stream )
{
char * dest = s;
if ( size == 0 )
{
return NULL;
}
if ( size == 1 )
{
*s = '\0';
return s;
}
if ( _PDCLIB_prepread( stream ) == EOF )
{
return NULL;
}
while ( ( ( *dest++ = stream->buffer[stream->bufidx++] ) != '\n' ) && --size > 0 )
{
if ( stream->bufidx == stream->bufend )
{
if ( _PDCLIB_fillbuffer( stream ) == EOF )
{
/* In case of error / EOF before a character is read, this
will lead to a \0 be written anyway. Since the results
are "indeterminate" by definition, this does not hurt.
*/
break;
}
}
}
*dest = '\0';
return ( dest == s ) ? NULL : s;
}

View File

@@ -0,0 +1,70 @@
/* fopen( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include <stdlib.h>
#include "j6libc/glue.h"
#include <string.h>
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
struct _PDCLIB_file_t * fopen( const char * restrict filename, const char * restrict mode )
{
struct _PDCLIB_file_t * rc;
size_t filename_len;
if ( mode == NULL || filename == NULL || filename[0] == '\0' )
{
/* Mode or filename invalid */
return NULL;
}
/* To reduce the number of malloc calls, all data fields are concatenated:
* the FILE structure itself,
* ungetc buffer,
* filename buffer,
* data buffer.
Data buffer comes last because it might change in size ( setvbuf() ).
*/
filename_len = strlen( filename ) + 1;
if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + filename_len + BUFSIZ ) ) == NULL )
{
/* no memory */
return NULL;
}
if ( ( rc->status = _PDCLIB_filemode( mode ) ) == 0 )
{
/* invalid mode */
free( rc );
return NULL;
}
rc->handle = _PDCLIB_open( filename, rc->status );
if ( rc->handle == _PDCLIB_NOHANDLE )
{
/* OS open() failed */
free( rc );
return NULL;
}
/* Setting pointers into the memory block allocated above */
rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t );
rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE;
rc->buffer = rc->filename + filename_len;
/* Copying filename to FILE structure */
strcpy( rc->filename, filename );
/* Initializing the rest of the structure */
rc->bufsize = BUFSIZ;
rc->bufidx = 0;
rc->ungetidx = 0;
/* Setting buffer to _IOLBF because "when opened, a stream is fully
buffered if and only if it can be determined not to refer to an
interactive device."
*/
rc->status |= _IOLBF;
/* TODO: Setting mbstate */
/* Adding to list of open files */
rc->next = _PDCLIB_filelist;
_PDCLIB_filelist = rc;
return rc;
}

View File

@@ -0,0 +1,18 @@
/* fprintf( FILE *, const char *, ... )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include <stdarg.h>
int fprintf( struct _PDCLIB_file_t * restrict stream, const char * restrict format, ... )
{
int rc;
va_list ap;
va_start( ap, format );
rc = vfprintf( stream, format, ap );
va_end( ap );
return rc;
}

Some files were not shown because too many files have changed in this diff Show More