[libc] Bring libc in-tree

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,25 @@
/* _PDCLIB_atomax( const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <string.h>
#include <ctype.h>
intmax_t _PDCLIB_atomax( const char * s )
{
intmax_t rc = 0;
char sign = '+';
const char * x;
/* TODO: In other than "C" locale, additional patterns may be defined */
while ( isspace( *s ) ) ++s;
if ( *s == '+' ) ++s;
else if ( *s == '-' ) sign = *(s++);
/* TODO: Earlier version was missing tolower() but was not caught by tests */
while ( ( x = memchr( _PDCLIB_digits, tolower(*(s++)), 10 ) ) != NULL )
{
rc = rc * 10 + ( x - _PDCLIB_digits );
}
return ( sign == '+' ) ? rc : -rc;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,48 @@
/* _PDCLIB_load_lines( FILE *, size_t )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include <stdlib.h>
char * _PDCLIB_load_lines( FILE * fh, size_t lines )
{
size_t required = 0;
long pos = ftell( fh );
char * rc = NULL;
int c;
/* Count the number of characters */
while ( lines && ( c = fgetc( fh ) ) != EOF )
{
if ( c == '\n' )
{
--lines;
}
++required;
}
if ( ! feof( fh ) )
{
if ( ( rc = malloc( required ) ) != NULL )
{
size_t i;
fseek( fh, pos, SEEK_SET );
fread( rc, 1, required, fh );
for ( i = 0; i < required; ++i )
{
if ( rc[ i ] == '\n' )
{
rc[ i ] = '\0';
}
}
}
}
return rc;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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