aboutsummaryrefslogtreecommitdiffstats
path: root/src/pdclib/functions/string
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdclib/functions/string')
-rw-r--r--src/pdclib/functions/string/memchr.c41
-rw-r--r--src/pdclib/functions/string/memcmp.c43
-rw-r--r--src/pdclib/functions/string/memcpy.c40
-rw-r--r--src/pdclib/functions/string/memmove.c52
-rw-r--r--src/pdclib/functions/string/memset.c40
-rw-r--r--src/pdclib/functions/string/strcat.c46
-rw-r--r--src/pdclib/functions/string/strchr.c40
-rw-r--r--src/pdclib/functions/string/strcmp.c41
-rw-r--r--src/pdclib/functions/string/strcoll.c46
-rw-r--r--src/pdclib/functions/string/strcpy.c37
-rw-r--r--src/pdclib/functions/string/strcspn.c50
-rw-r--r--src/pdclib/functions/string/strerror.c41
-rw-r--r--src/pdclib/functions/string/strlen.c34
-rw-r--r--src/pdclib/functions/string/strncat.c60
-rw-r--r--src/pdclib/functions/string/strncmp.c54
-rw-r--r--src/pdclib/functions/string/strncpy.c56
-rw-r--r--src/pdclib/functions/string/strpbrk.c49
-rw-r--r--src/pdclib/functions/string/strrchr.c41
-rw-r--r--src/pdclib/functions/string/strspn.c49
-rw-r--r--src/pdclib/functions/string/strstr.c51
-rw-r--r--src/pdclib/functions/string/strtok.c107
-rw-r--r--src/pdclib/functions/string/strxfrm.c50
22 files changed, 1068 insertions, 0 deletions
diff --git a/src/pdclib/functions/string/memchr.c b/src/pdclib/functions/string/memchr.c
new file mode 100644
index 0000000..29598a7
--- /dev/null
+++ b/src/pdclib/functions/string/memchr.c
@@ -0,0 +1,41 @@
+/* memchr( const void *, int, 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 <string.h>
+
+#ifndef REGTEST
+
+void * memchr( const void * s, int c, size_t n )
+{
+ const unsigned char * p = (const unsigned char *) s;
+ while ( n-- )
+ {
+ if ( *p == (unsigned char) c )
+ {
+ return (void *) p;
+ }
+ ++p;
+ }
+ return NULL;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ TESTCASE( memchr( abcde, 'c', 5 ) == &abcde[2] );
+ TESTCASE( memchr( abcde, 'a', 1 ) == &abcde[0] );
+ TESTCASE( memchr( abcde, 'a', 0 ) == NULL );
+ TESTCASE( memchr( abcde, '\0', 5 ) == NULL );
+ TESTCASE( memchr( abcde, '\0', 6 ) == &abcde[5] );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/memcmp.c b/src/pdclib/functions/string/memcmp.c
new file mode 100644
index 0000000..709b941
--- /dev/null
+++ b/src/pdclib/functions/string/memcmp.c
@@ -0,0 +1,43 @@
+/* memcmp( const void *, const void *, 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 <string.h>
+
+#ifndef REGTEST
+
+int memcmp( const void * s1, const void * s2, size_t n )
+{
+ const unsigned char * p1 = (const unsigned char *) s1;
+ const unsigned char * p2 = (const unsigned char *) s2;
+ while ( n-- )
+ {
+ if ( *p1 != *p2 )
+ {
+ return *p1 - *p2;
+ }
+ ++p1;
+ ++p2;
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ const char xxxxx[] = "xxxxx";
+ TESTCASE( memcmp( abcde, abcdx, 5 ) < 0 );
+ TESTCASE( memcmp( abcde, abcdx, 4 ) == 0 );
+ TESTCASE( memcmp( abcde, xxxxx, 0 ) == 0 );
+ TESTCASE( memcmp( xxxxx, abcde, 1 ) > 0 );
+ return 0;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/memcpy.c b/src/pdclib/functions/string/memcpy.c
new file mode 100644
index 0000000..21ef10e
--- /dev/null
+++ b/src/pdclib/functions/string/memcpy.c
@@ -0,0 +1,40 @@
+/* memcpy( void *, const void *, 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 <string.h>
+
+#ifndef REGTEST
+
+void * memcpy( void * _PDCLIB_restrict s1, const void * _PDCLIB_restrict s2, size_t n )
+{
+ char * dest = (char *) s1;
+ const char * src = (const char *) s2;
+ while ( n-- )
+ {
+ *dest++ = *src++;
+ }
+ return s1;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "xxxxxxxxxxx";
+ TESTCASE( memcpy( s, abcde, 6 ) == s );
+ TESTCASE( s[4] == 'e' );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( memcpy( s + 5, abcde, 5 ) == s + 5 );
+ TESTCASE( s[9] == 'e' );
+ TESTCASE( s[10] == 'x' );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/memmove.c b/src/pdclib/functions/string/memmove.c
new file mode 100644
index 0000000..af89813
--- /dev/null
+++ b/src/pdclib/functions/string/memmove.c
@@ -0,0 +1,52 @@
+/* memmove( void *, const void *, 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 <string.h>
+
+#ifndef REGTEST
+
+void * memmove( void * s1, const void * s2, size_t n )
+{
+ char * dest = (char *) s1;
+ const char * src = (const char *) s2;
+ if ( dest <= src )
+ {
+ while ( n-- )
+ {
+ *dest++ = *src++;
+ }
+ }
+ else
+ {
+ src += n;
+ dest += n;
+ while ( n-- )
+ {
+ *--dest = *--src;
+ }
+ }
+ return s1;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "xxxxabcde";
+ TESTCASE( memmove( s, s + 4, 5 ) == s );
+ TESTCASE( s[0] == 'a' );
+ TESTCASE( s[4] == 'e' );
+ TESTCASE( s[5] == 'b' );
+ TESTCASE( memmove( s + 4, s, 5 ) == s + 4 );
+ TESTCASE( s[4] == 'a' );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/memset.c b/src/pdclib/functions/string/memset.c
new file mode 100644
index 0000000..522ad77
--- /dev/null
+++ b/src/pdclib/functions/string/memset.c
@@ -0,0 +1,40 @@
+/* memset( void *, int, 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 <string.h>
+
+#ifndef REGTEST
+
+void * memset( void * s, int c, size_t n )
+{
+ unsigned char * p = (unsigned char *) s;
+ while ( n-- )
+ {
+ *p++ = (unsigned char) c;
+ }
+ return s;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "xxxxxxxxx";
+ TESTCASE( memset( s, 'o', 10 ) == s );
+ TESTCASE( s[9] == 'o' );
+ TESTCASE( memset( s, '_', 0 ) == s );
+ TESTCASE( s[0] == 'o' );
+ TESTCASE( memset( s, '_', 1 ) == s );
+ TESTCASE( s[0] == '_' );
+ TESTCASE( s[1] == 'o' );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strcat.c b/src/pdclib/functions/string/strcat.c
new file mode 100644
index 0000000..18fd409
--- /dev/null
+++ b/src/pdclib/functions/string/strcat.c
@@ -0,0 +1,46 @@
+/* strcat( 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 <string.h>
+
+#ifndef REGTEST
+
+char * strcat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 )
+{
+ char * rc = s1;
+ if ( *s1 )
+ {
+ while ( *++s1 );
+ }
+ while ( (*s1++ = *s2++) );
+ return rc;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "xx\0xxxxxx";
+ TESTCASE( strcat( s, abcde ) == s );
+ TESTCASE( s[2] == 'a' );
+ TESTCASE( s[6] == 'e' );
+ TESTCASE( s[7] == '\0' );
+ TESTCASE( s[8] == 'x' );
+ s[0] = '\0';
+ TESTCASE( strcat( s, abcdx ) == s );
+ TESTCASE( s[4] == 'x' );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( strcat( s, "\0" ) == s );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( s[6] == 'e' );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strchr.c b/src/pdclib/functions/string/strchr.c
new file mode 100644
index 0000000..621100e
--- /dev/null
+++ b/src/pdclib/functions/string/strchr.c
@@ -0,0 +1,40 @@
+/* strchr( const 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 <string.h>
+
+#ifndef REGTEST
+
+char * strchr( const char * s, int c )
+{
+ do
+ {
+ if ( *s == (char) c )
+ {
+ return (char *) s;
+ }
+ } while ( *s++ );
+ return NULL;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char abccd[] = "abccd";
+ TESTCASE( strchr( abccd, 'x' ) == NULL );
+ TESTCASE( strchr( abccd, 'a' ) == &abccd[0] );
+ TESTCASE( strchr( abccd, 'd' ) == &abccd[4] );
+ TESTCASE( strchr( abccd, '\0' ) == &abccd[5] );
+ TESTCASE( strchr( abccd, 'c' ) == &abccd[2] );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strcmp.c b/src/pdclib/functions/string/strcmp.c
new file mode 100644
index 0000000..639fc10
--- /dev/null
+++ b/src/pdclib/functions/string/strcmp.c
@@ -0,0 +1,41 @@
+/* strcmp( 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 <string.h>
+
+#ifndef REGTEST
+
+int strcmp( const char * s1, const char * s2 )
+{
+ while ( ( *s1 ) && ( *s1 == *s2 ) )
+ {
+ ++s1;
+ ++s2;
+ }
+ return ( *(unsigned char *)s1 - *(unsigned char *)s2 );
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char cmpabcde[] = "abcde";
+ char cmpabcd_[] = "abcd\xfc";
+ char empty[] = "";
+ TESTCASE( strcmp( abcde, cmpabcde ) == 0 );
+ TESTCASE( strcmp( abcde, abcdx ) < 0 );
+ TESTCASE( strcmp( abcdx, abcde ) > 0 );
+ TESTCASE( strcmp( empty, abcde ) < 0 );
+ TESTCASE( strcmp( abcde, empty ) > 0 );
+ TESTCASE( strcmp( abcde, cmpabcd_ ) < 0 );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strcoll.c b/src/pdclib/functions/string/strcoll.c
new file mode 100644
index 0000000..41d466a
--- /dev/null
+++ b/src/pdclib/functions/string/strcoll.c
@@ -0,0 +1,46 @@
+/* strcoll( 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 <string.h>
+
+#ifndef REGTEST
+
+#include <locale.h>
+
+int strcoll( const char * s1, const char * s2 )
+{
+ return strcmp( s1, s2 );
+
+ /* FIXME: This code became invalid when we started doing *real* locales... */
+ /*
+ while ( ( *s1 ) && ( _PDCLIB_lc_ctype[(unsigned char)*s1].collation == _PDCLIB_lc_ctype[(unsigned char)*s2].collation ) )
+ {
+ ++s1;
+ ++s2;
+ }
+ return ( _PDCLIB_lc_ctype[(unsigned char)*s1].collation == _PDCLIB_lc_ctype[(unsigned char)*s2].collation );
+ */
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char cmpabcde[] = "abcde";
+ char empty[] = "";
+ TESTCASE( strcmp( abcde, cmpabcde ) == 0 );
+ TESTCASE( strcmp( abcde, abcdx ) < 0 );
+ TESTCASE( strcmp( abcdx, abcde ) > 0 );
+ TESTCASE( strcmp( empty, abcde ) < 0 );
+ TESTCASE( strcmp( abcde, empty ) > 0 );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strcpy.c b/src/pdclib/functions/string/strcpy.c
new file mode 100644
index 0000000..e0357c8
--- /dev/null
+++ b/src/pdclib/functions/string/strcpy.c
@@ -0,0 +1,37 @@
+/* strcpy( 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 <string.h>
+
+#ifndef REGTEST
+
+char * strcpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 )
+{
+ char * rc = s1;
+ while ( ( *s1++ = *s2++ ) );
+ return rc;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "xxxxx";
+ TESTCASE( strcpy( s, "" ) == s );
+ TESTCASE( s[0] == '\0' );
+ TESTCASE( s[1] == 'x' );
+ TESTCASE( strcpy( s, abcde ) == s );
+ TESTCASE( s[0] == 'a' );
+ TESTCASE( s[4] == 'e' );
+ TESTCASE( s[5] == '\0' );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strcspn.c b/src/pdclib/functions/string/strcspn.c
new file mode 100644
index 0000000..84f8af1
--- /dev/null
+++ b/src/pdclib/functions/string/strcspn.c
@@ -0,0 +1,50 @@
+/* strcspn( 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 <string.h>
+
+#ifndef REGTEST
+
+size_t strcspn( const char * s1, const char * s2 )
+{
+ size_t len = 0;
+ const char * p;
+ while ( s1[len] )
+ {
+ p = s2;
+ while ( *p )
+ {
+ if ( s1[len] == *p++ )
+ {
+ return len;
+ }
+ }
+ ++len;
+ }
+ return len;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ TESTCASE( strcspn( abcde, "x" ) == 5 );
+ TESTCASE( strcspn( abcde, "xyz" ) == 5 );
+ TESTCASE( strcspn( abcde, "zyx" ) == 5 );
+ TESTCASE( strcspn( abcdx, "x" ) == 4 );
+ TESTCASE( strcspn( abcdx, "xyz" ) == 4 );
+ TESTCASE( strcspn( abcdx, "zyx" ) == 4 );
+ TESTCASE( strcspn( abcde, "a" ) == 0 );
+ TESTCASE( strcspn( abcde, "abc" ) == 0 );
+ TESTCASE( strcspn( abcde, "cba" ) == 0 );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strerror.c b/src/pdclib/functions/string/strerror.c
new file mode 100644
index 0000000..4506376
--- /dev/null
+++ b/src/pdclib/functions/string/strerror.c
@@ -0,0 +1,41 @@
+/* strerror( int )
+
+ 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>
+
+#ifndef REGTEST
+
+#include <locale.h>
+
+/* TODO: Doing this via a static array is not the way to do it. */
+char * strerror( int errnum )
+{
+ if ( errnum >= _PDCLIB_ERRNO_MAX )
+ {
+ return (char *)"Unknown error";
+ }
+ else
+ {
+ return _PDCLIB_lc_messages.errno_texts[errnum];
+ }
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+int main( void )
+{
+ TESTCASE( strerror( ERANGE ) != strerror( EDOM ) );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strlen.c b/src/pdclib/functions/string/strlen.c
new file mode 100644
index 0000000..c1a620e
--- /dev/null
+++ b/src/pdclib/functions/string/strlen.c
@@ -0,0 +1,34 @@
+/* strlen( 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>
+
+#ifndef REGTEST
+
+size_t strlen( const char * s )
+{
+ size_t rc = 0;
+ while ( s[rc] )
+ {
+ ++rc;
+ }
+ return rc;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ TESTCASE( strlen( abcde ) == 5 );
+ TESTCASE( strlen( "" ) == 0 );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strncat.c b/src/pdclib/functions/string/strncat.c
new file mode 100644
index 0000000..ba20edc
--- /dev/null
+++ b/src/pdclib/functions/string/strncat.c
@@ -0,0 +1,60 @@
+/* strncat( char *, const char *, 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 <string.h>
+
+#ifndef REGTEST
+
+char * strncat( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n )
+{
+ char * rc = s1;
+ while ( *s1 )
+ {
+ ++s1;
+ }
+ while ( n && ( *s1++ = *s2++ ) )
+ {
+ --n;
+ }
+ if ( n == 0 )
+ {
+ *s1 = '\0';
+ }
+ return rc;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "xx\0xxxxxx";
+ TESTCASE( strncat( s, abcde, 10 ) == s );
+ TESTCASE( s[2] == 'a' );
+ TESTCASE( s[6] == 'e' );
+ TESTCASE( s[7] == '\0' );
+ TESTCASE( s[8] == 'x' );
+ s[0] = '\0';
+ TESTCASE( strncat( s, abcdx, 10 ) == s );
+ TESTCASE( s[4] == 'x' );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( strncat( s, "\0", 10 ) == s );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( s[6] == 'e' );
+ TESTCASE( strncat( s, abcde, 0 ) == s );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( s[6] == 'e' );
+ TESTCASE( strncat( s, abcde, 3 ) == s );
+ TESTCASE( s[5] == 'a' );
+ TESTCASE( s[7] == 'c' );
+ TESTCASE( s[8] == '\0' );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strncmp.c b/src/pdclib/functions/string/strncmp.c
new file mode 100644
index 0000000..4bb3592
--- /dev/null
+++ b/src/pdclib/functions/string/strncmp.c
@@ -0,0 +1,54 @@
+/* strncmp( const char *, const char *, 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 <string.h>
+
+#ifndef REGTEST
+
+int strncmp( const char * s1, const char * s2, size_t n )
+{
+ while ( n && *s1 && ( *s1 == *s2 ) )
+ {
+ ++s1;
+ ++s2;
+ --n;
+ }
+ if ( n == 0 )
+ {
+ return 0;
+ }
+ else
+ {
+ return ( *(unsigned char *)s1 - *(unsigned char *)s2 );
+ }
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char cmpabcde[] = "abcde\0f";
+ char cmpabcd_[] = "abcde\xfc";
+ char empty[] = "";
+ char x[] = "x";
+ TESTCASE( strncmp( abcde, cmpabcde, 5 ) == 0 );
+ TESTCASE( strncmp( abcde, cmpabcde, 10 ) == 0 );
+ TESTCASE( strncmp( abcde, abcdx, 5 ) < 0 );
+ TESTCASE( strncmp( abcdx, abcde, 5 ) > 0 );
+ TESTCASE( strncmp( empty, abcde, 5 ) < 0 );
+ TESTCASE( strncmp( abcde, empty, 5 ) > 0 );
+ TESTCASE( strncmp( abcde, abcdx, 4 ) == 0 );
+ TESTCASE( strncmp( abcde, x, 0 ) == 0 );
+ TESTCASE( strncmp( abcde, x, 1 ) < 0 );
+ TESTCASE( strncmp( abcde, cmpabcd_, 10 ) < 0 );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strncpy.c b/src/pdclib/functions/string/strncpy.c
new file mode 100644
index 0000000..0627c41
--- /dev/null
+++ b/src/pdclib/functions/string/strncpy.c
@@ -0,0 +1,56 @@
+/* strncpy( char *, const char *, 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 <string.h>
+
+#ifndef REGTEST
+
+char * strncpy( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n )
+{
+ char * rc = s1;
+ while ( n && ( *s1++ = *s2++ ) )
+ {
+ /* Cannot do "n--" in the conditional as size_t is unsigned and we have
+ to check it again for >0 in the next loop below, so we must not risk
+ underflow.
+ */
+ --n;
+ }
+ /* Checking against 1 as we missed the last --n in the loop above. */
+ while ( n-- > 1 )
+ {
+ *s1++ = '\0';
+ }
+ return rc;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "xxxxxxx";
+ TESTCASE( strncpy( s, "", 1 ) == s );
+ TESTCASE( s[0] == '\0' );
+ TESTCASE( s[1] == 'x' );
+ TESTCASE( strncpy( s, abcde, 6 ) == s );
+ TESTCASE( s[0] == 'a' );
+ TESTCASE( s[4] == 'e' );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( s[6] == 'x' );
+ TESTCASE( strncpy( s, abcde, 7 ) == s );
+ TESTCASE( s[6] == '\0' );
+ TESTCASE( strncpy( s, "xxxx", 3 ) == s );
+ TESTCASE( s[0] == 'x' );
+ TESTCASE( s[2] == 'x' );
+ TESTCASE( s[3] == 'd' );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strpbrk.c b/src/pdclib/functions/string/strpbrk.c
new file mode 100644
index 0000000..e95f0c1
--- /dev/null
+++ b/src/pdclib/functions/string/strpbrk.c
@@ -0,0 +1,49 @@
+/* strpbrk( 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 <string.h>
+
+#ifndef REGTEST
+
+char * strpbrk( const char * s1, const char * s2 )
+{
+ const char * p1 = s1;
+ const char * p2;
+ while ( *p1 )
+ {
+ p2 = s2;
+ while ( *p2 )
+ {
+ if ( *p1 == *p2++ )
+ {
+ return (char *) p1;
+ }
+ }
+ ++p1;
+ }
+ return NULL;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ TESTCASE( strpbrk( abcde, "x" ) == NULL );
+ TESTCASE( strpbrk( abcde, "xyz" ) == NULL );
+ TESTCASE( strpbrk( abcdx, "x" ) == &abcdx[4] );
+ TESTCASE( strpbrk( abcdx, "xyz" ) == &abcdx[4] );
+ TESTCASE( strpbrk( abcdx, "zyx" ) == &abcdx[4] );
+ TESTCASE( strpbrk( abcde, "a" ) == &abcde[0] );
+ TESTCASE( strpbrk( abcde, "abc" ) == &abcde[0] );
+ TESTCASE( strpbrk( abcde, "cba" ) == &abcde[0] );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strrchr.c b/src/pdclib/functions/string/strrchr.c
new file mode 100644
index 0000000..c2369fa
--- /dev/null
+++ b/src/pdclib/functions/string/strrchr.c
@@ -0,0 +1,41 @@
+/* strrchr( const 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 <string.h>
+
+#ifndef REGTEST
+
+char * strrchr( const char * s, int c )
+{
+ size_t i = 0;
+ while ( s[i++] );
+ do
+ {
+ if ( s[--i] == (char) c )
+ {
+ return (char *) s + i;
+ }
+ } while ( i );
+ return NULL;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char abccd[] = "abccd";
+ TESTCASE( strrchr( abcde, '\0' ) == &abcde[5] );
+ TESTCASE( strrchr( abcde, 'e' ) == &abcde[4] );
+ TESTCASE( strrchr( abcde, 'a' ) == &abcde[0] );
+ TESTCASE( strrchr( abccd, 'c' ) == &abccd[3] );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strspn.c b/src/pdclib/functions/string/strspn.c
new file mode 100644
index 0000000..7b55b08
--- /dev/null
+++ b/src/pdclib/functions/string/strspn.c
@@ -0,0 +1,49 @@
+/* strspn( 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 <string.h>
+
+#ifndef REGTEST
+
+size_t strspn( const char * s1, const char * s2 )
+{
+ size_t len = 0;
+ const char * p;
+ while ( s1[ len ] )
+ {
+ p = s2;
+ while ( *p )
+ {
+ if ( s1[len] == *p )
+ {
+ break;
+ }
+ ++p;
+ }
+ if ( ! *p )
+ {
+ return len;
+ }
+ ++len;
+ }
+ return len;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ TESTCASE( strspn( abcde, "abc" ) == 3 );
+ TESTCASE( strspn( abcde, "b" ) == 0 );
+ TESTCASE( strspn( abcde, abcde ) == 5 );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strstr.c b/src/pdclib/functions/string/strstr.c
new file mode 100644
index 0000000..aee282f
--- /dev/null
+++ b/src/pdclib/functions/string/strstr.c
@@ -0,0 +1,51 @@
+/* strstr( 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 <string.h>
+
+#ifndef REGTEST
+
+char * strstr( const char * s1, const char * s2 )
+{
+ const char * p1 = s1;
+ const char * p2;
+ while ( *s1 )
+ {
+ p2 = s2;
+ while ( *p2 && ( *p1 == *p2 ) )
+ {
+ ++p1;
+ ++p2;
+ }
+ if ( ! *p2 )
+ {
+ return (char *) s1;
+ }
+ ++s1;
+ p1 = s1;
+ }
+ return NULL;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "abcabcabcdabcde";
+ TESTCASE( strstr( s, "x" ) == NULL );
+ TESTCASE( strstr( s, "xyz" ) == NULL );
+ TESTCASE( strstr( s, "a" ) == &s[0] );
+ TESTCASE( strstr( s, "abc" ) == &s[0] );
+ TESTCASE( strstr( s, "abcd" ) == &s[6] );
+ TESTCASE( strstr( s, "abcde" ) == &s[10] );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strtok.c b/src/pdclib/functions/string/strtok.c
new file mode 100644
index 0000000..69c2d68
--- /dev/null
+++ b/src/pdclib/functions/string/strtok.c
@@ -0,0 +1,107 @@
+/* strtok( 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 <string.h>
+
+#ifndef REGTEST
+
+char * strtok( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2 )
+{
+ static char * tmp = NULL;
+ const char * p = s2;
+
+ if ( s1 != NULL )
+ {
+ /* new string */
+ tmp = s1;
+ }
+ else
+ {
+ /* old string continued */
+ if ( tmp == NULL )
+ {
+ /* No old string, no new string, nothing to do */
+ return NULL;
+ }
+ s1 = tmp;
+ }
+
+ /* skipping leading s2 characters */
+ while ( *p && *s1 )
+ {
+ if ( *s1 == *p )
+ {
+ /* found seperator; skip and start over */
+ ++s1;
+ p = s2;
+ continue;
+ }
+ ++p;
+ }
+
+ if ( ! *s1 )
+ {
+ /* no more to parse */
+ return ( tmp = NULL );
+ }
+
+ /* skipping non-s2 characters */
+ tmp = s1;
+ while ( *tmp )
+ {
+ p = s2;
+ while ( *p )
+ {
+ if ( *tmp == *p++ )
+ {
+ /* found seperator; overwrite with '\0', position tmp, return */
+ *tmp++ = '\0';
+ return s1;
+ }
+ }
+ ++tmp;
+ }
+
+ /* parsed to end of string */
+ tmp = NULL;
+ return s1;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "_a_bc__d_";
+ TESTCASE( strtok( s, "_" ) == &s[1] );
+ TESTCASE( s[1] == 'a' );
+ TESTCASE( s[2] == '\0' );
+ TESTCASE( strtok( NULL, "_" ) == &s[3] );
+ TESTCASE( s[3] == 'b' );
+ TESTCASE( s[4] == 'c' );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( strtok( NULL, "_" ) == &s[7] );
+ TESTCASE( s[6] == '_' );
+ TESTCASE( s[7] == 'd' );
+ TESTCASE( s[8] == '\0' );
+ TESTCASE( strtok( NULL, "_" ) == NULL );
+ strcpy( s, "ab_cd" );
+ TESTCASE( strtok( s, "_" ) == &s[0] );
+ TESTCASE( s[0] == 'a' );
+ TESTCASE( s[1] == 'b' );
+ TESTCASE( s[2] == '\0' );
+ TESTCASE( strtok( NULL, "_" ) == &s[3] );
+ TESTCASE( s[3] == 'c' );
+ TESTCASE( s[4] == 'd' );
+ TESTCASE( s[5] == '\0' );
+ TESTCASE( strtok( NULL, "_" ) == NULL );
+ return TEST_RESULTS;
+}
+
+#endif
diff --git a/src/pdclib/functions/string/strxfrm.c b/src/pdclib/functions/string/strxfrm.c
new file mode 100644
index 0000000..e08dba2
--- /dev/null
+++ b/src/pdclib/functions/string/strxfrm.c
@@ -0,0 +1,50 @@
+/* strxfrm( char *, const char *, 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 <string.h>
+
+#ifndef REGTEST
+
+#include <locale.h>
+
+size_t strxfrm( char * _PDCLIB_restrict s1, const char * _PDCLIB_restrict s2, size_t n )
+{
+ size_t len = strlen( s2 );
+ if ( len < n )
+ {
+ /* Cannot use strncpy() here as the filling of s1 with '\0' is not part
+ of the spec.
+ */
+ /* FIXME: The code below became invalid when we started doing *real* locales... */
+ /*while ( n-- && ( *s1++ = _PDCLIB_lc_collate[(unsigned char)*s2++].collation ) );*/
+ while ( n-- && ( *s1++ = (unsigned char)*s2++ ) );
+ }
+ return len;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ char s[] = "xxxxxxxxxxx";
+ TESTCASE( strxfrm( NULL, "123456789012", 0 ) == 12 );
+ TESTCASE( strxfrm( s, "123456789012", 12 ) == 12 );
+ /*
+ The following test case is true in *this* implementation, but doesn't have to.
+ TESTCASE( s[0] == 'x' );
+ */
+ TESTCASE( strxfrm( s, "1234567890", 11 ) == 10 );
+ TESTCASE( s[0] == '1' );
+ TESTCASE( s[9] == '0' );
+ TESTCASE( s[10] == '\0' );
+ return TEST_RESULTS;
+}
+
+#endif