mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[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:
10
src/libraries/libc/j6libc/Readme.txt
Normal file
10
src/libraries/libc/j6libc/Readme.txt
Normal 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).
|
||||
16
src/libraries/libc/j6libc/allocpages.c
Normal file
16
src/libraries/libc/j6libc/allocpages.c
Normal 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;
|
||||
}
|
||||
19
src/libraries/libc/j6libc/assert.c
Normal file
19
src/libraries/libc/j6libc/assert.c
Normal 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();
|
||||
}
|
||||
25
src/libraries/libc/j6libc/atomax.c
Normal file
25
src/libraries/libc/j6libc/atomax.c
Normal 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;
|
||||
}
|
||||
16
src/libraries/libc/j6libc/close.c
Normal file
16
src/libraries/libc/j6libc/close.c
Normal 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;
|
||||
}
|
||||
21
src/libraries/libc/j6libc/closeall.c
Normal file
21
src/libraries/libc/j6libc/closeall.c
Normal 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;
|
||||
}
|
||||
}
|
||||
12
src/libraries/libc/j6libc/digits.c
Normal file
12
src/libraries/libc/j6libc/digits.c
Normal 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";
|
||||
14
src/libraries/libc/j6libc/errno.c
Normal file
14
src/libraries/libc/j6libc/errno.c
Normal 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;
|
||||
}
|
||||
54
src/libraries/libc/j6libc/filemode.c
Normal file
54
src/libraries/libc/j6libc/filemode.c
Normal 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;
|
||||
}
|
||||
19
src/libraries/libc/j6libc/fillbuffer.c
Normal file
19
src/libraries/libc/j6libc/fillbuffer.c
Normal 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;
|
||||
}
|
||||
19
src/libraries/libc/j6libc/flushbuffer.c
Normal file
19
src/libraries/libc/j6libc/flushbuffer.c
Normal 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;
|
||||
}
|
||||
14
src/libraries/libc/j6libc/is_leap.c
Normal file
14
src/libraries/libc/j6libc/is_leap.c
Normal 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 ) );
|
||||
}
|
||||
44
src/libraries/libc/j6libc/load_lc_collate.c
Normal file
44
src/libraries/libc/j6libc/load_lc_collate.c
Normal 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;
|
||||
}
|
||||
74
src/libraries/libc/j6libc/load_lc_ctype.c
Normal file
74
src/libraries/libc/j6libc/load_lc_ctype.c
Normal 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;
|
||||
}
|
||||
60
src/libraries/libc/j6libc/load_lc_messages.c
Normal file
60
src/libraries/libc/j6libc/load_lc_messages.c
Normal 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;
|
||||
}
|
||||
90
src/libraries/libc/j6libc/load_lc_monetary.c
Normal file
90
src/libraries/libc/j6libc/load_lc_monetary.c
Normal 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;
|
||||
}
|
||||
56
src/libraries/libc/j6libc/load_lc_numeric.c
Normal file
56
src/libraries/libc/j6libc/load_lc_numeric.c
Normal 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;
|
||||
}
|
||||
79
src/libraries/libc/j6libc/load_lc_time.c
Normal file
79
src/libraries/libc/j6libc/load_lc_time.c
Normal 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;
|
||||
}
|
||||
48
src/libraries/libc/j6libc/load_lines.c
Normal file
48
src/libraries/libc/j6libc/load_lines.c
Normal 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;
|
||||
}
|
||||
17
src/libraries/libc/j6libc/open.c
Normal file
17
src/libraries/libc/j6libc/open.c
Normal 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;
|
||||
}
|
||||
34
src/libraries/libc/j6libc/prepread.c
Normal file
34
src/libraries/libc/j6libc/prepread.c
Normal 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;
|
||||
}
|
||||
}
|
||||
25
src/libraries/libc/j6libc/prepwrite.c
Normal file
25
src/libraries/libc/j6libc/prepwrite.c
Normal 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;
|
||||
}
|
||||
624
src/libraries/libc/j6libc/print.c
Normal file
624
src/libraries/libc/j6libc/print.c
Normal 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;
|
||||
}
|
||||
18
src/libraries/libc/j6libc/rename.c
Normal file
18
src/libraries/libc/j6libc/rename.c
Normal 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;
|
||||
}
|
||||
4
src/libraries/libc/j6libc/sbrk.c
Normal file
4
src/libraries/libc/j6libc/sbrk.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#include <stdint.h>
|
||||
void *sbrk(intptr_t) __attribute__ ((weak));
|
||||
|
||||
void *sbrk(intptr_t i) { return 0; }
|
||||
595
src/libraries/libc/j6libc/scan.c
Normal file
595
src/libraries/libc/j6libc/scan.c
Normal 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;
|
||||
}
|
||||
7
src/libraries/libc/j6libc/seed.c
Normal file
7
src/libraries/libc/j6libc/seed.c
Normal 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;
|
||||
18
src/libraries/libc/j6libc/seek.c
Normal file
18
src/libraries/libc/j6libc/seek.c
Normal 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;
|
||||
}
|
||||
412
src/libraries/libc/j6libc/stdinit.c
Normal file
412
src/libraries/libc/j6libc/stdinit.c
Normal 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"
|
||||
}
|
||||
};
|
||||
42
src/libraries/libc/j6libc/strtox_main.c
Normal file
42
src/libraries/libc/j6libc/strtox_main.c
Normal 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;
|
||||
}
|
||||
50
src/libraries/libc/j6libc/strtox_prelim.c
Normal file
50
src/libraries/libc/j6libc/strtox_prelim.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user