Index: libcfa/src/stdlib.cfa
===================================================================
--- libcfa/src/stdlib.cfa	(revision b5e725a08cfb0cd8ca08fc4c9afb6f82a6db8f82)
+++ libcfa/src/stdlib.cfa	(revision 54af365fe21768cc290024aaeb88d8cbf7f0563f)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 17:10:29 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Aug 14 18:22:36 2023
-// Update Count     : 642
+// Last Modified On : Fri Mar 15 18:47:28 2024
+// Update Count     : 685
 //
 
@@ -24,4 +24,5 @@
 #include <complex.h>									// _Complex_I
 #include <assert.h>
+#include <ctype.h>
 
 #pragma GCC visibility push(default)
@@ -65,6 +66,158 @@
 //---------------------------------------
 
+// Cannot overload with singular (isspace) counterparts because they are macros.
+
+bool isalnums( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isalnum( *s ) ) return false;
+		s += 1;
+	} // for
+} // isalnums
+
+bool isalphas( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isalpha( *s ) ) return false;
+		s += 1;
+	} // for
+} // isblanks
+
+bool iscntrls( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! iscntrl( *s ) ) return false;
+		s += 1;
+	} // for
+} // iscntrls
+
+bool isdigits( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isdigit( *s ) ) return false;
+		s += 1;
+	} // for
+} // isdigits
+
+bool isgraphs( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isgraph( *s ) ) return false;
+		s += 1;
+	} // for
+} // isgraphs
+
+bool islowers( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! islower( *s ) ) return false;
+		s += 1;
+	} // for
+} // islowers
+
+bool isprints( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isprint( *s ) ) return false;
+		s += 1;
+	} // for
+} // isprints
+
+bool ispuncts( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! ispunct( *s ) ) return false;
+		s += 1;
+	} // for
+} // ispuncts
+
+bool isspaces( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isspace( *s ) ) return false;
+		s += 1;
+	} // for
+} // isspaces
+
+bool isblanks( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isblank( *s ) ) return false;
+		s += 1;
+	} // for
+} // isblanks
+
+bool isuppers( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isupper( *s ) ) return false;
+		s += 1;
+	} // for
+} // isuppers
+
+bool isxdigits( const char s[] ) {
+	for () {
+		if ( *s == '\0' ) return true;
+		if ( ! isxdigit( *s ) ) return false;
+		s += 1;
+	} // for
+} // isxdigits
+
+//---------------------------------------
+
+float _Complex strto( const char sptr[], char * eptr[] ) {
+	float re, im;
+	char * eeptr;
+	errno = 0;											// reset
+	re = strtof( sptr, &eeptr );
+	if ( sptr != eeptr ) {
+		im = strtof( eeptr, &eeptr );
+		if ( sptr != eeptr ) {
+			if ( *eeptr == 'i' ) {
+				if ( eptr != 0p ) *eptr = eeptr + 1;
+				return re + im * _Complex_I;
+			} // if
+		} // if
+	} // if
+	if ( eptr != 0p ) *eptr = eeptr;					// error case
+	return 0.0f + 0.0f * _Complex_I;
+} // strto
+
+double _Complex strto( const char sptr[], char * eptr[] ) {
+	double re, im;
+	char * eeptr;
+	re = strtod( sptr, &eeptr );
+	if ( sptr != eeptr ) {
+		im = strtod( eeptr, &eeptr );
+		if ( sptr != eeptr ) {
+			if ( *eeptr == 'i' ) {
+				if ( eptr != 0p ) *eptr = eeptr + 1;
+				return re + im * _Complex_I;
+			} // if
+		} // if
+	} // if
+	if ( eptr != 0p ) *eptr = eeptr;					// error case
+	return 0.0 + 0.0 * _Complex_I;
+} // strto
+
+long double _Complex strto( const char sptr[], char * eptr[] ) {
+	long double re, im;
+	char * eeptr;
+	re = strtold( sptr, &eeptr );
+	if ( sptr != eeptr ) {
+		im = strtold( eeptr, &eeptr );
+		if ( sptr != eeptr ) {
+			if ( *eeptr == 'i' ) {
+				if ( eptr != 0p ) *eptr = eeptr + 1;
+				return re + im * _Complex_I;
+			} // if
+		} // if
+	} // if
+	if ( eptr != 0p ) *eptr = eeptr;					// error case
+	return 0.0L + 0.0L * _Complex_I;
+} // strto
+
 forall( T | { T strto( const char sptr[], char * eptr[], int ); } )
-T convert( const char sptr[] ) {
+T convert( const char sptr[] ) {						// integral
 	char * eptr;
 	errno = 0;											// reset
@@ -72,40 +225,18 @@
 	if ( errno == ERANGE ) throw ExceptionInst( out_of_range );
 	if ( eptr == sptr ||								// conversion failed, no characters generated
-		 *eptr != '\0' ) throw ExceptionInst( invalid_argument ); // not at end of str ?
+		 eptr[0] != '\0' && ! isspaces( eptr ) ) throw ExceptionInst( invalid_argument ); // not at end of blank str ?
 	return val;
 } // convert
 
-float _Complex strto( const char sptr[], char * eptr[] ) {
-	float re, im;
-	char * eeptr;
-	re = strtof( sptr, &eeptr );
-	if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0f + 0.0f * _Complex_I; }
-	im = strtof( eeptr, &eeptr );
-	if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0f + 0.0f * _Complex_I; }
-	if ( *eeptr != 'i' ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0f + 0.0f * _Complex_I; }
-	return re + im * _Complex_I;
-} // strto
-
-double _Complex strto( const char sptr[], char * eptr[] ) {
-	double re, im;
-	char * eeptr;
-	re = strtod( sptr, &eeptr );
-	if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0 + 0.0 * _Complex_I; }
-	im = strtod( eeptr, &eeptr );
-	if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0 + 0.0 * _Complex_I; }
-	if ( *eeptr != 'i' ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0 + 0.0 * _Complex_I; }
-	return re + im * _Complex_I;
-} // strto
-
-long double _Complex strto( const char sptr[], char * eptr[] ) {
-	long double re, im;
-	char * eeptr;
-	re = strtold( sptr, &eeptr );
-	if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0L + 0.0L * _Complex_I; }
-	im = strtold( eeptr, &eeptr );
-	if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0L + 0.0L * _Complex_I; }
-	if ( *eeptr != 'i' ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0L + 0.0L * _Complex_I; }
-	return re + im * _Complex_I;
-} // strto
+forall( T | { T strto( const char sptr[], char * eptr[] ); } )
+T convert( const char sptr[] ) {						// floating-point
+	char * eptr;
+	errno = 0;											// reset
+	T val = strto( sptr, &eptr );						// attempt conversion
+	if ( errno == ERANGE ) throw ExceptionInst( out_of_range );
+	if ( eptr == sptr ||								// conversion failed, no characters generated
+		 eptr[0] != '\0' && ! isspaces( eptr ) ) throw ExceptionInst( invalid_argument ); // not at end of blank str ?
+	return val;
+} // convert
 
 //---------------------------------------
