]> pd.if.org Git - pdclib/commitdiff
Getting closer to scan().
authorsolar <unknown>
Tue, 15 Sep 2009 04:30:12 +0000 (04:30 +0000)
committersolar <unknown>
Tue, 15 Sep 2009 04:30:12 +0000 (04:30 +0000)
functions/_PDCLIB/scan.c
functions/ctype/isspace.c [new file with mode: 0644]
functions/ctype/tolower.c [new file with mode: 0644]
functions/stdio/vsscanf.c
includes/ctype.h [new file with mode: 0644]
internals/_PDCLIB_int.h
platform/example_64/internals/_PDCLIB_config.h

index d12e8844a06e9eebc712cc68f522a5afbdc026e0..1502f62ba5cc6c489fcc2e94b046cfbefea6987e 100644 (file)
 */
 
 #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
diff --git a/functions/ctype/isspace.c b/functions/ctype/isspace.c
new file mode 100644 (file)
index 0000000..346167e
--- /dev/null
@@ -0,0 +1,47 @@
+/* $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
diff --git a/functions/ctype/tolower.c b/functions/ctype/tolower.c
new file mode 100644 (file)
index 0000000..28c435d
--- /dev/null
@@ -0,0 +1,37 @@
+/* $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
index c4565aada0320a307c06a044991c4acd504ce450..34397ac36407834ff02f63b16de83190fc4db493 100644 (file)
 #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;
diff --git a/includes/ctype.h b/includes/ctype.h
new file mode 100644 (file)
index 0000000..2c8071c
--- /dev/null
@@ -0,0 +1,23 @@
+/* $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
+
index 62c38b25c6ddd221b18043aff68de5157aeed89c..9019f72b4993b6d83db7f0f14a062148c8bca559 100644 (file)
@@ -317,10 +317,12 @@ struct _PDCLIB_status_t
 {
     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                   */
index c8aa535e59e8640b396c625839b5ce722c60688a..81fdb09b4d4f4ae929be6abe6a0cdee61466a7f3 100644 (file)
 /* 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  */
@@ -237,6 +229,25 @@ typedef int _PDCLIB_fd_t;
 */
 #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).