compiled newlib, need to hook up the system calls

This commit is contained in:
2026-06-28 17:58:58 -05:00
parent 43bc0df81a
commit 97357f3170
337 changed files with 47955 additions and 114 deletions

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,48 @@
/* _PDCLIB_Exit( 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_Exit() fit for use with POSIX
kernels.
*/
#include <stdlib.h>
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#ifdef __cplusplus
extern "C" {
#endif
extern _PDCLIB_Noreturn void _exit( int status ) _PDCLIB_NORETURN;
#ifdef __cplusplus
}
#endif
void _PDCLIB_Exit( int status )
{
_exit( status );
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
int UNEXPECTED_RETURN = 0;
_PDCLIB_Exit( 0 );
TESTCASE( UNEXPECTED_RETURN );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,59 @@
/* _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>
#ifndef REGTEST
_PDCLIB_intmax_t _PDCLIB_atomax( const char * s )
{
_PDCLIB_intmax_t rc = 0;
char sign = '+';
const char * x;
/* TODO: In other than "C" locale, additional patterns may be defined */
while ( isspace( (unsigned char)*s ) )
{
++s;
}
if ( *s == '+' )
{
++s;
}
else if ( *s == '-' )
{
sign = *( s++ );
}
/* TODO: Earlier version was missing tolower() but was not caught by tests */
while ( ( x = (const char *)memchr( _PDCLIB_digits, tolower( (unsigned char)*( s++ ) ), 10 ) ) != NULL )
{
rc = rc * 10 + ( x - _PDCLIB_digits );
}
return ( sign == '+' ) ? rc : -rc;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
/* basic functionality */
TESTCASE( _PDCLIB_atomax( "123" ) == 123 );
/* testing skipping of leading whitespace and trailing garbage */
TESTCASE( _PDCLIB_atomax( " \n\v\t\f123xyz" ) == 123 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,83 @@
/* _PDCLIB_bigint_add( bigint_t *, bigint_t const * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
void _PDCLIB_bigint_add( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other )
{
unsigned i = 0;
_PDCLIB_bigint_arith_t arith = 0;
for ( i = bigint->size; i < other->size; ++i )
{
bigint->data[i] = 0;
}
bigint->size = i;
for ( i = 0; i < bigint->size; ++i )
{
arith += bigint->data[i] + other->data[i];
bigint->data[i] = arith & ( ( (_PDCLIB_bigint_arith_t)1 << _PDCLIB_BIGINT_DIGIT_BITS ) - 1 );
arith >>= _PDCLIB_BIGINT_DIGIT_BITS;
}
if ( arith > 0 )
{
bigint->data[i] = arith;
--(bigint->size);
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_t testdata[] =
{
{ 1, { 0x0001u } },
{ 2, { (_PDCLIB_bigint_digit_t)( ( (_PDCLIB_bigint_arith_t)1 << _PDCLIB_BIGINT_DIGIT_BITS ) - 1 ), 0x0001u } },
{ 1, { 0x0002u } },
{ 2, { 0x0001u, 0x0002u } },
{ 2, { 0x0000u, 0x0002u } }
};
/* 1 + 1 */
_PDCLIB_bigint_from_digit( &bigint, 1 );
_PDCLIB_bigint_add( &bigint, &bigint );
_PDCLIB_bigint_cmp( &bigint, &testdata[2] );
/* 1 + 0x0001 0xFFFF -- carry */
_PDCLIB_bigint_add( &bigint, &testdata[1] );
_PDCLIB_bigint_cmp( &bigint, &testdata[3] );
/* 0x0001 0xFFFF + 1 -- carry */
_PDCLIB_bigint_from_bigint( &bigint, &testdata[1] );
_PDCLIB_bigint_add( &bigint, &testdata[0] );
_PDCLIB_bigint_cmp( &bigint, &testdata[4] );
/* 0 + 0 */
_PDCLIB_bigint_from_digit( &bigint, 0 );
_PDCLIB_bigint_add( &bigint, &bigint );
TESTCASE( bigint.size == 0 );
/* 0 + 1 */
_PDCLIB_bigint_add( &bigint, &testdata[0] );
_PDCLIB_bigint_cmp( &bigint, &testdata[0] );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,74 @@
/* _PDCLIB_bigint_cmp( bigint_t const *, bigint_t const * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
int _PDCLIB_bigint_cmp( _PDCLIB_bigint_t const * lhs, _PDCLIB_bigint_t const * rhs )
{
_PDCLIB_size_t i = lhs->size;
if ( i != rhs->size )
{
return i > rhs->size ? 1 : -1;
}
while ( i-- > 0 )
{
if ( lhs->data[i] != rhs->data[i] )
{
return lhs->data[i] > rhs->data[i] ? 1 : -1;
}
}
return 0;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t lhs, rhs;
_PDCLIB_bigint_t testdata[] =
{
{ 2, { 0, 0x0001u } },
{ 1, { 1 } }
};
_PDCLIB_bigint_from_digit( &lhs, 0 );
_PDCLIB_bigint_from_digit( &rhs, 0 );
TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) == 0 );
_PDCLIB_bigint_add( &lhs, &testdata[1] );
TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) > 0 );
_PDCLIB_bigint_add( &rhs, &testdata[1] );
TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) == 0 );
_PDCLIB_bigint_add( &rhs, &testdata[1] );
TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) < 0 );
_PDCLIB_bigint_from_bigint( &lhs, &testdata[0] );
TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) > 0 );
_PDCLIB_bigint_from_bigint( &rhs, &testdata[0] );
TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) == 0 );
_PDCLIB_bigint_add( &rhs, &testdata[1] );
TESTCASE( _PDCLIB_bigint_cmp( &lhs, &rhs ) < 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,83 @@
/* _PDCLIB_bigint_digit_log2( bigint_t const * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <stdio.h>
int _PDCLIB_bigint_digit_log2( _PDCLIB_bigint_digit_t digit )
{
unsigned char log2_lookup[] =
{
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};
_PDCLIB_bigint_digit_t t;
#if _PDCLIB_BIGINT_DIGIT_BITS > 16
if ( ( t = ( digit >> 24 ) ) )
{
return log2_lookup[ t ] + 24;
}
else if ( ( t = ( digit >> 16 ) ) )
{
return log2_lookup[ t ] + 16;
}
else
#endif
if ( ( t = ( digit >> 8 ) ) )
{
return log2_lookup[ t ] + 8;
}
else if ( digit > 0 )
{
return log2_lookup[ digit ];
}
else
{
return -1;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <math.h>
int main( void )
{
#ifndef REGTEST
unsigned i;
for ( i = 1; i < (1 << _PDCLIB_BIGINT_DIGIT_BITS); ++i )
{
//TESTCASE( _PDCLIB_bigint_digit_log2( i ) == (int)log2( i ) );
}
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,135 @@
/* _PDCLIB_bigint_div( bigint_t *, bigint_t const * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <assert.h>
unsigned _PDCLIB_bigint_div( _PDCLIB_bigint_t * dividend, _PDCLIB_bigint_t const * divisor )
{
_PDCLIB_bigint_digit_t quotient;
_PDCLIB_size_t s = dividend->size;
_PDCLIB_size_t i;
assert( divisor->size > 0 );
assert( s <= divisor->size );
assert( divisor->data[ divisor->size - 1 ] < _PDCLIB_BIGINT_DIGIT_MAX );
if ( s < divisor->size || dividend->data[ s - 1 ] < divisor->data[ s - 1 ])
{
return 0;
}
/* With dividend truncated, and divisor + 1,
this quotient might be one short of correct.
*/
quotient = dividend->data[ s - 1 ] / ( divisor->data[ s - 1 ] + 1 );
if ( quotient > 0 )
{
/* dividend = dividend - (divisor * quotient) */
_PDCLIB_bigint_arith_t t = 0;
_PDCLIB_bigint_arith_t d = 0;
for ( i = 0; i < s; ++i )
{
t += (_PDCLIB_bigint_arith_t)divisor->data[i] * quotient;
d = (_PDCLIB_bigint_arith_t)dividend->data[i] - ( t & _PDCLIB_BIGINT_DIGIT_MAX ) - d;
dividend->data[i] = d & _PDCLIB_BIGINT_DIGIT_MAX;
t >>= _PDCLIB_BIGINT_DIGIT_BITS;
d >>= _PDCLIB_BIGINT_DIGIT_BITS;
d &= 1;
}
}
/* dividend might have leading zero digits here,
but that does not matter for the compare or
the subsequent substraction.
*/
if ( _PDCLIB_bigint_cmp( dividend, divisor ) >= 0 )
{
/* quotient was too small, substract divisor once more. */
_PDCLIB_bigint_arith_t d = 0;
++quotient;
for ( i = 0; i < s; ++i )
{
d = (_PDCLIB_bigint_arith_t)dividend->data[i] - divisor->data[i] - d;
dividend->data[i] = d & _PDCLIB_BIGINT_DIGIT_MAX;
d >>= _PDCLIB_BIGINT_DIGIT_BITS;
d &= 1;
}
}
/* size down dividend if it has leading zero digits. */
while ( dividend->size > 0 && dividend->data[ dividend->size - 1 ] == 0 )
{
--dividend->size;
}
return quotient;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t dividend;
_PDCLIB_bigint_t divisor;
_PDCLIB_bigint_t testdata[] =
{
{ 1, { 0x1234 } },
{ 2, { 0x2345, 0x0001 } },
{ 1, { 0x4000 } },
{ 1, { 0x3FFF } },
{ 1, { 0x0001 } },
{ 1, { _PDCLIB_BIGINT_DIGIT_MAX } },
{ 1, { 0xFFF9 } },
{ 1, { 0x1C71 } }
};
/* dividend < divisor */
_PDCLIB_bigint_from_bigint( &dividend, &testdata[0] );
_PDCLIB_bigint_from_bigint( &divisor, &testdata[1] );
TESTCASE( _PDCLIB_bigint_div( &dividend, &divisor ) == 0 );
TESTCASE( _PDCLIB_bigint_cmp( &dividend, &testdata[0] ) == 0 );
_PDCLIB_bigint_from_bigint( &dividend, &testdata[3] );
_PDCLIB_bigint_from_bigint( &divisor, &testdata[2] );
TESTCASE( _PDCLIB_bigint_div( &dividend, &divisor ) == 0 );
TESTCASE( _PDCLIB_bigint_cmp( &dividend, &testdata[3] ) == 0 );
/* dividend = divisor + 1 */
_PDCLIB_bigint_from_bigint( &dividend, &testdata[2] );
_PDCLIB_bigint_from_bigint( &divisor, &testdata[3] );
TESTCASE( _PDCLIB_bigint_div( &dividend, &divisor ) == 1 );
TESTCASE( _PDCLIB_bigint_cmp( &dividend, &testdata[4] ) == 0 );
/* dividend = divisor * 9 */
_PDCLIB_bigint_from_bigint( &dividend, &testdata[6] );
_PDCLIB_bigint_from_bigint( &divisor, &testdata[7] );
TESTCASE( _PDCLIB_bigint_div( &dividend, &divisor ) == 9 );
TESTCASE( dividend.size == 0 );
/* dividend = divisor * 9 + rem */
_PDCLIB_bigint_from_bigint( &dividend, &testdata[5] );
_PDCLIB_bigint_from_digit( &divisor, testdata[5].data[0] / 9 );
TESTCASE( _PDCLIB_bigint_div( &dividend, &divisor ) == 9 );
TESTCASE( dividend.data[0] == ( testdata[5].data[0] % 9 ) );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,54 @@
/* _PDCLIB_bigint_from_bigint( bigint_t *, bigint_t const * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
void _PDCLIB_bigint_from_bigint( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other )
{
_PDCLIB_size_t i;
for ( i = 0; i < other->size; ++i )
{
bigint->data[i] = other->data[i];
}
bigint->size = other->size;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_t testdata[] =
{
/* Only 16bit, works with 32bit digits as well. */
{ 0, { 0u } },
{ 1, { 0xFFFFu } },
{ 2, { 0xAAAAu, 0xFFFFu } }
};
_PDCLIB_bigint_from_bigint( &bigint, &testdata[0] );
TESTCASE( bigint.size == 0 );
_PDCLIB_bigint_from_bigint( &bigint, &testdata[1] );
_PDCLIB_bigint_cmp( &bigint, &testdata[1] );
_PDCLIB_bigint_from_bigint( &bigint, &testdata[2] );
_PDCLIB_bigint_cmp( &bigint, &testdata[2] );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,43 @@
/* _PDCLIB_bigint_from_digit( bigint_t *, digit_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
void _PDCLIB_bigint_from_digit( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_digit_t digit )
{
bigint->size = ( digit > 0 );
bigint->data[0] = digit;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_from_digit( &bigint, 0 );
TESTCASE( bigint.size == 0 );
_PDCLIB_bigint_from_digit( &bigint, 1 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 1 );
_PDCLIB_bigint_from_digit( &bigint, _PDCLIB_BIGINT_DIGIT_MAX );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == _PDCLIB_BIGINT_DIGIT_MAX );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,131 @@
/* _PDCLIB_bigint_from_pow10( bigint_t *, unsigned )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
void _PDCLIB_bigint_from_pow10( _PDCLIB_bigint_t * bigint, unsigned pow )
{
_PDCLIB_bigint_t powers_of_10[] =
{
{ 1, { 0x0001u } },
{ 1, { 0x000au } },
{ 1, { 0x0064u } },
{ 1, { 0x03e8u } },
{ 1, { 0x2710u } },
{ 2, { 0x86a0u, 0x0001u } },
{ 2, { 0x4240u, 0x000fu } },
{ 2, { 0x9680u, 0x0098u } },
{ 2, { 0xe100u, 0x05f5u } },
{ 4, { 0x0000u, 0x6fc1u, 0x86f2u, 0x0023u } },
{ 7, { 0x0000u, 0x0000u, 0xef81u, 0x85acu,
0x415bu, 0x2d6du, 0x04eeu } },
{ 14, { 0x0000u, 0x0000u, 0x0000u, 0x0000u,
0x1f01u, 0xbf6au, 0xed64u, 0x6e38u,
0x97edu, 0xdaa7u, 0xf9f4u, 0xe93fu,
0x4f03u, 0x0018u } },
{ 27, { 0x0000u, 0x0000u, 0x0000u, 0x0000u,
0x0000u, 0x0000u, 0x0000u, 0x0000u,
0x3e01u, 0x2e95u, 0x9909u, 0x03dfu,
0x38fdu, 0x0f15u, 0xe42fu, 0x2374u,
0xf5ecu, 0xd3cfu, 0xdc08u, 0xc404u,
0xb0dau, 0xbccdu, 0x7f19u, 0xa633u,
0x2603u, 0xe91fu, 0x024eu } },
{ 54, { 0x0000u, 0x0000u, 0x0000u, 0x0000u,
0x0000u, 0x0000u, 0x0000u, 0x0000u,
0x0000u, 0x0000u, 0x0000u, 0x0000u,
0x0000u, 0x0000u, 0x0000u, 0x0000u,
0x7c01u, 0x982eu, 0x875bu, 0xbed3u,
0x9f72u, 0xd8d9u, 0x2f87u, 0x1215u,
0x50c6u, 0x6bdeu, 0x6e70u, 0xcf4au,
0xd80fu, 0xd595u, 0x716eu, 0x26b2u,
0x66b0u, 0xadc6u, 0x3624u, 0x1d15u,
0xd35au, 0x3c42u, 0x540eu, 0x63ffu,
0x73c0u, 0xcc55u, 0xef17u, 0x65f9u,
0x28f2u, 0x55bcu, 0xc7f7u, 0x80dcu,
0xeddcu, 0xf46eu, 0xefceu, 0x5fdcu,
0x53f7u, 0x0005u } }
};
_PDCLIB_size_t index = 8;
_PDCLIB_bigint_from_bigint( bigint, &powers_of_10[ pow & 7 ] );
pow >>= 3;
while ( pow > 0 )
{
if ( pow & 1 )
{
_PDCLIB_bigint_mul( bigint, &powers_of_10[ index ] );
}
pow >>= 1;
++index;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_from_pow10( &bigint, 0 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 1 );
_PDCLIB_bigint_from_pow10( &bigint, 1 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 10 );
_PDCLIB_bigint_from_pow10( &bigint, 2 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 100 );
_PDCLIB_bigint_from_pow10( &bigint, 3 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 1000 );
_PDCLIB_bigint_from_pow10( &bigint, 4 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 10000 );
_PDCLIB_bigint_from_pow10( &bigint, 5 );
TESTCASE( bigint.size == 2 );
TESTCASE( bigint.data[1] == 1 );
TESTCASE( bigint.data[0] == 34464 );
_PDCLIB_bigint_from_pow10( &bigint, 6 );
TESTCASE( bigint.size == 2 );
TESTCASE( bigint.data[1] == 15 );
TESTCASE( bigint.data[0] == 16960 );
_PDCLIB_bigint_from_pow10( &bigint, 7 );
TESTCASE( bigint.size == 2 );
TESTCASE( bigint.data[1] == 152 );
TESTCASE( bigint.data[0] == 38528 );
_PDCLIB_bigint_from_pow10( &bigint, 8 );
TESTCASE( bigint.size == 2 );
TESTCASE( bigint.data[1] == 1525 );
TESTCASE( bigint.data[0] == 57600 );
_PDCLIB_bigint_from_pow10( &bigint, 9 );
TESTCASE( bigint.size == 2 );
TESTCASE( bigint.data[1] == 15258 );
TESTCASE( bigint.data[0] == 51712 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,54 @@
/* _PDCLIB_bigint_from_pow2( bigint_t *, unsigned )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <stdlib.h>
void _PDCLIB_bigint_from_pow2( _PDCLIB_bigint_t * bigint, unsigned pow )
{
ldiv_t dv = ldiv( pow, _PDCLIB_BIGINT_DIGIT_BITS );
long i;
for ( i = 0; i < dv.quot; ++i )
{
bigint->data[i] = 0;
}
bigint->data[i] = 1u << dv.rem;
bigint->size = i + 1;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_from_pow2( &bigint, 0 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 1 );
_PDCLIB_bigint_from_pow2( &bigint, 1 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 2 );
_PDCLIB_bigint_from_pow2( &bigint, 2 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 4 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,64 @@
/* _PDCLIB_bigint_log2( bigint_t const * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
int _PDCLIB_bigint_log2( _PDCLIB_bigint_t const * bigint )
{
_PDCLIB_size_t s = bigint->size;
if ( s == 0 )
{
return -1;
}
--s;
return _PDCLIB_bigint_digit_log2( bigint->data[ s ] ) + s * _PDCLIB_BIGINT_DIGIT_BITS;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_t one;
_PDCLIB_bigint_from_digit( &bigint, 0 );
_PDCLIB_bigint_from_digit( &one, 1 );
TESTCASE( _PDCLIB_bigint_log2( &bigint ) == -1 );
TESTCASE( _PDCLIB_bigint_log2( &one ) == 0 );
_PDCLIB_bigint_mul10( &one );
TESTCASE( _PDCLIB_bigint_log2( &one ) == 3 );
_PDCLIB_bigint_mul10( &one );
TESTCASE( _PDCLIB_bigint_log2( &one ) == 6 );
_PDCLIB_bigint_mul10( &one );
TESTCASE( _PDCLIB_bigint_log2( &one ) == 9 );
_PDCLIB_bigint_mul10( &one );
TESTCASE( _PDCLIB_bigint_log2( &one ) == 13 );
_PDCLIB_bigint_mul10( &one );
TESTCASE( _PDCLIB_bigint_log2( &one ) == 16 );
_PDCLIB_bigint_mul10( &one );
TESTCASE( _PDCLIB_bigint_log2( &one ) == 19 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,121 @@
/* _PDCLIB_bigint_mul( bigint_t *, bigint_t const * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
void _PDCLIB_bigint_mul( _PDCLIB_bigint_t * bigint, _PDCLIB_bigint_t const * other )
{
_PDCLIB_size_t s = other->size;
_PDCLIB_size_t b = bigint->size;
if ( s == 0 || b == 0 )
{
_PDCLIB_bigint_from_digit( bigint, 0 );
return;
}
{
_PDCLIB_bigint_t result = { s + b, { 0 } };
_PDCLIB_bigint_t const * small;
_PDCLIB_bigint_t const * big;
if ( s <= b )
{
small = other;
big = bigint;
}
else
{
small = bigint;
big = other;
}
for ( s = 0; s < small->size; ++s )
{
_PDCLIB_bigint_arith_t t = 0;
for ( b = 0; b < big->size; ++b )
{
t += result.data[ s + b ]
+ (_PDCLIB_bigint_arith_t)small->data[ s ]
* (_PDCLIB_bigint_arith_t)big->data[ b ];
result.data[ s + b ] = t & ( ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS ) - 1 );
t >>= _PDCLIB_BIGINT_DIGIT_BITS;
}
result.data[ s + b ] = t & ( ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS ) - 1 );
}
while ( result.data[ result.size - 1 ] == 0 )
{
--result.size;
}
_PDCLIB_bigint_from_bigint( bigint, &result );
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_t testdata[] =
{
{ 1, { 0x0001u } },
{ 1, { 0x0002u } },
{ 1, { ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 1 } },
{ 2, { ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 1, 1u } }
};
_PDCLIB_bigint_from_bigint( &bigint, &testdata[0] );
_PDCLIB_bigint_mul( &bigint, &testdata[0] );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 1u );
_PDCLIB_bigint_mul( &bigint, &testdata[1] );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 2u );
_PDCLIB_bigint_mul( &bigint, &testdata[2] );
TESTCASE( bigint.size == 2 );
TESTCASE( bigint.data[0] == ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 2 );
TESTCASE( bigint.data[1] == 1u );
_PDCLIB_bigint_mul( &bigint, &testdata[1] );
TESTCASE( bigint.size == 2 );
TESTCASE( bigint.data[0] == ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 4 );
TESTCASE( bigint.data[1] == 3u );
_PDCLIB_bigint_from_bigint( &bigint, &testdata[3] );
_PDCLIB_bigint_mul( &bigint, &bigint );
TESTCASE( bigint.data[0] == 1 );
TESTCASE( bigint.data[1] == ( (_PDCLIB_bigint_arith_t)1u << _PDCLIB_BIGINT_DIGIT_BITS) - 4 );
#if _PDCLIB_BIGINT_DIGIT_BITS == 16
TESTCASE( bigint.size == 3 );
TESTCASE( bigint.data[2] == 3 );
#else
TESTCASE( bigint.size == 2 );
#endif
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,58 @@
/* _PDCLIB_bigint_mul10( bigint_t * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
void _PDCLIB_bigint_mul10( _PDCLIB_bigint_t * bigint )
{
_PDCLIB_bigint_arith_t t = 0;
_PDCLIB_size_t i;
for ( i = 0; i < bigint->size; ++i )
{
t = (_PDCLIB_bigint_arith_t)bigint->data[ i ] * 10 + t;
bigint->data[ i ] = t & _PDCLIB_BIGINT_DIGIT_MAX;
t >>= _PDCLIB_BIGINT_DIGIT_BITS;
}
if ( t > 0 )
{
bigint->data[ bigint->size++ ] = t;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_t testdata[] =
{
{ 2, { 0x8080u, 0x0101u } },
{ 2, { 0x0500u, 0x0a0fu } },
{ 1, { 0x000au } }
};
_PDCLIB_bigint_from_digit( &bigint, 1 );
_PDCLIB_bigint_mul10( &bigint );
TESTCASE( _PDCLIB_bigint_cmp( &bigint, &testdata[2] ) == 0 );
_PDCLIB_bigint_from_bigint( &bigint, &testdata[0] );
_PDCLIB_bigint_mul10( &bigint );
TESTCASE( _PDCLIB_bigint_cmp( &bigint, &testdata[1] ) == 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,30 @@
/* _PDCLIB_bigint_mul_pow10( bigint_t *, int pow10 )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
void _PDCLIB_bigint_mul_pow10( _PDCLIB_bigint_t * bigint, int pow10 )
{
_PDCLIB_bigint_t multiplier;
_PDCLIB_bigint_from_pow10( &multiplier, pow10 );
_PDCLIB_bigint_mul( bigint, &multiplier );
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
TESTCASE( NO_TESTDRIVER );
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,83 @@
/* _PDCLIB_bigint_shl( bigint_t *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <stdlib.h>
void _PDCLIB_bigint_shl( _PDCLIB_bigint_t * bigint, _PDCLIB_size_t bits )
{
ldiv_t dv = ldiv( bits, _PDCLIB_BIGINT_DIGIT_BITS );
_PDCLIB_bigint_arith_t t = 0;
size_t i;
if ( dv.quot > 0 )
{
i = bigint->size;
/* shifting whole digits */
while ( i-- > 0 )
{
bigint->data[ i + dv.quot ] = bigint->data[ i ];
}
bigint->size += dv.quot;
/* zero out shifted low digits */
while ( (long)i < dv.quot )
{
bigint->data[ i++ ] = 0;
}
}
for ( i = dv.quot; i < bigint->size; ++i )
{
t = ( (_PDCLIB_bigint_arith_t)bigint->data[ i ] << dv.rem ) + t;
bigint->data[ i ] = t & _PDCLIB_BIGINT_DIGIT_MAX;
t >>= _PDCLIB_BIGINT_DIGIT_BITS;
}
if ( t > 0 )
{
bigint->data[ bigint->size++ ] = t;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_bigint_t bigint;
_PDCLIB_bigint_t testdata[] =
{
{ 2, { 0x8080u, 0x0101u } },
{ 3, { 0x0000u, 0x0100u, 0x0203u } }
};
_PDCLIB_bigint_from_digit( &bigint, 1 );
_PDCLIB_bigint_shl( &bigint, 2 );
TESTCASE( bigint.size == 1 );
TESTCASE( bigint.data[0] == 4 );
_PDCLIB_bigint_from_bigint( &bigint, &testdata[0] );
_PDCLIB_bigint_shl( &bigint, _PDCLIB_BIGINT_DIGIT_BITS + 1 );
TESTCASE( bigint.size == 3 );
TESTCASE( bigint.data[0] == 0 );
TESTCASE( bigint.data[1] == 0x0100 );
TESTCASE( bigint.data[2] == 0x0203 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,73 @@
/* _PDCLIB_changemode( FILE * stream, int mode )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
/* This is a utility function used by freopen, to allow for a rather
specific bit of trickery.
ISO/IEC 9899:2011 (i.e., the ISO C standard) is ambiguous in the case
of the filename argument being NULL. It states that the mode of the
open stream could be _changed_ in implementation-defined circumstances.
While it goes on to state that freopen will "first attempt to close any
file that is associated with the specified stream", it is not quite
clear if the "implementation-defined circumstances" mentioned earlier
would include changing the mode without actually closing the file.
IEEE Std 1003.1, 2004 Edition (POSIX) on the other hand is less
ambiguous, as it states that "the file descriptor associated with the
stream need not be closed if the call to freopen() succeeds" for the
same case (filename being NULL).
This function gets called by PDCLib's freopen() in just that case,
allowing you to perform whatever mode changes YOUR implementation
decides to support. Return zero if the change requested is not
supported and freopen() should attempt the close-and-open-again way.
Return INT_MIN if the change request is not supported and freopen()
should fail. Return any other value if the requested mode change was
supported and successful.
*/
/* This is a dummy implementation of _PDCLIB_open() not supporting any
mode changes.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#include <limits.h>
#include <stddef.h>
int _PDCLIB_changemode( struct _PDCLIB_file_t * stream, unsigned int mode )
{
if ( mode == 0 )
{
return INT_MIN;
}
/* Attempt mode change without closing the stream */
if ( stream->filename == NULL )
{
/* Standard stream, no filename for reopen */
return INT_MIN;
}
else
{
/* Stream with file associated, attempt reopen */
return 0;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* No test drivers. */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,44 @@
/* _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 <stdio.h>
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#ifdef __cplusplus
extern "C" {
#endif
extern int close( int fd );
#ifdef __cplusplus
}
#endif
int _PDCLIB_close( int fd )
{
return close( fd );
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* No testdriver; tested in driver for _PDCLIB_open(). */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,38 @@
/* _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>
#ifndef REGTEST
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;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* No testdriver */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,33 @@
/* _PDCLIB_digits
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_internal.h"
const char _PDCLIB_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
/* For _PDCLIB/print.c only; obsolete with ctype.h */
const char _PDCLIB_Xdigits[] = "0123456789ABCDEF";
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <string.h>
int main( void )
{
#ifndef REGTEST
TESTCASE( strcmp( _PDCLIB_digits, "0123456789abcdefghijklmnopqrstuvwxyz" ) == 0 );
TESTCASE( strcmp( _PDCLIB_Xdigits, "0123456789ABCDEF" ) == 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,114 @@
/* _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>
#ifndef REGTEST
/* 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;
if ( mode == NULL )
{
return 0;
}
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 )
{
/* Duplicates are invalid */
return 0;
}
rc |= _PDCLIB_FRW;
break;
case 'b':
if ( rc & _PDCLIB_FBIN )
{
/* Duplicates are invalid */
return 0;
}
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;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
TESTCASE( _PDCLIB_filemode( "r" ) == _PDCLIB_FREAD );
TESTCASE( _PDCLIB_filemode( "w" ) == _PDCLIB_FWRITE );
TESTCASE( _PDCLIB_filemode( "a" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE ) );
TESTCASE( _PDCLIB_filemode( "r+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW ) );
TESTCASE( _PDCLIB_filemode( "w+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW ) );
TESTCASE( _PDCLIB_filemode( "a+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE | _PDCLIB_FRW ) );
TESTCASE( _PDCLIB_filemode( "rb" ) == ( _PDCLIB_FREAD | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "wb" ) == ( _PDCLIB_FWRITE | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "ab" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "r+b" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "w+b" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "a+b" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "rb+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "wb+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "ab+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
TESTCASE( _PDCLIB_filemode( "x" ) == 0 );
TESTCASE( _PDCLIB_filemode( "r++" ) == 0 );
TESTCASE( _PDCLIB_filemode( "wbb" ) == 0 );
TESTCASE( _PDCLIB_filemode( "a+bx" ) == 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,77 @@
/* _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>
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#include "pdclib/_PDCLIB_platform_errno.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef long ssize_t;
extern ssize_t read( int fd, void * buf, size_t count );
#ifdef __cplusplus
}
#endif
int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream )
{
/* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */
ssize_t rc = read( stream->handle, stream->buffer, stream->bufsize );
if ( rc > 0 )
{
/* Reading successful. */
if ( !( stream->status & _PDCLIB_FBIN ) )
{
/* TODO: Text stream conversion here */
}
stream->pos.offset += rc;
stream->bufend = rc;
stream->bufidx = 0;
return 0;
}
if ( rc < 0 )
{
/* The 1:1 mapping done in _PDCLIB_config.h ensures
this works.
*/
*_PDCLIB_errno_func() = errno;
/* Flag the stream */
stream->status |= _PDCLIB_ERRORFLAG;
return EOF;
}
/* End-of-File */
stream->status |= _PDCLIB_EOFFLAG;
return EOF;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Testing covered by ftell.c */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,103 @@
/* _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 <string.h>
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#include "pdclib/_PDCLIB_platform_errno.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef long ssize_t;
extern ssize_t write( int fd, const void * buf, size_t count );
#ifdef __cplusplus
}
#endif
/* The number of attempts of output buffer flushing before giving up. */
#define _PDCLIB_IO_RETRIES 1
/* What the system should do after an I/O operation did not succeed, before */
/* trying again. (Empty by default.) */
#define _PDCLIB_IO_RETRY_OP( stream )
int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream )
{
/* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */
_PDCLIB_size_t written = 0;
int rc;
unsigned int retries;
if ( !( stream->status & _PDCLIB_FBIN ) )
{
/* TODO: Text stream conversion here */
}
/* Keep trying to write data until everything is written, an error
occurs, or the configured number of retries is exceeded.
*/
for ( retries = _PDCLIB_IO_RETRIES; retries > 0; --retries )
{
rc = ( int )write( stream->handle, stream->buffer + written, stream->bufidx - written );
if ( rc < 0 )
{
/* The 1:1 mapping done in _PDCLIB_config.h ensures
this works.
*/
*_PDCLIB_errno_func() = errno;
/* Flag the stream */
stream->status |= _PDCLIB_ERRORFLAG;
/* Move unwritten remains to begin of buffer. */
stream->bufidx -= written;
memmove( stream->buffer, stream->buffer + written, stream->bufidx );
return EOF;
}
written += ( _PDCLIB_size_t )rc;
stream->pos.offset += rc;
if ( written == stream->bufidx )
{
/* Buffer written completely. */
stream->bufidx = 0;
return 0;
}
}
/* Number of retries exceeded. */
*_PDCLIB_errno_func() = _PDCLIB_EAGAIN;
stream->status |= _PDCLIB_ERRORFLAG;
/* Move unwritten remains to begin of buffer. */
stream->bufidx -= written;
memmove( stream->buffer, stream->buffer + written, stream->bufidx );
return EOF;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Testing covered by ftell.c */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,106 @@
/* _PDCLIB_fp_from_dbl( _PDCLIB_fp_t *, double )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <stdlib.h>
#include <string.h>
void _PDCLIB_fp_from_dbl( _PDCLIB_fp_t * fp, double d )
{
memcpy( fp->mantissa.data, &d, sizeof( double ) );
fp->sign = _PDCLIB_DBL_SIGN( fp->mantissa.data );
fp->exponent = _PDCLIB_DBL_EXP( fp->mantissa.data );
fp->mantissa.size = _PDCLIB_DBL_SIZE( fp->mantissa.data );
switch ( fp->exponent )
{
case 0:
fp->state = _PDCLIB_FP_SUBNORMAL;
fp->exponent = 1 - ( _PDCLIB_DBL_MAX_EXP - 1 );
fp->scale = _PDCLIB_DBL_MANT_DIG - 1;
break;
case ( _PDCLIB_DBL_MAX_EXP - 1 ) + _PDCLIB_DBL_MAX_EXP:
fp->state = _PDCLIB_FP_NAN;
break;
default:
{
div_t dv = div( _PDCLIB_DBL_MANT_DIG - 1, _PDCLIB_BIGINT_DIGIT_BITS );
fp->state = _PDCLIB_FP_NORMAL;
if ( dv.rem == 0 )
{
fp->mantissa.data[ fp->mantissa.size++ ] = 1u;
}
else
{
fp->mantissa.data[ dv.quot ] |= ( 1u << dv.rem );
}
fp->exponent -= ( _PDCLIB_DBL_MAX_EXP - 1 );
fp->scale = _PDCLIB_DBL_MANT_DIG - 1;
break;
}
}
while ( fp->mantissa.size > 0 && fp->mantissa.data[ fp->mantissa.size - 1 ] == 0 )
{
--fp->mantissa.size;
}
if ( ( fp->state == _PDCLIB_FP_NAN ) && ( fp->mantissa.size == 0 ) )
{
fp->state = _PDCLIB_FP_INF;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_fp_t fp;
_PDCLIB_bigint_t t;
/* Normal */
_PDCLIB_fp_from_dbl( &fp, -1.0 );
_PDCLIB_bigint_from_pow2( &t, _PDCLIB_DBL_MANT_DIG - 1 );
TESTCASE( fp.state == _PDCLIB_FP_NORMAL );
TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 );
TESTCASE( fp.scale == ( _PDCLIB_DBL_MANT_DIG - 1 ) );
TESTCASE( fp.exponent == 0 );
/* Inf */
_PDCLIB_fp_from_dbl( &fp, 1e500 );
TESTCASE( fp.state == _PDCLIB_FP_INF );
TESTCASE( fp.mantissa.size == 0 );
/* NaN */
_PDCLIB_fp_from_dbl( &fp, -0.0/0.0 );
_PDCLIB_bigint_from_pow2( &t, _PDCLIB_DBL_MANT_DIG - 2 );
TESTCASE( fp.state == _PDCLIB_FP_NAN );
TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 );
/* Subnormal */
_PDCLIB_fp_from_dbl( &fp, _PDCLIB_DBL_MIN / 2 );
_PDCLIB_bigint_from_pow2( &t, _PDCLIB_DBL_MANT_DIG - 2 );
TESTCASE( fp.state == _PDCLIB_FP_SUBNORMAL );
TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 );
TESTCASE( fp.scale == ( _PDCLIB_DBL_MANT_DIG - 1 ) );
TESTCASE( fp.exponent == (_PDCLIB_int_least16_t)(1 - ( _PDCLIB_DBL_MAX_EXP - 1 ) ) );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,106 @@
/* _PDCLIB_fp_from_ldbl( _PDCLIB_fp_t *, long double )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <stdlib.h>
#include <string.h>
void _PDCLIB_fp_from_ldbl( _PDCLIB_fp_t * fp, long double ld )
{
memcpy( fp->mantissa.data, &ld, sizeof( long double ) );
fp->sign = _PDCLIB_LDBL_SIGN( fp->mantissa.data );
fp->exponent = _PDCLIB_LDBL_EXP( fp->mantissa.data );
fp->mantissa.size = _PDCLIB_LDBL_SIZE( fp->mantissa.data );
switch ( fp->exponent )
{
case 0:
fp->state = _PDCLIB_FP_SUBNORMAL;
fp->exponent = 1 - ( _PDCLIB_LDBL_MAX_EXP - 1 );
fp->scale = _PDCLIB_LDBL_MANT_DIG - 1;
break;
case ( _PDCLIB_LDBL_MAX_EXP - 1 ) + _PDCLIB_LDBL_MAX_EXP:
fp->state = _PDCLIB_FP_NAN;
break;
default:
{
div_t dv = div( _PDCLIB_LDBL_MANT_DIG - 1, _PDCLIB_BIGINT_DIGIT_BITS );
fp->state = _PDCLIB_FP_NORMAL;
if ( dv.rem == 0 )
{
fp->mantissa.data[ fp->mantissa.size++ ] = 1u;
}
else
{
fp->mantissa.data[ dv.quot ] |= ( 1u << dv.rem );
}
fp->exponent -= ( _PDCLIB_LDBL_MAX_EXP - 1 );
fp->scale = _PDCLIB_LDBL_MANT_DIG - 1;
break;
}
}
while ( fp->mantissa.size > 0 && fp->mantissa.data[ fp->mantissa.size - 1 ] == 0 )
{
--fp->mantissa.size;
}
if ( ( fp->state == _PDCLIB_FP_NAN ) && ( fp->mantissa.size == 0 ) )
{
fp->state = _PDCLIB_FP_INF;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
_PDCLIB_fp_t fp;
_PDCLIB_bigint_t t;
/* Normal */
_PDCLIB_fp_from_ldbl( &fp, -1.0L );
_PDCLIB_bigint_from_pow2( &t, _PDCLIB_LDBL_MANT_DIG - 1 );
TESTCASE( fp.state == _PDCLIB_FP_NORMAL );
TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 );
TESTCASE( fp.scale == ( _PDCLIB_LDBL_MANT_DIG - 1 ) );
TESTCASE( fp.exponent == 0 );
/* Inf */
_PDCLIB_fp_from_ldbl( &fp, 1e5000L );
TESTCASE( fp.state == _PDCLIB_FP_INF );
TESTCASE( fp.mantissa.size == 0 );
/* NaN */
_PDCLIB_fp_from_ldbl( &fp, -0.0L/0.0L );
_PDCLIB_bigint_from_pow2( &t, _PDCLIB_LDBL_MANT_DIG - 2 );
TESTCASE( fp.state == _PDCLIB_FP_NAN );
TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 );
/* Subnormal */
_PDCLIB_fp_from_ldbl( &fp, _PDCLIB_LDBL_MIN / 2L );
_PDCLIB_bigint_from_pow2( &t, _PDCLIB_LDBL_MANT_DIG - 2 );
TESTCASE( fp.state == _PDCLIB_FP_SUBNORMAL );
TESTCASE( _PDCLIB_bigint_cmp( &fp.mantissa, &t ) == 0 );
TESTCASE( fp.scale == ( _PDCLIB_LDBL_MANT_DIG - 1 ) );
TESTCASE( fp.exponent == (_PDCLIB_int_least16_t)(1 - ( _PDCLIB_LDBL_MAX_EXP - 1 ) ) );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,49 @@
/* _PDCLIB_getstream( 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>
#ifndef REGTEST
#include "pdclib/_PDCLIB_internal.h"
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
int _PDCLIB_getstream( struct _PDCLIB_file_t * stream )
{
struct _PDCLIB_file_t * previous;
if ( ! _PDCLIB_isstream( stream, &previous ) )
{
*_PDCLIB_errno_func() = _PDCLIB_EBADF;
return EOF;
}
if ( previous != NULL )
{
previous->next = stream->next;
}
else
{
_PDCLIB_filelist = stream->next;
}
return 0;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* No testdriver */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,82 @@
/* _PDCLIB_init_file_t( _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.
*/
#ifndef REGTEST
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef __STDC_NO_THREADS__
#include <threads.h>
#endif
struct _PDCLIB_file_t * _PDCLIB_init_file_t( struct _PDCLIB_file_t * stream )
{
struct _PDCLIB_file_t * rc = stream;
if ( rc == NULL )
{
if ( ( rc = (struct _PDCLIB_file_t *)malloc( sizeof( struct _PDCLIB_file_t ) ) ) == NULL )
{
/* No memory */
return NULL;
}
}
if ( ( rc->buffer = (char *)malloc( BUFSIZ ) ) == NULL )
{
/* No memory */
free( rc );
return NULL;
}
rc->bufsize = BUFSIZ;
rc->bufidx = 0;
rc->bufend = 0;
rc->pos.offset = 0;
rc->pos.status = 0;
rc->ungetidx = 0;
rc->status = _PDCLIB_FREEBUFFER;
#ifndef __STDC_NO_THREADS__
if ( stream == NULL )
{
/* If called by freopen() (stream not NULL), mutex is already
initialized.
*/
if ( mtx_init( &rc->mtx, mtx_plain | mtx_recursive ) != thrd_success )
{
/* could not initialize stream mutex */
free( rc->buffer );
free( rc );
return NULL;
}
}
#endif
/* TODO: Setting mbstate */
return rc;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
TESTCASE( NO_TESTDRIVER );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,39 @@
/* _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.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_internal.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 ) );
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
/* 1901 not leap */
TESTCASE( ! _PDCLIB_is_leap( 1 ) );
/* 1904 leap */
TESTCASE( _PDCLIB_is_leap( 4 ) );
/* 1900 not leap */
TESTCASE( ! _PDCLIB_is_leap( 0 ) );
/* 2000 leap */
TESTCASE( _PDCLIB_is_leap( 100 ) );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,49 @@
/* _PDCLIB_isstream( FILE *, 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>
#ifndef REGTEST
#include "pdclib/_PDCLIB_internal.h"
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
int _PDCLIB_isstream( struct _PDCLIB_file_t * stream, struct _PDCLIB_file_t ** previous )
{
struct _PDCLIB_file_t * current = _PDCLIB_filelist;
if ( previous != NULL )
{
*previous = NULL;
}
while ( ( current != NULL ) && ( current != stream ) )
{
if ( previous != NULL )
{
*previous = current;
}
current = current->next;
}
return current != NULL;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* No testdriver */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,63 @@
/* _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.
*/
#ifndef REGTEST
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_collate_t *)malloc( sizeof( struct _PDCLIB_lc_collate_t ) ) ) != NULL )
{
/* TODO: Collation data */
rc->alloced = 1;
}
fclose( fh );
}
free( file );
}
return rc;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
TESTCASE( NO_TESTDRIVER );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,365 @@
/* _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.
*/
#ifndef REGTEST
#include <inttypes.h>
#include <limits.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_ctype_t *)malloc( sizeof( struct _PDCLIB_lc_ctype_t ) ) ) != NULL )
{
struct _PDCLIB_lc_ctype_entry_t * entry;
if ( ( entry = (struct _PDCLIB_lc_ctype_entry_t *)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, "%" SCNx16 " %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;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <ctype.h>
int main( void )
{
#ifndef REGTEST
FILE * fh = fopen( "test_ctype.dat", "wb" );
TESTCASE( fh != NULL );
/* For test purposes, let's set up a charset that only has the hex digits */
/* 0x00..0x09 - digits */
/* 0x11..0x16 - Xdigits */
/* 0x21..0x26 - xdigits */
TESTCASE( fprintf( fh, "%x %x\n", 0x00, 0x09 ) );
TESTCASE( fprintf( fh, "%x %x %x %x\n", 0x11, 0x16, 0x21, 0x26 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x00, 0x00 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x01, 0x01 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x02, 0x02 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x03, 0x03 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x04, 0x04 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x05, 0x05 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x06, 0x06 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x07, 0x07 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x08, 0x08 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH, 0x09, 0x09 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0A, 0x0A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0B, 0x0B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0C, 0x0C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0D, 0x0D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0E, 0x0E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x0F, 0x0F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x10, 0x10 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x11, 0x11 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x12, 0x12 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x13, 0x13 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x14, 0x14 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x15, 0x15 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_UPPER, 0x16, 0x16 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x17, 0x17 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x18, 0x18 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x19, 0x19 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1A, 0x1A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1B, 0x1B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1C, 0x1C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1D, 0x1D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1E, 0x1E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x1F, 0x1F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x20, 0x20 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x21, 0x21 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x22, 0x22 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x23, 0x23 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x24, 0x24 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x25, 0x25 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", _PDCLIB_CTYPE_GRAPH | _PDCLIB_CTYPE_ALPHA | _PDCLIB_CTYPE_LOWER, 0x26, 0x26 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x27, 0x27 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x28, 0x28 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x29, 0x29 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2A, 0x2A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2B, 0x2B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2C, 0x2C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2D, 0x2D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2E, 0x2E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x2F, 0x2F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x30, 0x30 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x31, 0x31 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x32, 0x32 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x33, 0x33 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x34, 0x34 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x35, 0x35 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x36, 0x36 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x37, 0x37 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x38, 0x38 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x39, 0x39 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3A, 0x3A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3B, 0x3B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3C, 0x3C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3D, 0x3D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3E, 0x3E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x3F, 0x3F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x40, 0x40 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x41, 0x41 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x42, 0x42 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x43, 0x43 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x44, 0x44 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x45, 0x45 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x46, 0x46 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x47, 0x47 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x48, 0x48 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x49, 0x49 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4A, 0x4A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4B, 0x4B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4C, 0x4C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4D, 0x4D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4E, 0x4E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x4F, 0x4F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x50, 0x50 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x51, 0x51 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x52, 0x52 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x53, 0x53 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x54, 0x54 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x55, 0x55 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x56, 0x56 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x57, 0x57 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x58, 0x58 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x59, 0x59 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5A, 0x5A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5B, 0x5B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5C, 0x5C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5D, 0x5D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5E, 0x5E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x5F, 0x5F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x60, 0x60 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x61, 0x61 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x62, 0x62 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x63, 0x63 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x64, 0x64 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x65, 0x65 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x66, 0x66 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x67, 0x67 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x68, 0x68 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x69, 0x69 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6A, 0x6A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6B, 0x6B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6C, 0x6C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6D, 0x6D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6E, 0x6E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x6F, 0x6F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x70, 0x70 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x71, 0x71 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x72, 0x72 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x73, 0x73 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x74, 0x74 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x75, 0x75 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x76, 0x76 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x77, 0x77 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x78, 0x78 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x79, 0x79 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7A, 0x7A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7B, 0x7B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7C, 0x7C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7D, 0x7D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7E, 0x7E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x7F, 0x7F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x80, 0x80 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x81, 0x81 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x82, 0x82 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x83, 0x83 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x84, 0x84 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x85, 0x85 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x86, 0x86 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x87, 0x87 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x88, 0x88 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x89, 0x89 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8A, 0x8A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8B, 0x8B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8C, 0x8C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8D, 0x8D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8E, 0x8E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x8F, 0x8F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x90, 0x90 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x91, 0x91 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x92, 0x92 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x93, 0x93 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x94, 0x94 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x95, 0x95 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x96, 0x96 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x97, 0x97 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x98, 0x98 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x99, 0x99 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9A, 0x9A ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9B, 0x9B ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9C, 0x9C ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9D, 0x9D ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9E, 0x9E ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0x9F, 0x9F ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA0, 0xA0 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA1, 0xA1 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA2, 0xA2 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA3, 0xA3 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA4, 0xA4 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA5, 0xA5 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA6, 0xA6 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA7, 0xA7 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA8, 0xA8 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xA9, 0xA9 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAA, 0xAA ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAB, 0xAB ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAC, 0xAC ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAD, 0xAD ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAE, 0xAE ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xAF, 0xAF ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB0, 0xB0 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB1, 0xB1 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB2, 0xB2 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB3, 0xB3 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB4, 0xB4 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB5, 0xB5 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB6, 0xB6 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB7, 0xB7 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB8, 0xB8 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xB9, 0xB9 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBA, 0xBA ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBB, 0xBB ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBC, 0xBC ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBD, 0xBD ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBE, 0xBE ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xBF, 0xBF ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC0, 0xC0 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC1, 0xC1 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC2, 0xC2 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC3, 0xC3 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC4, 0xC4 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC5, 0xC5 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC6, 0xC6 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC7, 0xC7 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC8, 0xC8 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xC9, 0xC9 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCA, 0xCA ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCB, 0xCB ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCC, 0xCC ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCD, 0xCD ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCE, 0xCE ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xCF, 0xCF ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD0, 0xD0 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD1, 0xD1 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD2, 0xD2 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD3, 0xD3 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD4, 0xD4 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD5, 0xD5 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD6, 0xD6 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD7, 0xD7 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD8, 0xD8 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xD9, 0xD9 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDA, 0xDA ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDB, 0xDB ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDC, 0xDC ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDD, 0xDD ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDE, 0xDE ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xDF, 0xDF ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE0, 0xE0 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE1, 0xE1 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE2, 0xE2 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE3, 0xE3 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE4, 0xE4 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE5, 0xE5 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE6, 0xE6 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE7, 0xE7 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE8, 0xE8 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xE9, 0xE9 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEA, 0xEA ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEB, 0xEB ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEC, 0xEC ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xED, 0xED ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEE, 0xEE ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xEF, 0xEF ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF0, 0xF0 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF1, 0xF1 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF2, 0xF2 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF3, 0xF3 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF4, 0xF4 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF5, 0xF5 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF6, 0xF6 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF7, 0xF7 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF8, 0xF8 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xF9, 0xF9 ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFA, 0xFA ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFB, 0xFB ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFC, 0xFC ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFD, 0xFD ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFE, 0xFE ) );
TESTCASE( fprintf( fh, "%x %x %x\n", 0x00, 0xFF, 0xFF ) );
fclose( fh );
TESTCASE( _PDCLIB_load_lc_ctype( "./", "test" ) != NULL );
remove( "test_ctype.dat" );
/*
TESTCASE( isdigit( 0x00 ) && ! isxdigit( 0x00 ) && ! isalpha( 0x00 ) );
TESTCASE( ! isdigit( 0x11 ) && isxdigit( 0x11 ) && isalpha( 0x11 ) && isupper( 0x11 ) && ! islower( 0x11 ) );
TESTCASE( ! isdigit( 0x21 ) && isxdigit( 0x21 ) && isalpha( 0x21 ) && ! isupper( 0x11 ) && islower( 0x11 ) );
*/
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,88 @@
/* _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.
*/
#ifndef REGTEST
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_messages_t *)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;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
FILE * fh = fopen( "test_numeric.dat", "wb" );
struct _PDCLIB_lc_lconv_numeric_t * lc;
TESTCASE( fh != NULL );
TESTCASE( fputs( ",\n.\n\n", fh ) != EOF );
fclose( fh );
TESTCASE( ( lc = _PDCLIB_load_lc_numeric( "./", "test" ) ) );
remove( "test_numeric.dat" );
TESTCASE( strcmp( lc->decimal_point, "," ) == 0 );
TESTCASE( strcmp( lc->thousands_sep, "." ) == 0 );
TESTCASE( strcmp( lc->grouping, "" ) == 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,158 @@
/* _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.
*/
#ifndef REGTEST
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_lconv_monetary_t *)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;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
FILE * fh = fopen( "test_monetary.dat", "wb" );
struct _PDCLIB_lc_lconv_monetary_t * lc;
TESTCASE( fh != NULL );
fprintf( fh, "%s\n", "," ); /* mon_decimal_point */
fprintf( fh, "%s\n", "." ); /* mon_thousands_sep */
fprintf( fh, "%s\n", "3" ); /* mon_grouping */
fprintf( fh, "%s\n", "" ); /* positive_sign */
fprintf( fh, "%s\n", "-" ); /* negative_sign */
fprintf( fh, "%s\n", "\xa4" ); /* currency_symbol */
fprintf( fh, "%s\n", "EUR" ); /* int_curr_symbol */
fputc( 2, fh ); /* frac_digits */
fputc( 0, fh ); /* p_cs_precedes */
fputc( 0, fh ); /* n_cs_precedes */
fputc( 1, fh ); /* p_sep_by_space */
fputc( 1, fh ); /* n_sep_by_space */
fputc( 1, fh ); /* p_sign_posn */
fputc( 1, fh ); /* n_sign_posn */
fputc( 2, fh ); /* int_frac_digits */
fputc( 0, fh ); /* int_p_cs_precedes */
fputc( 0, fh ); /* int_n_cs_precedes */
fputc( 1, fh ); /* int_p_sep_by_space */
fputc( 1, fh ); /* int_n_sep_by_space */
fputc( 1, fh ); /* int_p_sign_posn */
fputc( 1, fh ); /* int_n_sign_posn */
fprintf( fh, "\n" );
fclose( fh );
TESTCASE( ( lc = _PDCLIB_load_lc_monetary( "./", "test" ) ) );
remove( "test_monetary.dat" );
TESTCASE( strcmp( lc->mon_decimal_point, "," ) == 0 );
TESTCASE( strcmp( lc->mon_thousands_sep, "." ) == 0 );
TESTCASE( strcmp( lc->mon_grouping, "3" ) == 0 );
TESTCASE( strcmp( lc->positive_sign, "" ) == 0 );
TESTCASE( strcmp( lc->negative_sign, "-" ) == 0 );
TESTCASE( strcmp( lc->currency_symbol, "\xa4" ) == 0 );
TESTCASE( strcmp( lc->int_curr_symbol, "EUR" ) == 0 );
TESTCASE( lc->frac_digits == 2 );
TESTCASE( lc->p_cs_precedes == 0 );
TESTCASE( lc->n_cs_precedes == 0 );
TESTCASE( lc->p_sep_by_space == 1 );
TESTCASE( lc->n_sep_by_space == 1 );
TESTCASE( lc->p_sign_posn == 1 );
TESTCASE( lc->n_sign_posn == 1 );
TESTCASE( lc->int_frac_digits == 2 );
TESTCASE( lc->int_p_cs_precedes == 0 );
TESTCASE( lc->int_n_cs_precedes == 0 );
TESTCASE( lc->int_p_sep_by_space == 1 );
TESTCASE( lc->int_n_sep_by_space == 1 );
TESTCASE( lc->int_p_sign_posn == 1 );
TESTCASE( lc->int_n_sign_posn == 1 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,84 @@
/* _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.
*/
#ifndef REGTEST
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_lconv_numeric_t *)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;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
FILE * fh = fopen( "test_numeric.dat", "wb" );
struct _PDCLIB_lc_lconv_numeric_t * lc;
TESTCASE( fh != NULL );
TESTCASE( fputs( ",\n.\n\n", fh ) != EOF );
fclose( fh );
TESTCASE( ( lc = _PDCLIB_load_lc_numeric( "./", "test" ) ) );
remove( "test_numeric.dat" );
TESTCASE( strcmp( lc->decimal_point, "," ) == 0 );
TESTCASE( strcmp( lc->thousands_sep, "." ) == 0 );
TESTCASE( strcmp( lc->grouping, "" ) == 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,165 @@
/* _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.
*/
#ifndef REGTEST
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pdclib/_PDCLIB_internal.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 = (char *)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 = (struct _PDCLIB_lc_time_t *)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;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
FILE * fh = fopen( "test_time.dat", "wb" );
struct _PDCLIB_lc_time_t * lc;
TESTCASE( fh != NULL );
/* month name abbreviation */
TESTCASE( fprintf( fh, "%s\n", "Jan" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Feb" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "M\xe4r" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Apr" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Mai" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Jun" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Jul" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Aug" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Sep" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Okt" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Nov" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Dez" ) == 4 );
/* month name full */
TESTCASE( fprintf( fh, "%s\n", "Januar" ) == 7 );
TESTCASE( fprintf( fh, "%s\n", "Februar" ) == 8 );
TESTCASE( fprintf( fh, "%s\n", "M\xe4rz" ) == 5 );
TESTCASE( fprintf( fh, "%s\n", "April" ) == 6 );
TESTCASE( fprintf( fh, "%s\n", "Mai" ) == 4 );
TESTCASE( fprintf( fh, "%s\n", "Juni" ) == 5 );
TESTCASE( fprintf( fh, "%s\n", "Juli" ) == 5 );
TESTCASE( fprintf( fh, "%s\n", "August" ) == 7 );
TESTCASE( fprintf( fh, "%s\n", "September" ) == 10 );
TESTCASE( fprintf( fh, "%s\n", "Oktober" ) == 8 );
TESTCASE( fprintf( fh, "%s\n", "November" ) == 9 );
TESTCASE( fprintf( fh, "%s\n", "Dezember" ) == 9 );
/* day name abbreviation */
TESTCASE( fprintf( fh, "%s\n", "So" ) == 3 );
TESTCASE( fprintf( fh, "%s\n", "Mo" ) == 3 );
TESTCASE( fprintf( fh, "%s\n", "Di" ) == 3 );
TESTCASE( fprintf( fh, "%s\n", "Mi" ) == 3 );
TESTCASE( fprintf( fh, "%s\n", "Do" ) == 3 );
TESTCASE( fprintf( fh, "%s\n", "Fr" ) == 3 );
TESTCASE( fprintf( fh, "%s\n", "Sa" ) == 3 );
/* day name full */
TESTCASE( fprintf( fh, "%s\n", "Sonntag" ) == 8 );
TESTCASE( fprintf( fh, "%s\n", "Montag" ) == 7 );
TESTCASE( fprintf( fh, "%s\n", "Dienstag" ) == 9 );
TESTCASE( fprintf( fh, "%s\n", "Mittwoch" ) == 9 );
TESTCASE( fprintf( fh, "%s\n", "Donnerstag" ) == 11 );
TESTCASE( fprintf( fh, "%s\n", "Freitag" ) == 8 );
TESTCASE( fprintf( fh, "%s\n", "Samstag" ) == 8 );
TESTCASE( fprintf( fh, "%s\n", "%a %d %b %Y %T %Z" ) == 18 ); /* date time format (%c) */
TESTCASE( fprintf( fh, "%s\n", "%I:%M:%S" ) == 9 ); /* 12-hour time format (%r) */
TESTCASE( fprintf( fh, "%s\n", "%d.%m.%Y" ) == 9 ); /* date format (%x) */
TESTCASE( fprintf( fh, "%s\n", "%H:%M:%S" ) == 9 ); /* time format (%X) */
TESTCASE( fprintf( fh, "%s\n", "" ) == 1 ); /* AM */
TESTCASE( fprintf( fh, "%s\n", "" ) == 1 ); /* PM */
fclose( fh );
TESTCASE( ( lc = _PDCLIB_load_lc_time( "./", "test" ) ) );
remove( "test_time.dat" );
TESTCASE( strcmp( lc->month_name_abbr[ 0 ], "Jan" ) == 0 );
TESTCASE( strcmp( lc->month_name_abbr[ 11 ], "Dez" ) == 0 );
TESTCASE( strcmp( lc->month_name_full[ 0 ], "Januar" ) == 0 );
TESTCASE( strcmp( lc->month_name_full[ 11 ], "Dezember" ) == 0 );
TESTCASE( strcmp( lc->day_name_abbr[ 0 ], "So" ) == 0 );
TESTCASE( strcmp( lc->day_name_abbr[ 6 ], "Sa" ) == 0 );
TESTCASE( strcmp( lc->day_name_full[ 0 ], "Sonntag" ) == 0 );
TESTCASE( strcmp( lc->day_name_full[ 6 ], "Samstag" ) == 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,81 @@
/* _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>
#ifndef REGTEST
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 = (char *)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;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
FILE * fh = fopen( "test_lines.txt", "w+" );
char * rc;
TESTCASE( fh != NULL );
TESTCASE( fputs( "Foo\n\nBar\n", fh ) != EOF );
rewind( fh );
rc = _PDCLIB_load_lines( fh, 3 );
fclose( fh );
remove( "test_lines.txt" );
TESTCASE( rc != NULL );
TESTCASE( strcmp( rc, "Foo" ) == 0 );
TESTCASE( strcmp( rc + 4, "" ) == 0 );
TESTCASE( strcmp( rc + 5, "Bar" ) == 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,96 @@
/* _PDCLIB_naive_ptod( const char *, char ** endptr )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_internal.h"
#include <ctype.h>
#include <string.h>
long double _PDCLIB_naive_etod( const char * s, char ** endptr )
{
/* This is nowhere good enough, just a quick approximation */
long double rc = 0.0;
while ( isdigit( (unsigned char)*s ) )
{
rc = rc * 10 + ( *s++ - '0' );
}
if ( *s == '.' )
{
long double fraction = 0.0;
long double scale = 1.0;
++s;
while ( isdigit( (unsigned char)*s ) )
{
fraction = fraction * 10 + ( *s++ - '0' );
scale *= 10;
}
rc += ( fraction / scale );
}
if ( tolower( (unsigned char)*s ) == 'e' )
{
char sign = '+';
long double exp = 0.0;
long double scale = 1.0;
++s;
if ( *s == '-' )
{
sign = *s++;
}
else if ( *s == '+' )
{
++s;
}
while ( isdigit( (unsigned char)*s ) )
{
exp = ( exp * 10 ) + ( *s++ - '0' );
}
while ( exp > 0 )
{
scale *= 10;
--exp;
}
if ( sign == '+' )
{
rc *= scale;
}
else
{
rc /= scale;
}
}
if ( endptr != NULL )
{
*endptr = (char *)s;
}
return rc;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Tested by strtof / strtol / strtold */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,97 @@
/* _PDCLIB_naive_ptod( const char *, char ** endptr )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_internal.h"
#include <ctype.h>
#include <string.h>
long double _PDCLIB_naive_ptod( const char * s, char ** endptr )
{
/* This is nowhere good enough, just a quick approximation */
long double rc = 0.0;
const char * x;
while ( ( x = (const char *)memchr( _PDCLIB_digits, tolower( (unsigned char)*s ), 16 ) ) != NULL )
{
rc = rc * 16 + ( x - _PDCLIB_digits );
}
if ( *s == '.' )
{
long double fraction = 0.0;
long double scale = 1.0;
++s;
while ( ( x = (const char *)memchr( _PDCLIB_digits, tolower( (unsigned char)*s ), 16 ) ) != NULL )
{
fraction = fraction * 16 + ( x - _PDCLIB_digits );
scale *= 16;
}
rc += ( fraction / scale );
}
if ( tolower( (unsigned char)*s ) == 'p' )
{
char sign = '+';
long double exp = 0.0;
long double scale = 1.0;
++s;
if ( *s == '-' )
{
sign = *s++;
}
else if ( *s == '+' )
{
++s;
}
while ( isdigit( (unsigned char)*s ) )
{
exp = ( exp * 10 ) + ( *s++ - '0' );
}
while ( exp > 0 )
{
scale *= 2;
--exp;
}
if ( sign == '+' )
{
rc *= scale;
}
else
{
rc /= scale;
}
}
if ( endptr != NULL )
{
*endptr = (char *)s;
}
return rc;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Tested by strtof / strtol / strtold */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,42 @@
/* _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>
#ifndef REGTEST
#include "pdclib/_PDCLIB_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. */
*_PDCLIB_errno_func() = _PDCLIB_EBADF;
stream->status |= _PDCLIB_ERRORFLAG;
return EOF;
}
stream->status |= _PDCLIB_FREAD | _PDCLIB_BYTESTREAM;
return 0;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Testing covered by ftell.c */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,39 @@
/* _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>
#ifndef REGTEST
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. */
*_PDCLIB_errno_func() = _PDCLIB_EBADF;
stream->status |= _PDCLIB_ERRORFLAG;
return EOF;
}
stream->status |= _PDCLIB_FWRITE | _PDCLIB_BYTESTREAM;
return 0;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Testing covered by ftell.c */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,493 @@
/* _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 <inttypes.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stddef.h>
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
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,
forced decimal point for floats, trailing zeroes not
removed for %g/%G
*/
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;
}
}
/* 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':
status->base = 2;
status->flags |= ( E_decimal | E_double | E_lower );
break;
case 'F':
status->base = 2;
status->flags |= ( E_decimal | E_double );
break;
case 'e':
status->base = 2;
status->flags |= ( E_exponent | E_double | E_lower );
break;
case 'E':
status->base = 2;
status->flags |= ( E_exponent | E_double );
break;
case 'g':
status->base = 2;
status->flags |= ( E_generic | E_double | E_lower );
break;
case 'G':
status->base = 2;
status->flags |= ( E_generic | E_double );
break;
case 'a':
status->base = 2;
status->flags |= ( E_hexa | E_double | E_lower );
break;
case 'A':
status->base = 2;
status->flags |= ( E_hexa | E_double );
break;
case 'c':
/* TODO: wide chars. */
{
char c[1];
c[0] = ( char )va_arg( status->arg, int );
status->flags |= E_char;
_PDCLIB_print_string( c, status );
return ++spec;
}
case 's':
/* TODO: wide chars. */
_PDCLIB_print_string( 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 )
{
/* TODO: Check for invalid flag combinations. */
if ( status->flags & E_double )
{
/* Floating Point conversions */
if ( status->flags & E_ldouble )
{
long double value = va_arg( status->arg, long double );
_PDCLIB_fp_t fp;
_PDCLIB_fp_from_ldbl( &fp, value );
_PDCLIB_print_fp( &fp, status );
}
else
{
double value = va_arg( status->arg, double );
_PDCLIB_fp_t fp;
_PDCLIB_fp_from_dbl( &fp, value );
_PDCLIB_print_fp( &fp, status );
}
}
else
{
/* Having a precision cancels out any zero flag. */
if ( status->prec != EOF )
{
status->flags &= ~E_zero;
}
if ( status->flags & E_unsigned )
{
/* Integer conversions (unsigned) */
uintmax_t value;
imaxdiv_t div;
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;
}
div.quot = value / status->base;
div.rem = value % status->base;
_PDCLIB_print_integer( div, status );
}
else
{
/* Integer conversions (signed) */
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;
}
_PDCLIB_print_integer( imaxdiv( value, status->base ), status );
}
}
if ( status->flags & E_minus )
{
/* Left-aligned filling */
while ( status->current < status->width )
{
PUT( ' ' );
++( status->current );
}
}
if ( status->i >= status->n && status->n > 0 )
{
status->s[status->n - 1] = '\0';
}
}
return ++spec;
}
#endif
#ifdef TEST
#define _PDCLIB_FILEID "_PDCLIB/print.c"
#define _PDCLIB_STRINGIO
#include "_PDCLIB_test.h"
#ifndef REGTEST
static int testprintf( char * buffer, const char * format, ... )
{
/* Members: base, flags, n, i, current, s, width, prec, stream, arg */
struct _PDCLIB_status_t status;
status.base = 0;
status.flags = 0;
status.n = 100;
status.i = 0;
status.current = 0;
status.s = buffer;
status.width = 0;
status.prec = EOF;
status.stream = NULL;
va_start( status.arg, format );
memset( buffer, '\0', 100 );
if ( *( _PDCLIB_print( format, &status ) ) != '\0' )
{
printf( "_PDCLIB_print() did not return end-of-specifier on '%s'.\n", format );
++TEST_RESULTS;
}
va_end( status.arg );
return status.i;
}
#endif
#define TEST_CONVERSION_ONLY
#include <float.h>
int main( void )
{
#ifndef REGTEST
char target[100];
#include "printf_testcases.h"
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,390 @@
/* _PDCLIB_print_fp( _PDCLIB_fp_t *, 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.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <string.h>
#include <stdlib.h>
#define MIN( x, y ) ( ( x < y ) ? x : y )
static char * exp_to_buffer( int exponent, char * buffer )
{
div_t dv = div( exponent, 10 );
if ( dv.quot > 0 )
{
buffer = exp_to_buffer( dv.quot, buffer );
}
*buffer++ = _PDCLIB_digits[ dv.rem ];
return buffer;
}
static void _PDCLIB_format_e( struct _PDCLIB_status_t * status, char * buffer, int exp10, char sign )
{
size_t len = strlen( buffer );
int exponent = ( len + exp10 ) - 1;
int i;
char exp_buffer[8];
char * current;
/* Print exponent to exp_buffer */
current = exp_buffer;
*current++ = ( status->flags & E_lower ) ? 'e' : 'E';
if ( exponent < 0 )
{
*current++ = '-';
exponent *= -1;
}
else
{
*current++ = '+';
}
if ( exponent > -10 && exponent < 10 )
{
*current++ = '0';
}
current = exp_to_buffer( exponent, current );
*current = '\0';
/* Left padding, if applicable */
if ( ! ( status->flags & E_minus ) )
{
i = ( sign != '\0' )
+ 1
+ ( status->prec > 0 || status->flags & E_alt )
+ ( ( status->prec > 0 ) ? status->prec : 0 )
+ ( current - exp_buffer );
if ( ( sign != '\0' ) && ( status->flags & E_zero ) )
{
PUT( sign );
status->current++;
}
for ( ; (size_t)i < status->width; ++i )
{
PUT( ( status->flags & E_zero ) ? '0' : ' ' );
status->current++;
}
if ( ( sign != '\0' ) && ! ( status->flags & E_zero ) )
{
PUT( sign );
status->current++;
}
}
else if ( sign != '\0' )
{
PUT( sign );
status->current++;
}
/* Print buffer */
current = buffer;
PUT( _PDCLIB_digits[ (size_t)*current++ ] );
status->current++;
if ( status->prec > 0 || status->flags & E_alt )
{
PUT( '.' );
status->current++;
}
for ( i = 0; i < status->prec; ++i )
{
if ( *current != '\0' )
{
PUT( _PDCLIB_digits[ (size_t)*current++ ] );
status->current++;
}
else if ( ! ( status->flags & E_generic ) )
{
PUT( '0' );
status->current++;
}
}
/* Print exponent */
for ( current = exp_buffer; *current != '\0'; ++current )
{
PUT( *current );
status->current++;
}
}
static void _PDCLIB_format_f( struct _PDCLIB_status_t * status, char * buffer, int exp10, char sign )
{
size_t len = strlen( buffer );
/* Left padding, if applicable */
if ( ! ( status->flags & E_minus ) )
{
size_t i = ( sign != '\0' )
+ ( ( (int)len + exp10 > 0 ) ? ( len + exp10 ) : 1 )
+ ( status->prec > 0 || status->flags & E_alt )
+ ( ( status->prec > 0 ) ? status->prec : 0 );
if ( ( sign != '\0' ) && ( status->flags & E_zero ) )
{
PUT( sign );
status->current++;
}
for ( ; i < status->width; ++i )
{
PUT( ( status->flags & E_zero ) ? '0' : ' ' );
status->current++;
}
if ( ( sign != '\0' ) && ! ( status->flags & E_zero ) )
{
PUT( sign );
status->current++;
}
}
else if ( sign != '\0' )
{
PUT( sign );
status->current++;
}
if ( exp10 >= 0 )
{
/* Print buffer, period, zeroes to precision */
/* len + exp10 + [period + [prec]] */
int i;
for ( i = 0; (size_t)i < len; ++i )
{
PUT( _PDCLIB_digits[ (size_t)buffer[i] ] );
status->current++;
}
for ( i = 0; i < exp10; ++i )
{
PUT( _PDCLIB_digits[0] );
status->current++;
}
if ( ( ( ! ( status->flags & E_generic ) ) && status->prec > 0 ) || status->flags & E_alt )
{
PUT( '.' );
status->current++;
}
len = status->prec;
}
else
{
int n = len + exp10;
int i;
if ( n > 0 )
{
/* Print n from buffer, period, rest from buffer, zeroes to precision */
for ( i = 0; i < n; ++i )
{
PUT( _PDCLIB_digits[ (size_t)buffer[i] ] );
status->current++;
}
if ( status->prec > 0 || status->flags & E_alt )
{
PUT( '.' );
status->current++;
}
for ( i = 0; buffer[ i + n ] != '\0'; ++i )
{
PUT( _PDCLIB_digits[ (size_t)buffer[ i + n ] ] );
status->current++;
}
len = status->prec - i;
}
else
{
/* Print zero, period, -n zeroes, buffer, zeroes to precision */
PUT( _PDCLIB_digits[0] );
status->current++;
if ( status->prec > 0 || status->flags & E_alt )
{
PUT( '.' );
status->current++;
}
for ( i = 0; i < -n; ++i )
{
PUT( _PDCLIB_digits[0] );
status->current++;
}
for ( i = 0; buffer[i] != '\0'; ++i )
{
PUT( _PDCLIB_digits[ (size_t)buffer[i] ] );
status->current++;
}
n = -n + i;
len = status->prec - n;
}
}
if ( ! ( status->flags & E_generic ) )
{
for ( ; len > 0; --len )
{
PUT( _PDCLIB_digits[0] );
status->current++;
}
}
}
static void _PDCLIB_format_infnan( struct _PDCLIB_status_t * status, int state, char sign )
{
size_t i;
char const * s = ( state == _PDCLIB_FP_INF )
? ( ( status->flags & E_lower ) ? "inf" : "INF" )
: ( ( status->flags & E_lower ) ? "nan" : "NAN" );
/* Left padding, if applicable */
if ( ! ( status->flags & E_minus ) )
{
i = ( sign != '\0' ) ? 4 : 3;
for ( i = ( sign != '\0' ) ? 4 : 3; i < status->width; ++i )
{
PUT( ' ' );
status->current++;
}
}
if ( sign != '\0' )
{
PUT( sign );
status->current++;
}
for ( i = 0; i < 3; ++i )
{
PUT( s[i] );
}
status->current += 3;
}
void _PDCLIB_print_fp( _PDCLIB_fp_t * fp,
struct _PDCLIB_status_t * status )
{
char buffer[ _PDCLIB_LDBL_MANT_DIG + 10 ];
/* Turning sign bit into sign character. */
if ( fp->sign == 1 )
{
fp->sign = '-';
}
else if ( status->flags & E_plus )
{
fp->sign = '+';
}
else if ( status->flags & E_space )
{
fp->sign = ' ';
}
else
{
fp->sign = '\0';
}
if ( fp->state == _PDCLIB_FP_INF || fp->state == _PDCLIB_FP_NAN )
{
_PDCLIB_format_infnan( status, fp->state, fp->sign );
return;
}
if ( status->flags & E_hexa )
{
_PDCLIB_print_fp_hexa( fp, status, buffer );
return;
}
else
{
int exp10;
if ( status->prec < 0 )
{
status->prec = 6;
}
switch ( status->flags & ( E_decimal | E_exponent | E_generic ) )
{
case E_decimal:
{
exp10 = _PDCLIB_print_fp_deci( fp, status, buffer );
_PDCLIB_format_f( status, buffer, exp10, fp->sign );
break;
}
case E_exponent:
{
exp10 = _PDCLIB_print_fp_deci( fp, status, buffer );
_PDCLIB_format_e( status, buffer, exp10, fp->sign );
break;
}
case E_generic:
{
_PDCLIB_bigint_t mant;
int exponent;
_PDCLIB_bigint_from_bigint( &mant, &fp->mantissa );
if ( status->prec == 0 )
{
status->prec = 1;
}
exp10 = _PDCLIB_print_fp_deci( fp, status, buffer );
exponent = ( strlen( buffer ) + exp10 ) - 1;
if ( exponent >= -4 && exponent < status->prec )
{
_PDCLIB_bigint_from_bigint( &fp->mantissa, &mant );
status->flags &= ~E_generic;
status->flags |= E_decimal;
status->prec -= exponent + 1;
exp10 = _PDCLIB_print_fp_deci( fp, status, buffer );
status->flags |= E_generic;
_PDCLIB_format_f( status, buffer, exp10, fp->sign );
}
else
{
status->prec -= 1;
_PDCLIB_format_e( status, buffer, exp10, fp->sign );
}
break;
}
}
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( int argc, char * argv[] )
{
/* Tested by _PDCLIB_print testdriver */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,211 @@
/* _PDCLIB_print_fp_deci( _PDCLIB_fp_t *, struct _PDCLIB_status_t *, char )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <float.h>
static int prep( _PDCLIB_bigint_t * mantissa, int exponent )
{
/* log10(2) to 128bit precision */
const long double log_10_2 = 0.30102999566398119521373889472449302l;
/* Get an approximation of the base 10 exponent we are looking at
and make it fall one short in most cases as correction is easier
that way.
*/
double guess = (double)( _PDCLIB_bigint_log2( mantissa ) + exponent ) * log_10_2 - 0.69;
int exp10 = ( (int)guess < guess ) ? (int)guess + 1 : (int)guess;
return exp10;
}
int _PDCLIB_print_fp_deci( _PDCLIB_fp_t * fp,
struct _PDCLIB_status_t * status,
char * buffer )
{
char * current = buffer;
_PDCLIB_bigint_t divisor;
_PDCLIB_bigint_digit_t msd;
int digit;
int cutoff;
/* No decimal point in the mantissa, so we adjust the exponent. */
int exponent = fp->exponent - fp->scale;
int exp10 = prep( &fp->mantissa, exponent );
if ( ( status->flags & E_decimal ) && ( status->prec >= 0 ) && ( exp10 <= -status->prec ) )
{
exp10 = -status->prec + 1;
}
/* Set up the fraction. */
if ( exponent > 0 )
{
_PDCLIB_bigint_shl( &fp->mantissa, exponent );
_PDCLIB_bigint_from_digit( &divisor, 1 );
}
else
{
_PDCLIB_bigint_from_pow2( &divisor, -exponent );
}
/* Using the approx. exp10, scale the fraction close to where
we could start dividing.
*/
if ( exp10 > 0 )
{
_PDCLIB_bigint_mul_pow10( &divisor, exp10 );
}
else if ( exp10 < 0 )
{
_PDCLIB_bigint_mul_pow10( &fp->mantissa, -exp10 );
}
/* Now we know if our approximation was good or needs correction.
This is why we substracted as much as we could in prep(), as
correctiong for one short is the cheaper operation.
*/
if ( _PDCLIB_bigint_cmp( &fp->mantissa, &divisor ) >= 0 )
{
++exp10;
}
else
{
_PDCLIB_bigint_mul10( &fp->mantissa );
}
/* We make sure the fraction is scaled properly.
The previous operations already ensured that
the mantissa is no more than divisor * 10.
Now we make sure that the divisor has enough
bits in the most significant digit to give a
proper result, and that both mantissa and the
divisor are scaled to the same bigint length.
*/
msd = divisor.data[ divisor.size - 1 ];
if ( ( msd < 8 ) || ( msd > ( _PDCLIB_BIGINT_DIGIT_MAX / 10 ) ) )
{
int shift = ( ( _PDCLIB_BIGINT_DIGIT_BITS * 2 - 5 ) - _PDCLIB_bigint_digit_log2( msd ) ) % 32;
_PDCLIB_bigint_shl( &fp->mantissa, shift );
_PDCLIB_bigint_shl( &divisor, shift );
}
/* Main loop - divide, generate digits, multiply with 10, repeat */
switch ( status->flags & ( E_decimal | E_exponent | E_generic ) )
{
case E_decimal:
cutoff = -status->prec;
break;
case E_exponent:
case E_generic:
cutoff = exp10 - status->prec - 1;
break;
}
for (;;)
{
digit = _PDCLIB_bigint_div( &fp->mantissa, &divisor );
--exp10;
if ( fp->mantissa.size == 0 || exp10 == cutoff )
{
break;
}
*current++ = _PDCLIB_digits[ digit ];
_PDCLIB_bigint_mul10( &fp->mantissa );
}
/* rounding */
{
int roundup = 0;
switch ( FLT_ROUNDS )
{
case 3: /*FE_DOWNWARD*/
roundup = ( fp->sign == '-' );
break;
case 2: /*FE_UPWARD*/
roundup = ( fp->sign != '-' );
break;
case 0: /*FE_TOWARDZERO*/
roundup = 0;
break;
default:
case 1: /*FE_TONEAREST*/
{
int compare;
_PDCLIB_bigint_shl( &fp->mantissa, 1 );
compare = _PDCLIB_bigint_cmp( &fp->mantissa, &divisor );
if ( ( compare > 0 ) /* Over 0.5 */
|| ( ( compare == 0 ) && ( digit & 1 ) ) ) /* Break tie to even */
{
roundup = 1;
}
}
if ( roundup )
{
if ( digit < 9 )
{
*current++ = _PDCLIB_digits[ ++digit ];
}
else
{
for (;;)
{
++exp10;
if ( current == buffer )
{
*current++ = _PDCLIB_digits[1];
++exp10;
break;
}
if ( *--current != _PDCLIB_digits[9] )
{
++*current++;
break;
}
}
}
}
else
{
*current++ = _PDCLIB_digits[ digit ];
}
}
while ( *(current - 1) == '0' )
{
--current;
++exp10;
}
}
*current = '\0';
return exp10;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( int argc, char * argv[] )
{
/* Tested by _PDCLIB_print testdriver */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,268 @@
/* _PDCLIB_print_fp_hexa( _PDCLIB_bigint_t *, struct _PDCLIB_status_t *, char )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_print.h"
#include <float.h>
#include <stdbool.h>
#include <stdlib.h>
static inline void round_up( char * buffer, size_t index )
{
if ( buffer[ index ] < '\017' )
{
++buffer[ index ];
}
else
{
buffer[ index ] = '\0';
round_up( buffer, index - 1 );
}
}
static inline void round( char * buffer, size_t last_non_zero, size_t prec, char sign )
{
switch ( FLT_ROUNDS )
{
case 0: /*FE_TOWARDZERO*/
break;
default: /*FE_TONEAREST*/
case 1:
if ( buffer[ prec + 1 ] > '\005' )
{
round_up( buffer, prec );
}
else if ( buffer[ prec + 1 ] == '\005' )
{
if ( last_non_zero > ( prec + 1 ) || ( buffer[ prec ] % 2 ) )
{
round_up( buffer, prec );
}
}
break;
case 2: /*FE_UPWARD*/
if ( sign != '-' )
{
round_up( buffer, prec );
}
break;
case 3: /*FE_DOWNWARD*/
if ( sign == '-' )
{
round_up( buffer, prec );
}
break;
}
}
static char * print_exp( char * buffer, int exp )
{
div_t dv = div( exp, 10 );
if ( dv.quot > 0 )
{
buffer = print_exp( buffer, dv.quot );
}
*buffer = _PDCLIB_digits[ dv.rem ];
return ++buffer;
}
static size_t print_mant( _PDCLIB_fp_t * fp, struct _PDCLIB_status_t * status, char * buffer )
{
size_t i;
int last_non_zero;
size_t mant_dig = ( ( status->flags & E_ldouble ) ? _PDCLIB_LDBL_MANT_DIG : _PDCLIB_DBL_MANT_DIG ) - 1;
size_t log2 = _PDCLIB_bigint_log2( &fp->mantissa );
char * bufend = buffer;
if ( ( mant_dig % 4 ) > 0 )
{
/* alignment */
int shift = 4 - ( mant_dig % 4 );
_PDCLIB_bigint_shl( &fp->mantissa, shift );
mant_dig += shift;
log2 += shift;
}
if ( mant_dig > log2 )
{
/* subnormal, leading zeroes */
for ( i = 0; i <= ( mant_dig - log2 - 1 ) / 4; ++i )
{
*bufend++ = '\0';
}
}
for ( i = log2 / 4 + 1; i > 0; --i, ++bufend )
{
/* data nibbles */
div_t dv = div( i - 1, _PDCLIB_BIGINT_DIGIT_BITS / 4 );
if ( ( *bufend = ( fp->mantissa.data[ dv.quot ] >> ( dv.rem * 4 ) ) & 0xfu ) > 0 )
{
last_non_zero = bufend - buffer;
}
}
if ( status->prec >= 0 )
{
/* check rounding */
if ( last_non_zero > ( status->prec + 1 ) )
{
round( buffer, last_non_zero, status->prec, fp->sign );
}
return status->prec + 1;
}
else
{
/* no precision given */
return last_non_zero + 1;
}
}
void _PDCLIB_print_fp_hexa( _PDCLIB_fp_t * fp,
struct _PDCLIB_status_t * status,
char * buffer )
{
_PDCLIB_static_assert( _PDCLIB_FLT_RADIX == 2, "Assuming 2-based Floating Point" );
char const * digits = ( status->flags & E_lower ) ? _PDCLIB_digits : _PDCLIB_Xdigits;
int exp = (_PDCLIB_bigint_sdigit_t)fp->exponent;
/* sign + "0x" + dec + "." + ( LDBL_MANT_DIG / 4 )
+ 'p' + sign + exp[5] + '\0' <= 41
...but how could I do THAT? :-)
*/
char * current = buffer;
size_t count;
size_t i;
/* significant */
if ( fp->mantissa.size == 0 )
{
*current++ = '0';
exp = 0;
}
else
{
count = print_mant( fp, status, current );
*current = digits[ (size_t)*current ];
++current;
if ( ( count > 1 && status->prec != 0 ) || status->flags & E_alt )
{
for ( i = count; i > 1; --i )
{
current[ i ] = current[ i - 1 ];
}
*current++ = '.'; /* TODO: decimal point */
}
for ( i = 1; i < count; ++i )
{
*current = digits[ (size_t)*current ];
++current;
}
}
/* exponent */
*current++ = ( status->flags & E_lower ) ? 'p' : 'P';
if ( exp < 0 )
{
*current++ = '-';
exp *= -1;
}
else
{
*current++ = '+';
}
current = print_exp( current, exp );
*current = '\0';
/* output */
count = ( current - buffer ) + ( ( fp->sign == '\0' ) ? 2 : 3 );
count = ( status->width > count ) ? ( status->width - count ) : 0;
if ( ( count > 0 ) && ! ( status->flags & E_minus ) && ! ( status->flags & E_zero ) )
{
for ( i = 0; i < count; ++i )
{
PUT( ' ' );
status->current++;
}
}
if ( fp->sign != '\0' )
{
PUT( fp->sign );
status->current++;
}
PUT( '0' );
PUT( ( status->flags & E_lower ) ? 'x' : 'X' );
status->current += 2;
if ( ( count > 0 ) && ! ( status->flags & E_minus ) && ( status->flags & E_zero ) )
{
for ( i = 0; i < count; ++i )
{
PUT( '0' );
status->current++;
}
}
current = buffer;
while ( *current != '\0' )
{
PUT( *current++ );
status->current++;
}
if ( ( count > 0 ) && ( status->flags & E_minus ) )
{
for ( i = 0; i < count; ++i )
{
PUT( ' ' );
status->current++;
}
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( int argc, char * argv[] )
{
/* Tested by _PDCLIB_print testdriver */
#ifndef REGTEST
char buffer[100];
*(print_exp( buffer, 0 )) = '\0';
TESTCASE( strcmp( buffer, "0" ) == 0 );
*(print_exp( buffer, 9 )) = '\0';
TESTCASE( strcmp( buffer, "9" ) == 0 );
*(print_exp( buffer, 10 )) = '\0';
TESTCASE( strcmp( buffer, "10" ) == 0 );
*(print_exp( buffer, 100 )) = '\0';
TESTCASE( strcmp( buffer, "100" ) == 0 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,175 @@
/* _PDCLIB_print_integer
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include <inttypes.h>
#include <stdio.h>
#include "pdclib/_PDCLIB_print.h"
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 signed 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 = ( ( _PDCLIB_size_t )status->prec > status->current ) ? ( ( _PDCLIB_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 > ( _PDCLIB_size_t )status->prec ) ? status->current : ( _PDCLIB_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 );
}
}
}
}
/* 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.
*/
void _PDCLIB_print_integer( imaxdiv_t div, struct _PDCLIB_status_t * status )
{
if ( status->current == 0 && div.quot == 0 && div.rem == 0 && status->prec == 0 )
{
intformat( 0, status );
}
else
{
++(status->current);
if ( div.quot != 0 )
{
_PDCLIB_print_integer( imaxdiv( div.quot, status->base ), status );
}
else
{
intformat( div.rem, status );
}
if ( div.rem < 0 )
{
div.rem *= -1;
}
if ( status->flags & E_lower )
{
PUT( _PDCLIB_digits[ div.rem ] );
}
else
{
PUT( _PDCLIB_Xdigits[ div.rem ] );
}
}
}
#endif
#ifdef TEST
#include <stddef.h>
#include "_PDCLIB_test.h"
int main( void )
{
/* Tested by the various *printf() drivers. */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,85 @@
/* _PDCLIB_print_string
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "pdclib/_PDCLIB_print.h"
/* Print a "string" (%c, %s) under control of a given status struct. See
INT2BASE().
*/
void _PDCLIB_print_string( 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 > ( _PDCLIB_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 );
}
}
}
#endif
#ifdef TEST
#include <stddef.h>
#include "_PDCLIB_test.h"
int main( void )
{
/* Tested by _PDCLIB_print testdriver */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,61 @@
/* _PDCLIB_realpath( const char * path )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
extern char * realpath( const char * file_name, char * resolved_name );
#ifdef __cplusplus
}
#endif
char * _PDCLIB_realpath( const char * path )
{
/* TODO: PATH_MAX but that seems difficult to come by */
char buffer[ 4096 ];
char * resolved_name;
if ( realpath( path, buffer ) == NULL )
{
return NULL;
}
/* Need to do our own alloc-and-copy here, as realpath()
would be linked to the system malloc(), and if our
fclose() would run our free() on someone else's memory,
results are more interesting than we would like to see.
*/
if ( ( resolved_name = malloc( strlen( buffer + 1 ) ) ) == NULL )
{
return NULL;
}
return strcpy( resolved_name, buffer );
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* No test drivers. */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,42 @@
/* _PDCLIB_remove( 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_remove() fit for use with
POSIX kernels.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#ifdef __cplusplus
extern "C" {
#endif
extern int unlink( const char * );
#ifdef __cplusplus
}
#endif
int _PDCLIB_remove( const char * pathname )
{
return unlink( pathname );
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Testing covered by ftell.c (and several others) */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,117 @@
/* _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>
#ifndef REGTEST
/* Having to jump through some hoops here so including fcntl.h does
work. Linux struggles with redefinitions of SEEK_SET et al. if
we set _GNU_SOURCE, but Cygwin needs that to actually get to the
AT_FDCWD definition.
*/
#ifdef __linux__
#define _ATFILE_SOURCE 1
#else
#define _GNU_SOURCE 1
#endif
#include "pdclib/_PDCLIB_glue.h"
#include "pdclib/_PDCLIB_defguard.h"
#include "pdclib/_PDCLIB_platform_errno.h"
/* The system calls provided for renaming are rename(), renameat()
and renameat2(). Using rename() is not possible, since we have
that symbol in our library and would end up with a recursive
call. But we *can* use renameat() with default parameters!
AT_FDCWD is declared in fcntl.h. We need to manually declare
renameat() here as it is declared in system's <stdio.h>.
*/
#include "pdclib/_PDCLIB_platform_fcntl.h"
#ifdef __cplusplus
extern "C" {
#endif
int renameat( int, const char *, int, const char * );
#ifdef __cplusplus
}
#endif
int _PDCLIB_rename( const char * oldpath, const char * newpath )
{
/* Whether existing newpath is overwritten is implementation-
defined. This system call *does* overwrite.
*/
if ( renameat( AT_FDCWD, oldpath, AT_FDCWD, newpath ) != 0 )
{
/* The 1:1 mapping in _PDCLIB_config.h ensures this works. */
*_PDCLIB_errno_func() = errno;
return -1;
}
else
{
return 0;
}
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <stdlib.h>
int main( void )
{
#ifndef REGTEST
FILE * file;
remove( testfile1 );
remove( testfile2 );
/* check that neither file exists */
TESTCASE( fopen( testfile1, "r" ) == NULL );
TESTCASE( fopen( testfile2, "r" ) == NULL );
/* rename file 1 to file 2 - expected to fail */
TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == -1 );
/* create file 1 */
TESTCASE( ( file = fopen( testfile1, "w" ) ) != NULL );
TESTCASE( fputc( 'x', file ) == 'x' );
TESTCASE( fclose( file ) == 0 );
/* check that file 1 exists */
TESTCASE( ( file = fopen( testfile1, "r" ) ) != NULL );
TESTCASE( fclose( file ) == 0 );
/* rename file 1 to file 2 */
TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == 0 );
/* check that file 2 exists, file 1 does not */
TESTCASE( fopen( testfile1, "r" ) == NULL );
TESTCASE( ( file = fopen( testfile2, "r" ) ) != NULL );
TESTCASE( fclose( file ) == 0 );
/* create another file 1 */
TESTCASE( ( file = fopen( testfile1, "w" ) ) != NULL );
TESTCASE( fputc( 'x', file ) == 'x' );
TESTCASE( fclose( file ) == 0 );
/* check that file 1 exists */
TESTCASE( ( file = fopen( testfile1, "r" ) ) != NULL );
TESTCASE( fclose( file ) == 0 );
/* Whether existing destination files are overwritten or not
is implementation-defined.
This implementation *does* overwrite.
*/
TESTCASE( _PDCLIB_rename( testfile1, testfile2 ) == 0 );
/* remove both files */
remove( testfile1 );
remove( testfile2 );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,781 @@
/* _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>
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.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 )
{
if ( _PDCLIB_CHECKBUFFER( status->stream ) != EOF )
{
rc = _PDCLIB_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 = NULL;
if ( !( status->flags & E_suppressed ) )
{
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 ) )
{
if ( c != NULL )
{
*( c++ ) = rc;
}
value_parsed = 1;
}
/* width or input exhausted */
if ( value_parsed )
{
if ( c != NULL )
{
++status->n;
}
return ++spec;
}
else
{
/* input error, no character read */
if ( status->n == 0 )
{
status->n = -1;
}
return NULL;
}
}
case 's':
{
char * c = NULL;
if ( !( status->flags & E_suppressed ) )
{
c = va_arg( status->arg, char * );
}
while ( ( status->current < status->width ) &&
( ( rc = GET( status ) ) != EOF ) )
{
if ( isspace( (unsigned char)rc ) )
{
UNGET( rc, status );
if ( value_parsed )
{
/* matching sequence terminated by whitespace */
if ( c != NULL )
{
*c = '\0';
++status->n;
}
return ++spec;
}
else
{
/* matching error */
return NULL;
}
}
else
{
/* match */
if ( c != NULL )
{
*( c++ ) = rc;
}
value_parsed = 1;
}
}
/* width or input exhausted */
if ( value_parsed )
{
if ( c != NULL )
{
*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 = NULL;
if ( !( status->flags & E_suppressed ) )
{
c = va_arg( status->arg, char * );
}
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 */
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;
}
}
if ( c != NULL )
{
*( c++ ) = rc;
}
value_parsed = 1;
}
/* width or input exhausted */
if ( value_parsed )
{
if ( c != NULL )
{
*c = '\0';
++status->n;
}
return ++endspec;
}
else
{
if ( status->n == 0 )
{
status->n = -1;
}
return NULL;
}
}
case 'p':
status->base = 16;
status->flags |= E_pointer;
break;
case 'n':
{
if ( !( status->flags & E_suppressed ) )
{
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( (unsigned char)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( (unsigned char)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 = (char *)memchr( _PDCLIB_digits, tolower( (unsigned char)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:
fputs( "UNSUPPORTED SCANF FLAG COMBINATIONi\n", stdout );
return NULL; /* behaviour unspecified */
}
++( status->n );
}
return ++spec;
}
/* TODO: Floats. */
return NULL;
}
#endif
#ifdef TEST
#define _PDCLIB_FILEID "_PDCLIB/scan.c"
#define _PDCLIB_STRINGIO
#include "_PDCLIB_test.h"
#ifndef REGTEST
static int testscanf( const char * s, const char * format, ... )
{
struct _PDCLIB_status_t status;
char const * rc;
status.n = 0;
status.i = 0;
status.s = ( char * )s;
status.stream = NULL;
va_start( status.arg, format );
rc = _PDCLIB_scan( format, &status );
if ( rc != NULL && rc[0] != '\0' )
{
printf( "_PDCLIB_scan() did not return end-of-specifier on '%s'.\n", format );
++TEST_RESULTS;
}
if ( rc == NULL && s[0] != '\0' )
{
printf( "_PDCLIB_scan() returned NULL on '%s' input.", s );
++TEST_RESULTS;
}
va_end( status.arg );
return status.n;
}
#endif
#define TEST_CONVERSION_ONLY
int main( void )
{
#ifndef REGTEST
char source[100];
#include "scanf_testcases.h"
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,19 @@
/* _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;
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* no tests for raw data */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,81 @@
/* int_least64_t _PDCLIB_seek( FILE *, int_least64_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.
*/
#ifndef REGTEST
#include <stdio.h>
#include <stdint.h>
#include "pdclib/_PDCLIB_glue.h"
#include "pdclib/_PDCLIB_platform_errno.h"
#ifdef __cplusplus
extern "C" {
#endif
extern int64_t lseek64( int fd, _PDCLIB_int_least64_t offset, int whence );
extern long lseek( int fd, long offset, int whence );
#ifdef __cplusplus
}
#endif
_PDCLIB_int_least64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int_least64_t offset, int whence )
{
_PDCLIB_int_least64_t rc;
switch ( whence )
{
case SEEK_SET:
case SEEK_CUR:
case SEEK_END:
/* EMPTY - OK */
break;
default:
*_PDCLIB_errno_func() = _PDCLIB_EINVAL;
return EOF;
break;
}
#ifdef __CYGWIN__
rc = lseek( stream->handle, offset, whence );
#else
rc = lseek64( stream->handle, offset, whence );
#endif
if ( rc != EOF )
{
stream->ungetidx = 0;
stream->bufidx = 0;
stream->bufend = 0;
stream->pos.offset = rc;
return rc;
}
/* The 1:1 mapping in _PDCLIB_config.h ensures that this works. */
*_PDCLIB_errno_func() = errno;
return EOF;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Testing covered by ftell.c */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,598 @@
/* _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>
#ifndef REGTEST
#include "pdclib/_PDCLIB_tzcode.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 struct _PDCLIB_file_t _PDCLIB_serr = { 2, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, { 0 }, _IONBF | _PDCLIB_FWRITE,
#ifndef __STDC_NO_THREADS__
_PDCLIB_MTX_RECURSIVE_INIT,
#endif
NULL, NULL
};
static struct _PDCLIB_file_t _PDCLIB_sout = { 1, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, { 0 }, _IOLBF | _PDCLIB_FWRITE,
#ifndef __STDC_NO_THREADS__
_PDCLIB_MTX_RECURSIVE_INIT,
#endif
NULL, &_PDCLIB_serr
};
static struct _PDCLIB_file_t _PDCLIB_sin = { 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, { 0 }, _IOLBF | _PDCLIB_FREAD,
#ifndef __STDC_NO_THREADS__
_PDCLIB_MTX_RECURSIVE_INIT,
#endif
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;
#ifndef __STDC_NO_THREADS__
_PDCLIB_mtx_t _PDCLIB_filelist_mtx = _PDCLIB_MTX_PLAIN_INIT;
_PDCLIB_mtx_t _PDCLIB_time_mtx = _PDCLIB_MTX_PLAIN_INIT;
#endif
/* "C" locale - defaulting to ASCII-7.
1 kByte (+ 4 byte) of <ctype.h> data.
Each line: flags, lowercase, uppercase.
*/
static struct _PDCLIB_lc_ctype_entry_t _ctype_entries_C[ _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_C = { 0, 0x30, 0x39, 0x41, 0x46, 0x61, 0x66, &_ctype_entries_C[1] };
struct _PDCLIB_lc_ctype_t * _PDCLIB_lc_ctype = &_PDCLIB_lc_ctype_C;
struct _PDCLIB_lc_collate_t _PDCLIB_lc_collate_C = { 0 };
struct _PDCLIB_lc_collate_t * _PDCLIB_lc_collate = &_PDCLIB_lc_collate_C;
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_C =
{
0,
/* _PDCLIB_errno_texts */
{
/* unknown error */ ( char * )"unknown error",
/* EPERM */ ( char * )"EPERM (Operation not permitted)",
/* ENOENT */ ( char * )"ENOENT (No such file or directory)",
/* ESRCH */ ( char * )"ESRCH (No such process)",
/* EINTR */ ( char * )"EINTR (Interrupted function)",
/* EIO */ ( char * )"EIO (I/O error)",
/* ENXIO */ ( char * )"ENXIO (No such device or address)",
/* E2BIG */ ( char * )"E2BIG (Argument list too long)",
/* ENOEXEC */ ( char * )"ENOEXEC (Executable file format error)",
/* EBADF */ ( char * )"EBADF (Bad file descriptor)",
/* ECHILD */ ( char * )"ECHILD (No child processes)",
/* EAGAIN */ ( char * )"EAGAIN (Resource unavailable, try again)",
/* ENOMEM */ ( char * )"ENOMEM (Not enough space)",
/* EACCES */ ( char * )"EACCES (Permission denied)",
/* EFAULT */ ( char * )"EFAULT (Bad address)",
/* unknown error */ ( char * )"unknown error",
/* EBUSY */ ( char * )"EBUSY (Device or resource busy)",
/* EEXIST */ ( char * )"EEXIST (File exists)",
/* EXDEV */ ( char * )"EXDEV (Cross-device link)",
/* ENODEV */ ( char * )"ENODEV (No such device)",
/* ENOTDIR */ ( char * )"ENOTDIR (Not a directory)",
/* EISDIR */ ( char * )"EISDIR (Is a directory)",
/* EINVAL */ ( char * )"EINVAL (Invalid argument)",
/* ENFILE */ ( char * )"ENFILE (Too many files open in system)",
/* EMFILE */ ( char * )"EMFILE (File descriptor value too large)",
/* ENOTTY */ ( char * )"ENOTTY (Inappropriate I/O control operation)",
/* ETXTBSY */ ( char * )"ETXTBSY (Text file busy)",
/* EFBIG */ ( char * )"EFBIG (File too large)",
/* ENOSPC */ ( char * )"ENOSPC (No space left on device)",
/* ESPIPE */ ( char * )"ESPIPE (Invalid seek)",
/* EROFS */ ( char * )"EROFS (Read-only file system)",
/* EMLINK */ ( char * )"EMLINK (Too many links)",
/* EPIPE */ ( char * )"EPIPE (Broken pipe)",
/* EDOM */ ( char * )"EDOM (Mathematics argument out of domain of function)",
/* ERANGE */ ( char * )"ERANGE (Result too large)",
/* EDEADLK */ ( char * )"EDEADLK (Resource deadlock would occur)",
/* ENAMETOOLONG */ ( char * )"ENAMETOOLONG (Filename too long)",
/* ENOLCK */ ( char * )"ENOLCK (No locks available)",
/* ENOSYS */ ( char * )"ENOSYS (Function not supported)",
/* ENOTEMPTY */ ( char * )"ENOTEMPTY (Directory not empty)",
/* ELOOP */ ( char * )"ELOOP (Too many levels of symbolic links)",
/* unknown error */ ( char * )"unknown error",
/* ENOMSG */ ( char * )"ENOMSG (No message of the desired type)",
/* EIDRM */ ( char * )"EIDRM (Identifier removed)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* ENOSTR */ ( char * )"ENOSTR (Not a STREAM)",
/* ENODATA */ ( char * )"ENODATA (No message is available on the STREAM head read queue)",
/* ETIME */ ( char * )"ETIME (Stream ioctl() timeout)",
/* ENOSR */ ( char * )"ENOSR (No STREAM resources)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* ENOLINK */ ( char * )"ENOLINK (Link has been severed)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* EPROTO */ ( char * )"EPROTO (Protocol error)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* EBADMSG */ ( char * )"EBADMSG (Bad message)",
/* EOVERFLOW */ ( char * )"EOVERFLOW (Value too large to be stored in data type)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* EILSEQ */ ( char * )"EILSEQ (Illegal byte sequence)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* ENOTSOCK */ ( char * )"ENOTSOCK (Not a socket)",
/* EDESTADDRREQ */ ( char * )"EDESTADDRREQ (Destination address required)",
/* EMSGSIZE */ ( char * )"EMSGSIZE (Message too large)",
/* EPROTOTYPE */ ( char * )"EPROTOTYPE (Protocol wrong type for socket)",
/* ENOPROTOOPT */ ( char * )"ENOPROTOOPT (Protocol not available)",
/* EPROTONOSUPPORT */ ( char * )"EPROTONOSUPPORT (Protocol not supported)",
/* unknown error */ ( char * )"unknown error",
/* ENOTSUP */ ( char * )"ENOTSUP (Not supported)",
/* unknown error */ ( char * )"unknown error",
/* EAFNOSUPPORT */ ( char * )"EAFNOSUPPORT (Address family not supported)",
/* EADDRINUSE */ ( char * )"EADDRINUSE (Address in use)",
/* EADDRNOTAVAIL */ ( char * )"EADDRNOTAVAIL (Address not available)",
/* ENETDOWN */ ( char * )"ENETDOWN (Network is down)",
/* ENETUNREACH */ ( char * )"ENETUNREACH (Network unreachable)",
/* ENETRESET */ ( char * )"ENETRESET (Connection aborted by network)",
/* ECONNABORTED */ ( char * )"ECONNABORTED (Connection aborted)",
/* ECONNRESET */ ( char * )"ECONNRESET (Connection reset)",
/* ENOBUFS */ ( char * )"ENOBUFS (No buffer space available)",
/* EISCONN */ ( char * )"EISCONN (Socket is connected)",
/* ENOTCONN */ ( char * )"ENOTCONN (The socket is not connected)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* ETIMEDOUT */ ( char * )"ETIMEDOUT (Connection timed out)",
/* ECONNREFUSED */ ( char * )"ECONNREFUSED (Connection refused)",
/* unknown error */ ( char * )"unknown error",
/* EHOSTUNREACH */ ( char * )"EHOSTUNREACH (Host is unreachable)",
/* EALREADY */ ( char * )"EALREADY (Connection already in progress)",
/* EINPROGRESS */ ( char * )"EINPROGRESS (Operation in progress)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* ECANCELED */ ( char * )"ECANCELED (Operation canceled)",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* unknown error */ ( char * )"unknown error",
/* EOWNERDEAD */ ( char * )"EOWNERDEAD (Previous owner died)",
/* ENOTRECOVERABLE */ ( char * )"ENOTRECOVERABLE (State not recoverable)",
}
};
struct _PDCLIB_lc_messages_t * _PDCLIB_lc_messages = &_PDCLIB_lc_messages_C;
struct _PDCLIB_lc_time_t _PDCLIB_lc_time_C =
{
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 * )"Nov",
( 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"
}
};
struct _PDCLIB_lc_time_t * _PDCLIB_lc_time = &_PDCLIB_lc_time_C;
struct state _PDCLIB_lclmem;
struct state _PDCLIB_gmtmem;
/* Section 4.12.3 of X3.159-1989 requires that
Except for the strftime function, these functions [asctime,
ctime, gmtime, localtime] return values in one of two static
objects: a broken-down time structure and an array of char.
Thanks to Paul Eggert for noting this.
*/
struct tm _PDCLIB_tm;
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Testing covered by several other testdrivers using stdin / stdout /
stderr.
*/
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,135 @@
/* _PDCLIB_strtod_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>
#ifndef REGTEST
int _PDCLIB_strtod_prelim( const char * p, char * sign, char ** endptr )
{
int base = 10;
/* skipping leading whitespace */
while ( isspace( (unsigned char)*p ) )
{
++p;
}
/* determining / skipping sign */
if ( *p != '+' && *p != '-' )
{
*sign = '+';
}
else
{
*sign = *( p++ );
}
/* determining base */
if ( *p == '0' )
{
++p;
if ( *p == 'x' || *p == 'X' )
{
int period = 0;
base = 16;
++p;
if ( *p == '.' )
{
++p;
period = 1;
}
/* catching a border case here: "0x" followed by a non-digit should
be parsed as the unprefixed zero.
We have to "rewind" the parsing.
*/
if ( memchr( _PDCLIB_digits, tolower( (unsigned char)*p ), base ) == NULL )
{
p -= ( 2 + period );
}
}
else
{
--p;
}
}
else
{
/* inf / nan(...) */
/* Repurposing base: 0 for no match, -1 for inf, -2 for nan */
if ( tolower( (unsigned char)p[0] ) == 'i' && tolower( (unsigned char)p[1] ) == 'n' && tolower( (unsigned char)p[2] ) == 'f' )
{
p += 3;
base = -1;
}
else if ( tolower( (unsigned char)p[0] ) == 'n' && tolower( (unsigned char)p[1] ) == 'a' && tolower( (unsigned char)p[2] ) == 'n' )
{
const char * n = p + 3;
p = n;
base = -2;
if ( *n == '(' )
{
while ( *++n && *n != ')' );
if ( *n == ')' )
{
p = n + 1;
}
}
}
}
*endptr = (char *)p;
return base;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
int base = 0;
char sign = '\0';
char test1[] = " 123";
char test2[] = "\t+0123";
char test3[] = "\v-0x123";
TESTCASE( _PDCLIB_strtox_prelim( test1, &sign, &base ) == &test1[2] );
TESTCASE( sign == '+' );
TESTCASE( base == 10 );
base = 0;
sign = '\0';
TESTCASE( _PDCLIB_strtox_prelim( test2, &sign, &base ) == &test2[2] );
TESTCASE( sign == '+' );
TESTCASE( base == 8 );
base = 0;
sign = '\0';
TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == &test3[4] );
TESTCASE( sign == '-' );
TESTCASE( base == 16 );
base = 10;
sign = '\0';
TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == &test3[2] );
TESTCASE( sign == '-' );
TESTCASE( base == 10 );
base = 1;
TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == NULL );
base = 37;
TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == NULL );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,186 @@
/* _PDCLIB_strtok( char *, rsize_t *, const char *, char ** )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
char * _PDCLIB_strtok( char * _PDCLIB_restrict s1, rsize_t * _PDCLIB_restrict s1max, const char * _PDCLIB_restrict s2, char ** _PDCLIB_restrict ptr )
{
const char * p = s2;
if ( s1max == NULL || s2 == NULL || ptr == NULL || ( s1 == NULL && *ptr == NULL ) || *s1max > RSIZE_MAX )
{
_PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) );
return NULL;
}
if ( s1 != NULL )
{
/* new string */
*ptr = s1;
}
else
{
/* old string continued */
if ( *ptr == NULL )
{
/* No old string, no new string, nothing to do */
return NULL;
}
s1 = *ptr;
}
/* skip leading s2 characters */
while ( *p && *s1 )
{
if ( *s1 == *p )
{
/* found separator; skip and start over */
if ( *s1max == 0 )
{
_PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) );
return NULL;
}
++s1;
--( *s1max );
p = s2;
continue;
}
++p;
}
if ( ! *s1 )
{
/* no more to parse */
*ptr = s1;
return NULL;
}
/* skipping non-s2 characters */
*ptr = s1;
while ( **ptr )
{
p = s2;
while ( *p )
{
if ( **ptr == *p++ )
{
/* found separator; overwrite with '\0', position *ptr, return */
if ( *s1max == 0 )
{
_PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) );
return NULL;
}
--( *s1max );
*( ( *ptr )++ ) = '\0';
return s1;
}
}
if ( *s1max == 0 )
{
_PDCLIB_constraint_handler( _PDCLIB_CONSTRAINT_VIOLATION( _PDCLIB_EINVAL ) );
return NULL;
}
--( *s1max );
++( *ptr );
}
/* parsed to end of string */
return s1;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#ifndef REGTEST
static int HANDLER_CALLS = 0;
static void test_handler( const char * _PDCLIB_restrict msg, void * _PDCLIB_restrict ptr, errno_t error )
{
++HANDLER_CALLS;
}
#endif
int main( void )
{
#ifndef REGTEST
/* The original PDCLib strtok() test */
char s[] = "_a_bc__d_";
rsize_t max = strlen( s );
char * p;
TESTCASE( _PDCLIB_strtok( s, &max, "_", &p ) == &s[1] );
TESTCASE( max == 6 );
TESTCASE( s[1] == 'a' );
TESTCASE( s[2] == '\0' );
TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[3] );
TESTCASE( max == 3 );
TESTCASE( s[3] == 'b' );
TESTCASE( s[4] == 'c' );
TESTCASE( s[5] == '\0' );
TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[7] );
TESTCASE( max == 0 );
TESTCASE( s[6] == '_' );
TESTCASE( s[7] == 'd' );
TESTCASE( s[8] == '\0' );
TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == NULL );
TESTCASE( max == 0 );
strcpy( s, "ab_cd" );
max = strlen( s );
TESTCASE( _PDCLIB_strtok( s, &max, "_", &p ) == &s[0] );
TESTCASE( s[0] == 'a' );
TESTCASE( s[1] == 'b' );
TESTCASE( s[2] == '\0' );
TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == &s[3] );
TESTCASE( s[3] == 'c' );
TESTCASE( s[4] == 'd' );
TESTCASE( s[5] == '\0' );
TESTCASE( _PDCLIB_strtok( NULL, &max, "_", &p ) == NULL );
/* Testing the constraint handling */
strcpy( s, "ab.cd" );
max = 2;
TESTCASE( set_constraint_handler_s( test_handler ) == abort_handler_s );
TESTCASE( _PDCLIB_strtok( s, &max, ".", &p ) == NULL );
TESTCASE( HANDLER_CALLS == 1 );
{
/* The strtok_s() example code from the standard */
char str1[] = "?a???b,,,#c";
char str2[] = "\t \t";
rsize_t max1 = strlen( str1 );
rsize_t max2 = strlen( str2 );
char * ptr1;
char * ptr2;
TESTCASE( _PDCLIB_strtok( str1, &max1, "?", &ptr1 ) == &str1[1] );
TESTCASE( _PDCLIB_strtok( NULL, &max1, ",", &ptr1 ) == &str1[3] );
TESTCASE( _PDCLIB_strtok( str2, &max2, " \t", &ptr2 ) == NULL );
TESTCASE( _PDCLIB_strtok( NULL, &max1, "#,", &ptr1 ) == &str1[10] );
TESTCASE( _PDCLIB_strtok( NULL, &max1, "?", &ptr1 ) == NULL );
}
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,99 @@
/* _PDCLIB_strtox_main( const char **, int, _PDCLIB_uintmax_t, _PDCLIB_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>
#ifndef REGTEST
_PDCLIB_uintmax_t _PDCLIB_strtox_main( const char ** p, unsigned int base, uintmax_t error, uintmax_t limit, char * sign )
{
_PDCLIB_uintmax_t rc = 0;
int digit = -1;
const char * x;
_PDCLIB_uintmax_t limval = limit / base;
int limdigit = limit % base;
while ( ( x = (const char *)memchr( _PDCLIB_digits, tolower( (unsigned char)**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( (unsigned char)**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;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <errno.h>
int main( void )
{
#ifndef REGTEST
const char * p;
char test[] = "123_";
char fail[] = "xxx";
char sign = '-';
/* basic functionality */
p = test;
errno = 0;
TESTCASE( _PDCLIB_strtox_main( &p, 10u, ( uintmax_t )999, ( uintmax_t )999, &sign ) == 123 );
TESTCASE( errno == 0 );
TESTCASE( p == &test[3] );
/* proper functioning to smaller base */
p = test;
TESTCASE( _PDCLIB_strtox_main( &p, 8u, ( uintmax_t )999, ( uintmax_t )999, &sign ) == 0123 );
TESTCASE( errno == 0 );
TESTCASE( p == &test[3] );
/* overflowing subject sequence must still return proper endptr */
p = test;
TESTCASE( _PDCLIB_strtox_main( &p, 4u, ( uintmax_t )999, ( uintmax_t )6, &sign ) == 999 );
TESTCASE( errno == ERANGE );
TESTCASE( p == &test[3] );
TESTCASE( sign == '+' );
/* testing conversion failure */
errno = 0;
p = fail;
sign = '-';
TESTCASE( _PDCLIB_strtox_main( &p, 10u, ( uintmax_t )999, ( uintmax_t )999, &sign ) == 0 );
TESTCASE( p == NULL );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,113 @@
/* _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>
#ifndef REGTEST
const char * _PDCLIB_strtox_prelim( const char * p, char * sign, int * base )
{
/* skipping leading whitespace */
while ( isspace( (unsigned char)*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( (unsigned char)*p ), *base ) == NULL )
{
p -= 2;
}
}
else if ( *base == 0 )
{
*base = 8;
/* back up one digit, so that a plain zero is decoded correctly
(and endptr is set correctly as well).
(2019-01-15, Giovanni Mascellani)
*/
--p;
}
else
{
--p;
}
}
else if ( ! *base )
{
*base = 10;
}
return ( ( *base >= 2 ) && ( *base <= 36 ) ) ? p : NULL;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
#ifndef REGTEST
int base = 0;
char sign = '\0';
char test1[] = " 123";
char test2[] = "\t+0123";
char test3[] = "\v-0x123";
TESTCASE( _PDCLIB_strtox_prelim( test1, &sign, &base ) == &test1[2] );
TESTCASE( sign == '+' );
TESTCASE( base == 10 );
base = 0;
sign = '\0';
TESTCASE( _PDCLIB_strtox_prelim( test2, &sign, &base ) == &test2[2] );
TESTCASE( sign == '+' );
TESTCASE( base == 8 );
base = 0;
sign = '\0';
TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == &test3[4] );
TESTCASE( sign == '-' );
TESTCASE( base == 16 );
base = 10;
sign = '\0';
TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == &test3[2] );
TESTCASE( sign == '-' );
TESTCASE( base == 10 );
base = 1;
TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == NULL );
base = 37;
TESTCASE( _PDCLIB_strtox_prelim( test3, &sign, &base ) == NULL );
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,73 @@
/* _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>
#ifndef REGTEST
void _PDCLIB_assert99( const char * const message1, const char * const function, const char * const message2 )
{
fputs( message1, stderr );
fputs( function, stderr );
fputs( message2, stderr );
abort();
}
void _PDCLIB_assert89( const char * const message )
{
fputs( message, stderr );
abort();
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <signal.h>
static int EXPECTED_ABORT = 0;
static int UNEXPECTED_ABORT = 1;
static void aborthandler( int sig )
{
TESTCASE( ! EXPECTED_ABORT );
exit( ( signed int )TEST_RESULTS );
}
#ifdef NDEBUG
#error Compiling test drivers with NDEBUG set is a questionable choice...
#endif
#define NDEBUG
#include <assert.h>
static int disabled_test( void )
{
int i = 0;
assert( i == 0 ); /* NDEBUG set, condition met */
assert( i == 1 ); /* NDEBUG set, condition fails */
return i;
}
#undef NDEBUG
#include <assert.h>
int main( void )
{
TESTCASE( signal( SIGABRT, &aborthandler ) != SIG_ERR );
TESTCASE( disabled_test() == 0 );
assert( UNEXPECTED_ABORT ); /* NDEBUG not set, condition met */
assert( EXPECTED_ABORT ); /* NDEBUG not set, condition fails - should abort */
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,71 @@
/* _PDCLIB_errno
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#ifndef REGTEST
#include "pdclib/_PDCLIB_internal.h"
#if __STDC_VERSION__ >= 201112L && ! defined( __STDC_NO_THREADS__ )
_Thread_local int _PDCLIB_errno = 0;
#else
static int _PDCLIB_errno = 0;
#endif
int * _PDCLIB_errno_func()
{
return &_PDCLIB_errno;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
#include <errno.h>
#if ! defined( REGTEST ) && __STDC_VERSION__ >= 201112L && ! defined( __STDC_NO_THREADS__ )
#include <threads.h>
static int thread_func( void * arg )
{
TESTCASE( errno == 0 );
*_PDCLIB_errno_func() = 1;
TESTCASE( errno == 1 );
thrd_exit( 0 );
}
#endif
int main( void )
{
errno = 0;
TESTCASE( errno == 0 );
errno = EDOM;
TESTCASE( errno == EDOM );
errno = ERANGE;
TESTCASE( errno == ERANGE );
#if ! defined( REGTEST ) && __STDC_VERSION__ >= 201112L && ! defined( __STDC_NO_THREADS__ )
{
thrd_t t;
struct timespec spec = { 1, 0 };
int rc;
TESTCASE( thrd_create( &t, thread_func, NULL ) == thrd_success );
TESTCASE( thrd_sleep( &spec, NULL ) == 0 );
TESTCASE( errno == ERANGE );
TESTCASE( thrd_join( t, &rc ) == thrd_success );
TESTCASE( rc == 0 );
}
#endif
return TEST_RESULTS;
}
#endif

View File

@@ -0,0 +1,120 @@
/* stdarg
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdarg.h>
#include <limits.h>
#include <float.h>
#ifdef TEST
#include "_PDCLIB_test.h"
typedef int ( *intfunc_t )( void );
#define TAG_END 0
#define TAG_INT 1
#define TAG_LONG 2
#define TAG_LLONG 3
#define TAG_DBL 4
#define TAG_LDBL 5
#define TAG_INTPTR 6
#define TAG_LDBLPTR 7
#define TAG_FUNCPTR 8
static int dummy( void )
{
return INT_MAX;
}
static int test( int s, ... )
{
va_list ap;
va_start( ap, s );
for ( ;; )
{
switch ( s )
{
case TAG_INT:
{
TESTCASE( va_arg( ap, int ) == INT_MAX );
s = va_arg( ap, int );
break;
}
case TAG_LONG:
{
TESTCASE( va_arg( ap, long ) == LONG_MAX );
s = va_arg( ap, int );
break;
}
case TAG_LLONG:
{
TESTCASE( va_arg( ap, long long ) == LLONG_MAX );
s = va_arg( ap, int );
break;
}
case TAG_DBL:
{
TESTCASE( va_arg( ap, double ) == DBL_MAX );
s = va_arg( ap, int );
break;
}
case TAG_LDBL:
{
TESTCASE( va_arg( ap, long double ) == LDBL_MAX );
s = va_arg( ap, int );
break;
}
case TAG_INTPTR:
{
TESTCASE( *( va_arg( ap, int * ) ) == INT_MAX );
s = va_arg( ap, int );
break;
}
case TAG_LDBLPTR:
{
TESTCASE( *( va_arg( ap, long double * ) ) == LDBL_MAX );
s = va_arg( ap, int );
break;
}
case TAG_FUNCPTR:
{
intfunc_t function;
TESTCASE( ( function = va_arg( ap, intfunc_t ) ) == dummy );
TESTCASE( function() == INT_MAX );
s = va_arg( ap, int );
break;
}
case TAG_END:
{
va_end( ap );
return 0;
}
}
}
}
int main( void )
{
int x = INT_MAX;
long double d = LDBL_MAX;
test( TAG_END );
test( TAG_INT, INT_MAX, TAG_END );
test( TAG_LONG, LONG_MAX, TAG_LLONG, LLONG_MAX, TAG_END );
test( TAG_DBL, DBL_MAX, TAG_LDBL, LDBL_MAX, TAG_END );
test( TAG_INTPTR, &x, TAG_LDBLPTR, &d, TAG_FUNCPTR, dummy, TAG_END );
return TEST_RESULTS;
}
#endif