*/
#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdarg.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_intptr 1<<13
+#define E_ldouble 1<<14
+#define E_unsigned 1<<16
+
+
+static bool MATCH( const char x, struct _PDCLIB_status_t * status )
+{
+ if ( status->stream != NULL )
+ {
+ /* Matching against stream */
+ if ( status->stream->buffer[ status->stream->bufidx ] == x )
+ {
+ getc( status->stream );
+ ++(status->i);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ /* Matching against string */
+ if ( *(status->s) == x )
+ {
+ ++(status->s);
+ ++(status->i);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
+
const char * _PDCLIB_scan( const char * spec, struct _PDCLIB_status_t * status )
{
- return ++spec;
+ const char * orig_spec = spec;
+ if ( *(++spec) == '%' )
+ {
+ /* %% -> match single '%' */
+ MATCH( *spec, status );
+ return ++spec;
+ }
+ /* Initializing status structure */
+ status->flags = 0;
+ status->base = 0;
+ status->this = 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.
+ */
+ status->width = (int)strtol( spec, (char**)&spec, 10 );
+
+ /* 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 */
+ 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':
+ /* TODO */
+ break;
+ case 's':
+ /* TODO */
+ break;
+ case 'p':
+ /* TODO */
+ status->base = 16;
+ status->flags |= E_unsigned;
+ break;
+ case 'n':
+ {
+ int * val = va_arg( status->arg, int * );
+ *val = status->i;
+ return ++spec;
+ }
+ default:
+ /* No conversion specifier. Bad conversion. */
+ return orig_spec;
+ }
+ /* TODO: Actual conversions */
+ return NULL;
}
#ifdef TEST
--- /dev/null
+/* $Id$ */
+
+/* isspace( int )
+
+ This file is part of the Public Domain C Library (PDCLib).
+ Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+#include <ctype.h>
+#include <stdbool.h>
+
+#ifndef REGTEST
+
+int isspace( int c )
+{
+ switch ( c )
+ {
+ case ' ':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ return true;
+ default:
+ return false;
+ }
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+ TESTCASE( isspace( ' ' ) );
+ TESTCASE( isspace( '\f' ) );
+ TESTCASE( isspace( '\n' ) );
+ TESTCASE( isspace( '\r' ) );
+ TESTCASE( isspace( '\t' ) );
+ TESTCASE( isspace( '\v' ) );
+ TESTCASE( ! isspace( 'a' ) );
+ return TEST_RESULTS;
+}
+
+#endif
--- /dev/null
+/* $Id$ */
+
+/* tolower( int )
+
+ This file is part of the Public Domain C Library (PDCLib).
+ Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+#include <ctype.h>
+
+#ifndef REGTEST
+
+int tolower( int c )
+{
+ if ( ( c >= 'A' ) && ( c <= 'Z' ) )
+ {
+ c += ( 'a' - 'A' );
+ }
+ return c;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+ TESTCASE( tolower( 'A' ) == 'a' );
+ TESTCASE( tolower( 'Z' ) == 'z' );
+ TESTCASE( tolower( 'a' ) == 'a' );
+ TESTCASE( tolower( 'z' ) == 'z' );
+ TESTCASE( tolower( '@' ) == '@' );
+ TESTCASE( tolower( '[' ) == '[' );
+ return TEST_RESULTS;
+}
+#endif
#include <stdarg.h>
#ifndef REGTEST
+#include <ctype.h>
int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, va_list arg )
{
struct _PDCLIB_status_t status;
status.base = 0;
status.flags = 0;
- /* In _PDCLIB_print, status.n holds the maximum number of characters to be
- written. As we don't need that for the scanf() functions, we (ab)use
- this field to hold the number of matching conversion specifiers.
- */
status.n = 0;
status.i = 0;
status.this = 0;
- /* In _PDCLIB_print, status.s is the string *printed to*. In the scanf()
- functions, we (ab)use this field to hold the string *scanned from*.
- */
status.s = (char *)s;
status.width = 0;
status.prec = 0;
--- /dev/null
+/* $Id$ */
+
+/* 7.4 Character handling <ctype.h>
+
+ This file is part of the Public Domain C Library (PDCLib).
+ Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+#ifndef _PDCLIB_CTYPE_H
+#define _PDCLIB_CTYPE_H _PDCLIB_CTYPE_H
+
+/* ------------------------------------------------------------------------- */
+/* THIS IS A STUB - THIS IS A STUB - THIS IS A STUB - THIS IS A STUB */
+/* ------------------------------------------------------------------------- */
+/* This implements two functions that are required by <stdlib.h> / <stdio.h> */
+/* for the C locale only. Will be replaced in v0.6 by something compliant. */
+/* ------------------------------------------------------------------------- */
+
+int tolower( int c );
+int isspace( int c );
+
+#endif
+
{
int base; /* base to which the value shall be converted */
_PDCLIB_int_fast32_t flags; /* flags and length modifiers */
- _PDCLIB_size_t n; /* maximum number of characters to be written */
+ _PDCLIB_size_t n; /* print: maximum characters to be written */
+ /* scan: number matched conversion specifiers */
_PDCLIB_size_t i; /* number of characters already written */
_PDCLIB_size_t this; /* output chars in the current conversion */
- char * s; /* target buffer */
+ char * s; /* print: target buffer */
+ /* scan: source string */
_PDCLIB_size_t width; /* width of current field */
_PDCLIB_size_t prec; /* precision of current field */
struct _PDCLIB_file_t * stream;/* for to-stream output */
/* The character (sequence) your platform uses as newline. */
#define _PDCLIB_endl "\n"
-/* The number of attempts to complete an I/O operation before giving up. */
-/* (Example: How often a buffer flushing is attempted before reporting fail.) */
-#define _PDCLIB_IO_RETRIES 1
-
-/* What the system should do after an I/O operation did not succeed, before */
-/* trying again. (Empty by default.) */
-#define _PDCLIB_IO_RETRY_OP( stream )
-
/* exit() can signal success to the host environment by the value of zero or */
/* the constant EXIT_SUCCESS. Failure is signaled by EXIT_FAILURE. Note that */
/* any other return value is "implementation-defined", i.e. your environment */
*/
#define _PDCLIB_NOHANDLE ( (_PDCLIB_fd_t) -1 )
+/* The default size for file buffers. Must be at least 256. */
+#define _PDCLIB_BUFSIZ 1024
+
+/* The minimum number of files the implementation can open simultaneously. Must
+ be at least 8. Depends largely on how the bookkeeping is done by fopen() /
+ freopen() / fclose(). The example implementation limits the number of open
+ files only by available memory.
+*/
+#define _PDCLIB_FOPEN_MAX 8
+
+/* Length of the longest filename the implementation guarantees to support. */
+#define _PDCLIB_FILENAME_MAX 128
+
+/* Buffer size for tmpnam(). */
+#define _PDCLIB_L_tmpnam 100
+
+/* Number of distinct file names that can be generated by tmpnam(). */
+#define _PDCLIB_TMP_MAX 50
+
/* The values of SEEK_SET, SEEK_CUR and SEEK_END, used by fseek().
Since at least one platform (POSIX) uses the same symbols for its own "seek"
function, we use whatever the host defines (if it does define them).