aboutsummaryrefslogtreecommitdiffstats
path: root/src/pdclib/functions/_PDCLIB
diff options
context:
space:
mode:
authortcsullivan <tullivan99@gmail.com>2018-11-17 13:02:57 -0500
committertcsullivan <tullivan99@gmail.com>2018-11-17 13:02:57 -0500
commitc6ef89664b8c0d7aa85bddd5c7014aa6df82cbe7 (patch)
treed1f9d09412a46bdf4344fe30392455070a72993d /src/pdclib/functions/_PDCLIB
parentdb38c4b9dac461de0ed75bf6d079dacba1b31bc9 (diff)
added pdclib, removed sash
Diffstat (limited to 'src/pdclib/functions/_PDCLIB')
-rw-r--r--src/pdclib/functions/_PDCLIB/Readme.txt10
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_atomax.c46
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_closeall.c37
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_digits.c33
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_filemode.c90
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_is_leap.c39
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_collate.c63
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_ctype.c365
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_messages.c88
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_monetary.c158
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_numeric.c84
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_time.c165
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_load_lines.c81
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_prepread.c50
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_prepwrite.c41
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_print.c625
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_scan.c639
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_seed.c19
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_strtox_main.c88
-rw-r--r--src/pdclib/functions/_PDCLIB/_PDCLIB_strtox_prelim.c94
-rw-r--r--src/pdclib/functions/_PDCLIB/assert.c71
-rw-r--r--src/pdclib/functions/_PDCLIB/errno.c37
-rw-r--r--src/pdclib/functions/_PDCLIB/stdarg.c115
23 files changed, 3038 insertions, 0 deletions
diff --git a/src/pdclib/functions/_PDCLIB/Readme.txt b/src/pdclib/functions/_PDCLIB/Readme.txt
new file mode 100644
index 0000000..13ad05c
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/Readme.txt
@@ -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).
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_atomax.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_atomax.c
new file mode 100644
index 0000000..eaf7ced
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_atomax.c
@@ -0,0 +1,46 @@
+/* _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( *s ) ) ++s;
+ if ( *s == '+' ) ++s;
+ else if ( *s == '-' ) sign = *(s++);
+ /* TODO: Earlier version was missing tolower() but was not caught by tests */
+ while ( ( x = memchr( _PDCLIB_digits, tolower(*(s++)), 10 ) ) != NULL )
+ {
+ rc = rc * 10 + ( x - _PDCLIB_digits );
+ }
+ return ( sign == '+' ) ? rc : -rc;
+}
+
+#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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_closeall.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_closeall.c
new file mode 100644
index 0000000..3c928e7
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_closeall.c
@@ -0,0 +1,37 @@
+/* _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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_digits.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_digits.c
new file mode 100644
index 0000000..69c4f2b
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_digits.c
@@ -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_int.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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_filemode.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_filemode.c
new file mode 100644
index 0000000..2555a00
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_filemode.c
@@ -0,0 +1,90 @@
+/* _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;
+ switch ( mode[0] )
+ {
+ case 'r':
+ rc |= _PDCLIB_FREAD;
+ break;
+ case 'w':
+ rc |= _PDCLIB_FWRITE;
+ break;
+ case 'a':
+ rc |= _PDCLIB_FAPPEND | _PDCLIB_FWRITE;
+ break;
+ default:
+ /* Other than read, write, or append - invalid */
+ return 0;
+ }
+ for ( i = 1; i < 4; ++i )
+ {
+ switch ( mode[i] )
+ {
+ case '+':
+ if ( rc & _PDCLIB_FRW ) return 0; /* Duplicates are invalid */
+ rc |= _PDCLIB_FRW;
+ break;
+ case 'b':
+ if ( rc & _PDCLIB_FBIN ) return 0; /* Duplicates are invalid */
+ rc |= _PDCLIB_FBIN;
+ break;
+ case '\0':
+ /* End of mode */
+ return rc;
+ default:
+ /* Other than read/write or binary - invalid. */
+ return 0;
+ }
+ }
+ /* Longer than three chars - invalid. */
+ return 0;
+}
+
+#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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_is_leap.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_is_leap.c
new file mode 100644
index 0000000..2407337
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_is_leap.c
@@ -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_int.h"
+
+int _PDCLIB_is_leap( int year_offset )
+{
+ /* year given as offset from 1900, matching tm.tm_year in <time.h> */
+ long long year = year_offset + 1900ll;
+ return ( ( year % 4 ) == 0 && ( ( year % 25 ) != 0 || ( year % 400 ) == 0 ) );
+}
+
+#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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_collate.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_collate.c
new file mode 100644
index 0000000..d66b996
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_collate.c
@@ -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_int.h"
+
+struct _PDCLIB_lc_collate_t * _PDCLIB_load_lc_collate( const char * path, const char * locale )
+{
+ struct _PDCLIB_lc_collate_t * rc = NULL;
+ const char * extension = "_collate.dat";
+ char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
+
+ if ( file )
+ {
+ FILE * fh;
+
+ strcpy( file, path );
+ strcat( file, locale );
+ strcat( file, extension );
+
+ if ( ( fh = fopen( file, "rb" ) ) != NULL )
+ {
+ if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_collate_t ) ) ) != NULL )
+ {
+ /* TODO: Collation data */
+
+ rc->alloced = 1;
+ }
+
+ fclose( fh );
+ }
+
+ free( file );
+ }
+
+ return rc;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+#ifndef REGTEST
+ TESTCASE( NO_TESTDRIVER );
+#endif
+
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_ctype.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_ctype.c
new file mode 100644
index 0000000..81fb18f
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_ctype.c
@@ -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_int.h"
+
+struct _PDCLIB_lc_ctype_t * _PDCLIB_load_lc_ctype( const char * path, const char * locale )
+{
+ struct _PDCLIB_lc_ctype_t * rc = NULL;
+ const char * extension = "_ctype.dat";
+ char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
+
+ if ( file )
+ {
+ FILE * fh;
+
+ strcpy( file, path );
+ strcat( file, locale );
+ strcat( file, extension );
+
+ if ( ( fh = fopen( file, "rb" ) ) != NULL )
+ {
+ if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_ctype_t ) ) ) != NULL )
+ {
+ struct _PDCLIB_lc_ctype_entry_t * entry;
+
+ if ( ( entry = malloc( sizeof( struct _PDCLIB_lc_ctype_entry_t ) * _PDCLIB_CHARSET_SIZE + 1 ) ) != NULL )
+ {
+ rc->entry = entry + 1;
+ rc->entry[ -1 ].flags = rc->entry[ -1 ].upper = rc->entry[ -1 ].lower = 0;
+
+ if ( fscanf( fh, "%x %x %x %x %x %x", &rc->digits_low, &_PDCLIB_lc_ctype.digits_high, &_PDCLIB_lc_ctype.Xdigits_low, &_PDCLIB_lc_ctype.Xdigits_high, &_PDCLIB_lc_ctype.xdigits_low, &_PDCLIB_lc_ctype.xdigits_high ) == 6 )
+ {
+ size_t i;
+
+ for ( i = 0; i < _PDCLIB_CHARSET_SIZE; ++i )
+ {
+ if ( fscanf( fh, "%x %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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_messages.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_messages.c
new file mode 100644
index 0000000..6ff2a50
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_messages.c
@@ -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_int.h"
+
+struct _PDCLIB_lc_messages_t * _PDCLIB_load_lc_messages( const char * path, const char * locale )
+{
+ struct _PDCLIB_lc_messages_t * rc = NULL;
+ const char * extension = "_messages.dat";
+ char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
+
+ if ( file )
+ {
+ FILE * fh;
+
+ strcpy( file, path );
+ strcat( file, locale );
+ strcat( file, extension );
+
+ if ( ( fh = fopen( file, "rb" ) ) != NULL )
+ {
+ if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_messages_t ) ) ) != NULL )
+ {
+ char * data = _PDCLIB_load_lines( fh, _PDCLIB_ERRNO_MAX );
+
+ if ( data != NULL )
+ {
+ size_t i;
+
+ for ( i = 0; i < _PDCLIB_ERRNO_MAX; ++i )
+ {
+ rc->errno_texts[ i ] = data;
+ data += strlen( data ) + 1;
+ }
+
+ rc->alloced = 1;
+ }
+ else
+ {
+ free( rc );
+ rc = NULL;
+ }
+ }
+
+ fclose( fh );
+ }
+
+ free( file );
+ }
+
+ return rc;
+}
+
+#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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_monetary.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_monetary.c
new file mode 100644
index 0000000..e2dcbb4
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_monetary.c
@@ -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_int.h"
+
+struct _PDCLIB_lc_lconv_monetary_t * _PDCLIB_load_lc_monetary( const char * path, const char * locale )
+{
+ struct _PDCLIB_lc_lconv_monetary_t * rc = NULL;
+ const char * extension = "_monetary.dat";
+ char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
+
+ if ( file )
+ {
+ FILE * fh;
+
+ strcpy( file, path );
+ strcat( file, locale );
+ strcat( file, extension );
+
+ if ( ( fh = fopen( file, "rb" ) ) != NULL )
+ {
+ if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_lconv_monetary_t ) ) ) != NULL )
+ {
+ char buffer[ 14 ];
+ char * data = _PDCLIB_load_lines( fh, 7 );
+
+ if ( data != NULL )
+ {
+ if ( fread( buffer, 1, 14, fh ) == 14 )
+ {
+ rc->mon_decimal_point = data;
+ data += strlen( data ) + 1;
+ rc->mon_thousands_sep = data;
+ data += strlen( data ) + 1;
+ rc->mon_grouping = data;
+ data += strlen( data ) + 1;
+ rc->positive_sign = data;
+ data += strlen( data ) + 1;
+ rc->negative_sign = data;
+ data += strlen( data ) + 1;
+ rc->currency_symbol = data;
+ data += strlen( data ) + 1;
+ rc->int_curr_symbol = data;
+
+ rc->frac_digits = buffer[ 0 ];
+ rc->p_cs_precedes = buffer[ 1 ];
+ rc->n_cs_precedes = buffer[ 2 ];
+ rc->p_sep_by_space = buffer[ 3 ];
+ rc->n_sep_by_space = buffer[ 4 ];
+ rc->p_sign_posn = buffer[ 5 ];
+ rc->n_sign_posn = buffer[ 6 ];
+ rc->int_frac_digits = buffer[ 7 ];
+ rc->int_p_cs_precedes = buffer[ 8 ];
+ rc->int_n_cs_precedes = buffer[ 9 ];
+ rc->int_p_sep_by_space = buffer[ 10 ];
+ rc->int_n_sep_by_space = buffer[ 11 ];
+ rc->int_p_sign_posn = buffer[ 12 ];
+ rc->int_n_sign_posn= buffer[ 13 ];
+ }
+ else
+ {
+ free( data );
+ free( rc );
+ rc = NULL;
+ }
+ }
+ else
+ {
+ free( rc );
+ rc = NULL;
+ }
+ }
+
+ fclose( fh );
+ }
+
+ free( file );
+ }
+
+ return rc;
+}
+
+#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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_numeric.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_numeric.c
new file mode 100644
index 0000000..de42bbd
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_numeric.c
@@ -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_int.h"
+
+struct _PDCLIB_lc_lconv_numeric_t * _PDCLIB_load_lc_numeric( const char * path, const char * locale )
+{
+ struct _PDCLIB_lc_lconv_numeric_t * rc = NULL;
+ const char * extension = "_numeric.dat";
+ char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
+
+ if ( file )
+ {
+ FILE * fh;
+
+ strcpy( file, path );
+ strcat( file, locale );
+ strcat( file, extension );
+
+ if ( ( fh = fopen( file, "rb" ) ) != NULL )
+ {
+ if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_lconv_numeric_t ) ) ) != NULL )
+ {
+ char * data = _PDCLIB_load_lines( fh, 3 );
+
+ if ( data != NULL )
+ {
+ rc->decimal_point = data;
+ data += strlen( data ) + 1;
+ rc->thousands_sep = data;
+ data += strlen( data ) + 1;
+ rc->grouping = data;
+ }
+ else
+ {
+ free( rc );
+ rc = NULL;
+ }
+ }
+
+ fclose( fh );
+ }
+
+ free( file );
+ }
+
+ return rc;
+}
+
+#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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_time.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_time.c
new file mode 100644
index 0000000..733e5c7
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lc_time.c
@@ -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_int.h"
+
+struct _PDCLIB_lc_time_t * _PDCLIB_load_lc_time( const char * path, const char * locale )
+{
+ struct _PDCLIB_lc_time_t * rc = NULL;
+ const char * extension = "_time.dat";
+ char * file = malloc( strlen( path ) + strlen( locale ) + strlen( extension ) + 1 );
+
+ if ( file )
+ {
+ FILE * fh;
+
+ strcpy( file, path );
+ strcat( file, locale );
+ strcat( file, extension );
+
+ if ( ( fh = fopen( file, "rb" ) ) != NULL )
+ {
+ if ( ( rc = malloc( sizeof( struct _PDCLIB_lc_time_t ) ) ) != NULL )
+ {
+ char * data = _PDCLIB_load_lines( fh, 44 );
+
+ if ( data != NULL )
+ {
+ size_t i;
+
+ for ( i = 0; i < 12; ++i )
+ {
+ rc->month_name_abbr[ i ] = data;
+ data += strlen( data ) + 1;
+ }
+
+ for ( i = 0; i < 12; ++i )
+ {
+ rc->month_name_full[ i ] = data;
+ data += strlen( data ) + 1;
+ }
+
+ for ( i = 0; i < 7; ++i )
+ {
+ rc->day_name_abbr[ i ] = data;
+ data += strlen( data ) + 1;
+ }
+
+ for ( i = 0; i < 7; ++i )
+ {
+ rc->day_name_full[ i ] = data;
+ data += strlen( data ) + 1;
+ }
+
+ rc->alloced = 1;
+ }
+ else
+ {
+ free( rc );
+ rc = NULL;
+ }
+ }
+
+ fclose( fh );
+ }
+
+ free( file );
+ }
+
+ return rc;
+}
+
+#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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lines.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lines.c
new file mode 100644
index 0000000..aaaa743
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_load_lines.c
@@ -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 = 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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_prepread.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_prepread.c
new file mode 100644
index 0000000..1d60642
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_prepread.c
@@ -0,0 +1,50 @@
+/* _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.
+ See comments on implementation-defined errno values in
+ <_PDCLIB_config.h>.
+ */
+ _PDCLIB_errno = _PDCLIB_ERROR;
+ stream->status |= _PDCLIB_ERRORFLAG;
+ return EOF;
+ }
+ stream->status |= _PDCLIB_FREAD | _PDCLIB_BYTESTREAM;
+ if ( ( stream->bufidx == stream->bufend ) && ( stream->ungetidx == 0 ) )
+ {
+ return _PDCLIB_fillbuffer( stream );
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ /* Testing covered by ftell.c */
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_prepwrite.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_prepwrite.c
new file mode 100644
index 0000000..dcdc970
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_prepwrite.c
@@ -0,0 +1,41 @@
+/* _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.
+ See the comments on implementation-defined errno values in
+ <_PDCLIB_config.h>.
+ */
+ _PDCLIB_errno = _PDCLIB_ERROR;
+ 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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_print.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_print.c
new file mode 100644
index 0000000..3c13da2
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_print.c
@@ -0,0 +1,625 @@
+/* _PDCLIB_print( const char *, struct _PDCLIB_status_t * )
+
+ This file is part of the Public Domain C Library (PDCLib).
+ Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#ifndef REGTEST
+
+/* Using an integer's bits as flags for both the conversion flags and length
+ modifiers.
+*/
+/* FIXME: one too many flags to work on a 16-bit machine, join some (e.g. the
+ width flags) into a combined field.
+*/
+#define E_minus (1<<0)
+#define E_plus (1<<1)
+#define E_alt (1<<2)
+#define E_space (1<<3)
+#define E_zero (1<<4)
+#define E_done (1<<5)
+
+#define E_char (1<<6)
+#define E_short (1<<7)
+#define E_long (1<<8)
+#define E_llong (1<<9)
+#define E_intmax (1<<10)
+#define E_size (1<<11)
+#define E_ptrdiff (1<<12)
+#define E_pointer (1<<13)
+
+#define E_ldouble (1<<14)
+
+#define E_lower (1<<15)
+#define E_unsigned (1<<16)
+
+/* This macro delivers a given character to either a memory buffer or a stream,
+ depending on the contents of 'status' (struct _PDCLIB_status_t).
+ x - the character to be delivered
+ i - pointer to number of characters already delivered in this call
+ n - pointer to maximum number of characters to be delivered in this call
+ s - the buffer into which the character shall be delivered
+*/
+#define PUT( x ) \
+do { \
+ int character = x; \
+ if ( status->i < status->n ) { \
+ if ( status->stream != NULL ) \
+ putc( character, status->stream ); \
+ else \
+ status->s[status->i] = character; \
+ } \
+ ++(status->i); \
+} while ( 0 )
+
+
+static void intformat( intmax_t value, struct _PDCLIB_status_t * status )
+{
+ /* At worst, we need two prefix characters (hex prefix). */
+ char preface[3] = "\0";
+ size_t preidx = 0;
+ if ( status->prec < 0 )
+ {
+ status->prec = 1;
+ }
+ if ( ( status->flags & E_alt ) && ( status->base == 16 || status->base == 8 ) && ( value != 0 ) )
+ {
+ /* Octal / hexadecimal prefix for "%#" conversions */
+ preface[ preidx++ ] = '0';
+ if ( status->base == 16 )
+ {
+ preface[ preidx++ ] = ( status->flags & E_lower ) ? 'x' : 'X';
+ }
+ }
+ if ( value < 0 )
+ {
+ /* Negative sign for negative values - at all times. */
+ preface[ preidx++ ] = '-';
+ }
+ else if ( ! ( status->flags & E_unsigned ) )
+ {
+ /* plus sign / extra space are only for unsigned conversions */
+ if ( status->flags & E_plus )
+ {
+ preface[ preidx++ ] = '+';
+ }
+ else if ( status->flags & E_space )
+ {
+ preface[ preidx++ ] = ' ';
+ }
+ }
+ {
+ /* At this point, status->current has the number of digits queued up.
+ Determine if we have a precision requirement to pad those.
+ */
+ size_t prec_pads = ( (_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.
+*/
+#define INT2BASE() \
+do \
+{ \
+ /* Special case: zero value, zero precision -- no output (but padding) */ \
+ if ( status->current == 0 && value == 0 && status->prec == 0 ) \
+ { \
+ intformat( value, status ); \
+ } \
+ else \
+ { \
+ /* Registering the character being printed at the end of the function here \
+ already so it will be taken into account when the deepestmost recursion \
+ does the prefix / padding stuff. \
+ */ \
+ ++(status->current); \
+ if ( ( value / status->base ) != 0 ) \
+ { \
+ /* More digits to be done - recurse deeper */ \
+ int2base( value / status->base, status ); \
+ } \
+ else \
+ { \
+ /* We reached the last digit, the deepest point of our recursion, and \
+ only now know how long the number to be printed actually is. Now we \
+ have to do the sign, prefix, width, and precision padding stuff \
+ before printing the numbers while we resurface from the recursion. \
+ */ \
+ intformat( value, status ); \
+ } \
+ /* Recursion tail - print the current digit. */ \
+ { \
+ int digit = value % status->base; \
+ if ( digit < 0 ) \
+ { \
+ digit *= -1; \
+ } \
+ if ( status->flags & E_lower ) \
+ { \
+ /* Lowercase letters. Same array used for strto...(). */ \
+ PUT( _PDCLIB_digits[ digit ] ); \
+ } \
+ else \
+ { \
+ /* Uppercase letters. Array only used here, only 0-F. */ \
+ PUT( _PDCLIB_Xdigits[ digit ] ); \
+ } \
+ } \
+ } \
+} while ( 0 )
+
+
+static void int2base( intmax_t value, struct _PDCLIB_status_t * status )
+{
+ INT2BASE();
+}
+
+
+static void stringformat( const char * s, struct _PDCLIB_status_t * status )
+{
+ if ( status->flags & E_char )
+ {
+ status->prec = 1;
+ }
+ else
+ {
+ if ( status->prec < 0 )
+ {
+ status->prec = strlen( s );
+ }
+ else
+ {
+ int i;
+ for ( i = 0; i < status->prec; ++i )
+ {
+ if ( s[i] == 0 )
+ {
+ status->prec = i;
+ break;
+ }
+ }
+ }
+ }
+ if ( ! ( status->flags & E_minus ) && ( status->width > (_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);
+ }
+ }
+}
+
+
+const char * _PDCLIB_print( const char * spec, struct _PDCLIB_status_t * status )
+{
+ const char * orig_spec = spec;
+ if ( *(++spec) == '%' )
+ {
+ /* %% -> print single '%' */
+ PUT( *spec );
+ return ++spec;
+ }
+ /* Initializing status structure */
+ status->flags = 0;
+ status->base = 0;
+ status->current = 0;
+ status->width = 0;
+ status->prec = EOF;
+
+ /* First come 0..n flags */
+ do
+ {
+ switch ( *spec )
+ {
+ case '-':
+ /* left-aligned output */
+ status->flags |= E_minus;
+ ++spec;
+ break;
+ case '+':
+ /* positive numbers prefixed with '+' */
+ status->flags |= E_plus;
+ ++spec;
+ break;
+ case '#':
+ /* alternative format (leading 0x for hex, 0 for octal) */
+ status->flags |= E_alt;
+ ++spec;
+ break;
+ case ' ':
+ /* positive numbers prefixed with ' ' */
+ status->flags |= E_space;
+ ++spec;
+ break;
+ case '0':
+ /* right-aligned padding done with '0' instead of ' ' */
+ status->flags |= E_zero;
+ ++spec;
+ break;
+ default:
+ /* not a flag, exit flag parsing */
+ status->flags |= E_done;
+ break;
+ }
+ } while ( ! ( status->flags & E_done ) );
+
+ /* Optional field width */
+ if ( *spec == '*' )
+ {
+ /* Retrieve width value from argument stack */
+ int width = va_arg( status->arg, int );
+ if ( width < 0 )
+ {
+ status->flags |= E_minus;
+ status->width = abs( width );
+ }
+ else
+ {
+ status->width = width;
+ }
+ ++spec;
+ }
+ else
+ {
+ /* If a width is given, strtol() will return its value. If not given,
+ strtol() will return zero. In both cases, endptr will point to the
+ rest of the conversion specifier - just what we need.
+ */
+ status->width = (int)strtol( spec, (char**)&spec, 10 );
+ }
+
+ /* Optional precision */
+ if ( *spec == '.' )
+ {
+ ++spec;
+ if ( *spec == '*' )
+ {
+ /* Retrieve precision value from argument stack. A negative value
+ is as if no precision is given - as precision is initalized to
+ EOF (negative), there is no need for testing for negative here.
+ */
+ status->prec = va_arg( status->arg, int );
+ ++spec;
+ }
+ else
+ {
+ char * endptr;
+ status->prec = (int)strtol( spec, &endptr, 10 );
+ if ( spec == endptr )
+ {
+ /* Decimal point but no number - equals zero */
+ status->prec = 0;
+ }
+ spec = endptr;
+ }
+ /* Having a precision cancels out any zero flag. */
+ status->flags &= ~E_zero;
+ }
+
+ /* Optional length modifier
+ We step one character ahead in any case, and step back only if we find
+ there has been no length modifier (or step ahead another character if it
+ has been "hh" or "ll").
+ */
+ switch ( *(spec++) )
+ {
+ case 'h':
+ if ( *spec == 'h' )
+ {
+ /* hh -> char */
+ status->flags |= E_char;
+ ++spec;
+ }
+ else
+ {
+ /* h -> short */
+ status->flags |= E_short;
+ }
+ break;
+ case 'l':
+ if ( *spec == 'l' )
+ {
+ /* ll -> long long */
+ status->flags |= E_llong;
+ ++spec;
+ }
+ else
+ {
+ /* k -> long */
+ status->flags |= E_long;
+ }
+ break;
+ case 'j':
+ /* j -> intmax_t, which might or might not be long long */
+ status->flags |= E_intmax;
+ break;
+ case 'z':
+ /* z -> size_t, which might or might not be unsigned int */
+ status->flags |= E_size;
+ break;
+ case 't':
+ /* t -> ptrdiff_t, which might or might not be long */
+ status->flags |= E_ptrdiff;
+ break;
+ case 'L':
+ /* L -> long double */
+ status->flags |= E_ldouble;
+ break;
+ default:
+ --spec;
+ break;
+ }
+
+ /* Conversion specifier */
+ switch ( *spec )
+ {
+ case 'd':
+ /* FALLTHROUGH */
+ case 'i':
+ status->base = 10;
+ break;
+ case 'o':
+ status->base = 8;
+ status->flags |= E_unsigned;
+ break;
+ case 'u':
+ status->base = 10;
+ status->flags |= E_unsigned;
+ break;
+ case 'x':
+ status->base = 16;
+ status->flags |= ( E_lower | E_unsigned );
+ break;
+ case 'X':
+ status->base = 16;
+ status->flags |= E_unsigned;
+ break;
+ case 'f':
+ case 'F':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ break;
+ case 'a':
+ case 'A':
+ break;
+ case 'c':
+ /* TODO: wide chars. */
+ {
+ char c[1];
+ c[0] = (char)va_arg( status->arg, int );
+ status->flags |= E_char;
+ stringformat( c, status );
+ return ++spec;
+ }
+ case 's':
+ /* TODO: wide chars. */
+ stringformat( va_arg( status->arg, char * ), status );
+ return ++spec;
+ case 'p':
+ status->base = 16;
+ status->flags |= ( E_lower | E_unsigned | E_alt | E_pointer );
+ break;
+ case 'n':
+ {
+ int * val = va_arg( status->arg, int * );
+ *val = status->i;
+ return ++spec;
+ }
+ default:
+ /* No conversion specifier. Bad conversion. */
+ return orig_spec;
+ }
+
+ /* Do the actual output based on our findings */
+ if ( status->base != 0 )
+ {
+ /* Integer conversions */
+ /* TODO: Check for invalid flag combinations. */
+ if ( status->flags & E_unsigned )
+ {
+ uintmax_t value;
+ switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_size | E_pointer | E_intmax ) )
+ {
+ case E_char:
+ value = (uintmax_t)(unsigned char)va_arg( status->arg, int );
+ break;
+ case E_short:
+ value = (uintmax_t)(unsigned short)va_arg( status->arg, int );
+ break;
+ case 0:
+ value = (uintmax_t)va_arg( status->arg, unsigned int );
+ break;
+ case E_long:
+ value = (uintmax_t)va_arg( status->arg, unsigned long );
+ break;
+ case E_llong:
+ value = (uintmax_t)va_arg( status->arg, unsigned long long );
+ break;
+ case E_size:
+ value = (uintmax_t)va_arg( status->arg, size_t );
+ break;
+ case E_pointer:
+ value = (uintmax_t)(uintptr_t)va_arg( status->arg, void * );
+ break;
+ case E_intmax:
+ value = va_arg( status->arg, uintmax_t );
+ break;
+ default:
+ puts( "UNSUPPORTED PRINTF FLAG COMBINATION" );
+ return NULL;
+ }
+ INT2BASE();
+ }
+ else
+ {
+ intmax_t value;
+ switch ( status->flags & ( E_char | E_short | E_long | E_llong | E_intmax ) )
+ {
+ case E_char:
+ value = (intmax_t)(char)va_arg( status->arg, int );
+ break;
+ case E_short:
+ value = (intmax_t)(short)va_arg( status->arg, int );
+ break;
+ case 0:
+ value = (intmax_t)va_arg( status->arg, int );
+ break;
+ case E_long:
+ value = (intmax_t)va_arg( status->arg, long );
+ break;
+ case E_llong:
+ value = (intmax_t)va_arg( status->arg, long long );
+ break;
+ case E_ptrdiff:
+ value = (intmax_t)va_arg( status->arg, ptrdiff_t );
+ break;
+ case E_intmax:
+ value = va_arg( status->arg, intmax_t );
+ break;
+ default:
+ puts( "UNSUPPORTED PRINTF FLAG COMBINATION" );
+ return NULL;
+ }
+ INT2BASE();
+ }
+ if ( status->flags & E_minus )
+ {
+ while ( status->current < status->width )
+ {
+ PUT( ' ' );
+ ++(status->current);
+ }
+ }
+ if ( status->i >= status->n && status->n > 0 )
+ {
+ status->s[status->n - 1] = '\0';
+ }
+ }
+ return ++spec;
+}
+
+#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
+
+int main( void )
+{
+#ifndef REGTEST
+ char target[100];
+#include "printf_testcases.h"
+#endif
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_scan.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_scan.c
new file mode 100644
index 0000000..1f8fd71
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_scan.c
@@ -0,0 +1,639 @@
+/* _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
+
+/* Using an integer's bits as flags for both the conversion flags and length
+ modifiers.
+*/
+#define E_suppressed 1<<0
+#define E_char 1<<6
+#define E_short 1<<7
+#define E_long 1<<8
+#define E_llong 1<<9
+#define E_intmax 1<<10
+#define E_size 1<<11
+#define E_ptrdiff 1<<12
+#define E_pointer 1<<13
+#define E_ldouble 1<<14
+#define E_unsigned 1<<16
+
+
+/* Helper function to get a character from the string or stream, whatever is
+ used for input. When reading from a string, returns EOF on end-of-string
+ so that handling of the return value can be uniform for both streams and
+ strings.
+*/
+static int GET( struct _PDCLIB_status_t * status )
+{
+ int rc = EOF;
+ if ( status->stream != NULL )
+ {
+ rc = getc( status->stream );
+ }
+ else
+ {
+ rc = ( *status->s == '\0' ) ? EOF : (unsigned char)*((status->s)++);
+ }
+ if ( rc != EOF )
+ {
+ ++(status->i);
+ ++(status->current);
+ }
+ return rc;
+}
+
+
+/* Helper function to put a read character back into the string or stream,
+ whatever is used for input.
+*/
+static void UNGET( int c, struct _PDCLIB_status_t * status )
+{
+ if ( status->stream != NULL )
+ {
+ ungetc( c, status->stream ); /* TODO: Error? */
+ }
+ else
+ {
+ --(status->s);
+ }
+ --(status->i);
+ --(status->current);
+}
+
+
+/* Helper function to check if a character is part of a given scanset */
+static int IN_SCANSET( const char * scanlist, const char * end_scanlist, int rc )
+{
+ /* SOLAR */
+ int previous = -1;
+ while ( scanlist != end_scanlist )
+ {
+ if ( ( *scanlist == '-' ) && ( previous != -1 ) )
+ {
+ /* possible scangroup ("a-z") */
+ if ( ++scanlist == end_scanlist )
+ {
+ /* '-' at end of scanlist does not describe a scangroup */
+ return rc == '-';
+ }
+ while ( ++previous <= (unsigned char)*scanlist )
+ {
+ if ( previous == rc )
+ {
+ return 1;
+ }
+ }
+ previous = -1;
+ }
+ else
+ {
+ /* not a scangroup, check verbatim */
+ if ( rc == (unsigned char)*scanlist )
+ {
+ return 1;
+ }
+ previous = (unsigned char)(*scanlist++);
+ }
+ }
+ return 0;
+}
+
+
+const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
+{
+ /* generic input character */
+ int rc;
+ const char * prev_spec;
+ const char * orig_spec = spec;
+ int value_parsed;
+ if ( *(++spec) == '%' )
+ {
+ /* %% -> match single '%' */
+ rc = GET( status );
+ switch ( rc )
+ {
+ case EOF:
+ /* input error */
+ if ( status->n == 0 )
+ {
+ status->n = -1;
+ }
+ return NULL;
+ case '%':
+ return ++spec;
+ default:
+ UNGET( rc, status );
+ break;
+ }
+ }
+ /* Initializing status structure */
+ status->flags = 0;
+ status->base = -1;
+ status->current = 0;
+ status->width = 0;
+ status->prec = 0;
+
+ /* '*' suppresses assigning parsed value to variable */
+ if ( *spec == '*' )
+ {
+ status->flags |= E_suppressed;
+ ++spec;
+ }
+
+ /* If a width is given, strtol() will return its value. If not given,
+ strtol() will return zero. In both cases, endptr will point to the
+ rest of the conversion specifier - just what we need.
+ */
+ prev_spec = spec;
+ status->width = (int)strtol( spec, (char**)&spec, 10 );
+ if ( spec == prev_spec )
+ {
+ status->width = SIZE_MAX;
+ }
+
+ /* Optional length modifier
+ We step one character ahead in any case, and step back only if we find
+ there has been no length modifier (or step ahead another character if it
+ has been "hh" or "ll").
+ */
+ switch ( *(spec++) )
+ {
+ case 'h':
+ if ( *spec == 'h' )
+ {
+ /* hh -> char */
+ status->flags |= E_char;
+ ++spec;
+ }
+ else
+ {
+ /* h -> short */
+ status->flags |= E_short;
+ }
+ break;
+ case 'l':
+ if ( *spec == 'l' )
+ {
+ /* ll -> long long */
+ status->flags |= E_llong;
+ ++spec;
+ }
+ else
+ {
+ /* l -> long */
+ status->flags |= E_long;
+ }
+ break;
+ case 'j':
+ /* j -> intmax_t, which might or might not be long long */
+ status->flags |= E_intmax;
+ break;
+ case 'z':
+ /* z -> size_t, which might or might not be unsigned int */
+ status->flags |= E_size;
+ break;
+ case 't':
+ /* t -> ptrdiff_t, which might or might not be long */
+ status->flags |= E_ptrdiff;
+ break;
+ case 'L':
+ /* L -> long double */
+ status->flags |= E_ldouble;
+ break;
+ default:
+ --spec;
+ break;
+ }
+
+ /* Conversion specifier */
+
+ /* whether valid input had been parsed */
+ value_parsed = 0;
+
+ switch ( *spec )
+ {
+ case 'd':
+ status->base = 10;
+ break;
+ case 'i':
+ status->base = 0;
+ break;
+ case 'o':
+ status->base = 8;
+ status->flags |= E_unsigned;
+ break;
+ case 'u':
+ status->base = 10;
+ status->flags |= E_unsigned;
+ break;
+ case 'x':
+ status->base = 16;
+ status->flags |= E_unsigned;
+ break;
+ case 'f':
+ case 'F':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ case 'a':
+ case 'A':
+ break;
+ case 'c':
+ {
+ char * c = va_arg( status->arg, char * );
+ /* for %c, default width is one */
+ if ( status->width == SIZE_MAX )
+ {
+ status->width = 1;
+ }
+ /* reading until width reached or input exhausted */
+ while ( ( status->current < status->width ) &&
+ ( ( rc = GET( status ) ) != EOF ) )
+ {
+ *(c++) = rc;
+ value_parsed = 1;
+ }
+ /* width or input exhausted */
+ if ( value_parsed )
+ {
+ ++status->n;
+ return ++spec;
+ }
+ else
+ {
+ /* input error, no character read */
+ if ( status->n == 0 )
+ {
+ status->n = -1;
+ }
+ return NULL;
+ }
+ }
+ case 's':
+ {
+ char * c = va_arg( status->arg, char * );
+ while ( ( status->current < status->width ) &&
+ ( ( rc = GET( status ) ) != EOF ) )
+ {
+ if ( isspace( rc ) )
+ {
+ UNGET( rc, status );
+ if ( value_parsed )
+ {
+ /* matching sequence terminated by whitespace */
+ *c = '\0';
+ ++status->n;
+ return ++spec;
+ }
+ else
+ {
+ /* matching error */
+ return NULL;
+ }
+ }
+ else
+ {
+ /* match */
+ value_parsed = 1;
+ *(c++) = rc;
+ }
+ }
+ /* width or input exhausted */
+ if ( value_parsed )
+ {
+ *c = '\0';
+ ++status->n;
+ return ++spec;
+ }
+ else
+ {
+ /* input error, no character read */
+ if ( status->n == 0 )
+ {
+ status->n = -1;
+ }
+ return NULL;
+ }
+ }
+ case '[':
+ {
+ const char * endspec = spec;
+ int negative_scanlist = 0;
+ char * c;
+ if ( *(++endspec) == '^' )
+ {
+ negative_scanlist = 1;
+ ++endspec;
+ }
+ spec = endspec;
+ do
+ {
+ /* TODO: This can run beyond a malformed format string */
+ ++endspec;
+ } while ( *endspec != ']' );
+ /* read according to scanlist, equiv. to %s above */
+ c = va_arg( status->arg, char * );
+ while ( ( status->current < status->width ) &&
+ ( ( rc = GET( status ) ) != EOF ) )
+ {
+ if ( negative_scanlist )
+ {
+ if ( IN_SCANSET( spec, endspec, rc ) )
+ {
+ UNGET( rc, status );
+ break;
+ }
+ }
+ else
+ {
+ if ( ! IN_SCANSET( spec, endspec, rc ) )
+ {
+ UNGET( rc, status );
+ break;
+ }
+ }
+ value_parsed = 1;
+ *(c++) = rc;
+ }
+ if ( value_parsed )
+ {
+ *c = '\0';
+ ++status->n;
+ return ++endspec;
+ }
+ else
+ {
+ if ( rc == EOF )
+ {
+ status->n = -1;
+ }
+ return NULL;
+ }
+ }
+ case 'p':
+ status->base = 16;
+ status->flags |= E_pointer;
+ break;
+ case 'n':
+ {
+ int * val = va_arg( status->arg, int * );
+ *val = status->i;
+ return ++spec;
+ }
+ default:
+ /* No conversion specifier. Bad conversion. */
+ return orig_spec;
+ }
+
+ if ( status->base != -1 )
+ {
+ /* integer conversion */
+ uintmax_t value = 0; /* absolute value read */
+ int prefix_parsed = 0;
+ int sign = 0;
+ while ( ( status->current < status->width ) &&
+ ( ( rc = GET( status ) ) != EOF ) )
+ {
+ if ( isspace( rc ) )
+ {
+ if ( sign )
+ {
+ /* matching sequence terminated by whitespace */
+ UNGET( rc, status );
+ break;
+ }
+ else
+ {
+ /* leading whitespace not counted against width */
+ status->current--;
+ }
+ }
+ else if ( ! sign )
+ {
+ /* no sign parsed yet */
+ switch ( rc )
+ {
+ case '-':
+ sign = -1;
+ break;
+ case '+':
+ sign = 1;
+ break;
+ default:
+ /* not a sign; put back character */
+ sign = 1;
+ UNGET( rc, status );
+ break;
+ }
+ }
+ else if ( ! prefix_parsed )
+ {
+ /* no prefix (0x... for hex, 0... for octal) parsed yet */
+ prefix_parsed = 1;
+ if ( rc != '0' )
+ {
+ /* not a prefix; if base not yet set, set to decimal */
+ if ( status->base == 0 )
+ {
+ status->base = 10;
+ }
+ UNGET( rc, status );
+ }
+ else
+ {
+ /* starts with zero, so it might be a prefix. */
+ /* check what follows next (might be 0x...) */
+ if ( ( status->current < status->width ) &&
+ ( ( rc = GET( status ) ) != EOF ) )
+ {
+ if ( tolower( rc ) == 'x' )
+ {
+ /* 0x... would be prefix for hex base... */
+ if ( ( status->base == 0 ) ||
+ ( status->base == 16 ) )
+ {
+ status->base = 16;
+ }
+ else
+ {
+ /* ...unless already set to other value */
+ UNGET( rc, status );
+ value_parsed = 1;
+ }
+ }
+ else
+ {
+ /* 0... but not 0x.... would be octal prefix */
+ UNGET( rc, status );
+ if ( status->base == 0 )
+ {
+ status->base = 8;
+ }
+ /* in any case we have read a zero */
+ value_parsed = 1;
+ }
+ }
+ else
+ {
+ /* failed to read beyond the initial zero */
+ value_parsed = 1;
+ break;
+ }
+ }
+ }
+ else
+ {
+ char * digitptr = memchr( _PDCLIB_digits, tolower( rc ), status->base );
+ if ( digitptr == NULL )
+ {
+ /* end of input item */
+ UNGET( rc, status );
+ break;
+ }
+ value *= status->base;
+ value += digitptr - _PDCLIB_digits;
+ value_parsed = 1;
+ }
+ }
+ /* width or input exhausted, or non-matching character */
+ if ( ! value_parsed )
+ {
+ /* out of input before anything could be parsed - input error */
+ /* FIXME: if first character does not match, value_parsed is not set - but it is NOT an input error */
+ if ( ( status->n == 0 ) && ( rc == EOF ) )
+ {
+ status->n = -1;
+ }
+ return NULL;
+ }
+ /* convert value to target type and assign to parameter */
+ if ( ! ( status->flags & E_suppressed ) )
+ {
+ switch ( status->flags & ( E_char | E_short | E_long | E_llong |
+ E_intmax | E_size | E_ptrdiff | E_pointer |
+ E_unsigned ) )
+ {
+ case E_char:
+ *( va_arg( status->arg, char * ) ) = (char)( value * sign );
+ break;
+ case E_char | E_unsigned:
+ *( va_arg( status->arg, unsigned char * ) ) = (unsigned char)( value * sign );
+ break;
+
+ case E_short:
+ *( va_arg( status->arg, short * ) ) = (short)( value * sign );
+ break;
+ case E_short | E_unsigned:
+ *( va_arg( status->arg, unsigned short * ) ) = (unsigned short)( value * sign );
+ break;
+
+ case 0:
+ *( va_arg( status->arg, int * ) ) = (int)( value * sign );
+ break;
+ case E_unsigned:
+ *( va_arg( status->arg, unsigned int * ) ) = (unsigned int)( value * sign );
+ break;
+
+ case E_long:
+ *( va_arg( status->arg, long * ) ) = (long)( value * sign );
+ break;
+ case E_long | E_unsigned:
+ *( va_arg( status->arg, unsigned long * ) ) = (unsigned long)( value * sign );
+ break;
+
+ case E_llong:
+ *( va_arg( status->arg, long long * ) ) = (long long)( value * sign );
+ break;
+ case E_llong | E_unsigned:
+ *( va_arg( status->arg, unsigned long long * ) ) = (unsigned long long)( value * sign );
+ break;
+
+ case E_intmax:
+ *( va_arg( status->arg, intmax_t * ) ) = (intmax_t)( value * sign );
+ break;
+ case E_intmax | E_unsigned:
+ *( va_arg( status->arg, uintmax_t * ) ) = (uintmax_t)( value * sign );
+ break;
+
+ case E_size:
+ /* E_size always implies unsigned */
+ *( va_arg( status->arg, size_t * ) ) = (size_t)( value * sign );
+ break;
+
+ case E_ptrdiff:
+ /* E_ptrdiff always implies signed */
+ *( va_arg( status->arg, ptrdiff_t * ) ) = (ptrdiff_t)( value * sign );
+ break;
+
+ case E_pointer:
+ /* E_pointer always implies unsigned */
+ *( uintptr_t* )( va_arg( status->arg, void * ) ) = (uintptr_t)( value * sign );
+ break;
+
+ default:
+ puts( "UNSUPPORTED SCANF FLAG COMBINATION" );
+ return NULL; /* behaviour unspecified */
+ }
+ ++(status->n);
+ }
+ return ++spec;
+ }
+ /* TODO: Floats. */
+ return NULL;
+}
+
+#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;
+ status.n = 0;
+ status.i = 0;
+ status.s = (char *)s;
+ status.stream = NULL;
+ va_start( status.arg, format );
+ if ( *(_PDCLIB_scan( format, &status )) != '\0' )
+ {
+ printf( "_PDCLIB_scan() did not return end-of-specifier on '%s'.\n", format );
+ ++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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_seed.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_seed.c
new file mode 100644
index 0000000..ce7c31c
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_seed.c
@@ -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
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_strtox_main.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_strtox_main.c
new file mode 100644
index 0000000..4808952
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_strtox_main.c
@@ -0,0 +1,88 @@
+/* _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 limval, int limdigit, char * sign )
+{
+ _PDCLIB_uintmax_t rc = 0;
+ int digit = -1;
+ const char * x;
+ while ( ( x = memchr( _PDCLIB_digits, tolower(**p), base ) ) != NULL )
+ {
+ digit = x - _PDCLIB_digits;
+ if ( ( rc < limval ) || ( ( rc == limval ) && ( digit <= limdigit ) ) )
+ {
+ rc = rc * base + (unsigned)digit;
+ ++(*p);
+ }
+ else
+ {
+ errno = ERANGE;
+ /* TODO: Only if endptr != NULL - but do we really want *another* parameter? */
+ /* TODO: Earlier version was missing tolower() here but was not caught by tests */
+ while ( memchr( _PDCLIB_digits, tolower(**p), base ) != NULL ) ++(*p);
+ /* TODO: This is ugly, but keeps caller from negating the error value */
+ *sign = '+';
+ return error;
+ }
+ }
+ if ( digit == -1 )
+ {
+ *p = NULL;
+ return 0;
+ }
+ return rc;
+}
+
+#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)12, 3, &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)12, 3, &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)1, 2, &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)99, 8, &sign ) == 0 );
+ TESTCASE( p == NULL );
+#endif
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/_PDCLIB/_PDCLIB_strtox_prelim.c b/src/pdclib/functions/_PDCLIB/_PDCLIB_strtox_prelim.c
new file mode 100644
index 0000000..6e16b35
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/_PDCLIB_strtox_prelim.c
@@ -0,0 +1,94 @@
+/* _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( *p ) ) ++p;
+ /* determining / skipping sign */
+ if ( *p != '+' && *p != '-' ) *sign = '+';
+ else *sign = *(p++);
+ /* determining base */
+ if ( *p == '0' )
+ {
+ ++p;
+ if ( ( *base == 0 || *base == 16 ) && ( *p == 'x' || *p == 'X' ) )
+ {
+ *base = 16;
+ ++p;
+ /* catching a border case here: "0x" followed by a non-digit should
+ be parsed as the unprefixed zero.
+ We have to "rewind" the parsing; having the base set to 16 if it
+ was zero previously does not hurt, as the result is zero anyway.
+ */
+ if ( memchr( _PDCLIB_digits, tolower(*p), *base ) == NULL )
+ {
+ p -= 2;
+ }
+ }
+ else if ( *base == 0 )
+ {
+ *base = 8;
+ }
+ else
+ {
+ --p;
+ }
+ }
+ else if ( ! *base )
+ {
+ *base = 10;
+ }
+ return ( ( *base >= 2 ) && ( *base <= 36 ) ) ? p : NULL;
+}
+
+#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[3] );
+ 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
diff --git a/src/pdclib/functions/_PDCLIB/assert.c b/src/pdclib/functions/_PDCLIB/assert.c
new file mode 100644
index 0000000..f84265f
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/assert.c
@@ -0,0 +1,71 @@
+/* _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
+
+#include "pdclib/_PDCLIB_aux.h"
+
+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 );
+}
+
+#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
diff --git a/src/pdclib/functions/_PDCLIB/errno.c b/src/pdclib/functions/_PDCLIB/errno.c
new file mode 100644
index 0000000..13270fc
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/errno.c
@@ -0,0 +1,37 @@
+/* _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_int.h"
+
+int _PDCLIB_errno = 0;
+
+int * _PDCLIB_errno_func()
+{
+ return &_PDCLIB_errno;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+#include <errno.h>
+
+int main( void )
+{
+ errno = 0;
+ TESTCASE( errno == 0 );
+ errno = EDOM;
+ TESTCASE( errno == EDOM );
+ errno = ERANGE;
+ TESTCASE( errno == ERANGE );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/_PDCLIB/stdarg.c b/src/pdclib/functions/_PDCLIB/stdarg.c
new file mode 100644
index 0000000..7ad1087
--- /dev/null
+++ b/src/pdclib/functions/_PDCLIB/stdarg.c
@@ -0,0 +1,115 @@
+/* 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 );
+
+enum tag_t
+{
+ TAG_END,
+ TAG_INT,
+ TAG_LONG,
+ TAG_LLONG,
+ TAG_DBL,
+ TAG_LDBL,
+ TAG_INTPTR,
+ TAG_LDBLPTR,
+ TAG_FUNCPTR
+};
+
+static int dummy( void )
+{
+ return INT_MAX;
+}
+
+static int test( enum tag_t s, ... )
+{
+ enum tag_t tag = s;
+ va_list ap;
+ va_start( ap, s );
+ for (;;)
+ {
+ switch ( tag )
+ {
+ case TAG_INT:
+ {
+ TESTCASE( va_arg( ap, int ) == INT_MAX );
+ tag = va_arg( ap, enum tag_t );
+ break;
+ }
+ case TAG_LONG:
+ {
+ TESTCASE( va_arg( ap, long ) == LONG_MAX );
+ tag = va_arg( ap, enum tag_t );
+ break;
+ }
+ case TAG_LLONG:
+ {
+ TESTCASE( va_arg( ap, long long ) == LLONG_MAX );
+ tag = va_arg( ap, enum tag_t );
+ break;
+ }
+ case TAG_DBL:
+ {
+ TESTCASE( va_arg( ap, double ) == DBL_MAX );
+ tag = va_arg( ap, enum tag_t );
+ break;
+ }
+ case TAG_LDBL:
+ {
+ TESTCASE( va_arg( ap, long double ) == LDBL_MAX );
+ tag = va_arg( ap, enum tag_t );
+ break;
+ }
+ case TAG_INTPTR:
+ {
+ TESTCASE( *( va_arg( ap, int * ) ) == INT_MAX );
+ tag = va_arg( ap, enum tag_t );
+ break;
+ }
+ case TAG_LDBLPTR:
+ {
+ TESTCASE( *( va_arg( ap, long double * ) ) == LDBL_MAX );
+ tag = va_arg( ap, enum tag_t );
+ break;
+ }
+ case TAG_FUNCPTR:
+ {
+ intfunc_t function;
+ TESTCASE( ( function = va_arg( ap, intfunc_t ) ) == dummy );
+ TESTCASE( function() == INT_MAX );
+ tag = va_arg( ap, enum tag_t );
+ 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