Index: libcfa/src/iostream.cfa
===================================================================
--- libcfa/src/iostream.cfa	(revision 3318dff9124a356ddd12a7df7cd197d06e1f9722)
+++ libcfa/src/iostream.cfa	(revision e7a8f655ee2736d3b5a902f42b4cba2d05067676)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Aug  7 08:59:29 2023
-// Update Count     : 1407
+// Last Modified On : Wed Aug  9 10:10:56 2023
+// Update Count     : 1432
 //
 
@@ -271,5 +271,5 @@
 	OSTYPE_VOID_IMPL( const char * )
 
-// 	ostype & ?|?( ostype & os, const char16_t * s ) {
+// 	ostype & ?|?( ostype & os, const char16_t s[] ) {
 // 		if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
 // 		fmt( os, "%ls", s );
@@ -278,5 +278,5 @@
 
 // #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
-// 	ostype & ?|?( ostype & os, const char32_t * s ) {
+// 	ostype & ?|?( ostype & os, const char32_t s[] ) {
 // 		if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
 // 		fmt( os, "%ls", s );
@@ -285,5 +285,5 @@
 // #endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
 
-// 	ostype & ?|?( ostype & os, const wchar_t * s ) {
+// 	ostype & ?|?( ostype & os, const wchar_t s[] ) {
 // 		if ( sepPrt$( os ) ) fmt( os, "%s", sepGetCur$( os ) );
 // 		fmt( os, "%ls", s );
@@ -917,9 +917,9 @@
 	// } // ?|?
 
-	istype & ?|?( istype & is, char s[] ) {
-		fmt( is, "%s", s );
-		return is;
-	} // ?|?
-	ISTYPE_VOID_IMPL( char * )
+	// istype & ?|?( istype & is, char s[] ) {
+	// 	fmt( is, "%s", s );
+	// 	return is;
+	// } // ?|?
+	// ISTYPE_VOID_IMPL( char * )
 
 	// manipulators
@@ -934,4 +934,5 @@
 	istype & nl( istype & is ) {
 		fmt( is, "%*[^\n]" );							// ignore characters to newline
+		if ( ! eof( is ) && getANL$( is ) ) fmt( is, "%*c" ); // read newline
 		return is;
 	} // nl
@@ -952,11 +953,22 @@
 forall( istype & | basic_istream( istype ) ) {
 	istype & ?|?( istype & is, _Istream_Cstr f ) {
-		// skip xxx
+		// skip
 		if ( ! f.s ) {
 			// printf( "skip %s %d\n", f.scanset, f.wd );
-			if ( f.wd == -1 ) fmt( is, f.scanset, "" );		// no input arguments
+			if ( f.wd == -1 ) fmt( is, f.scanset, "" );	// no input arguments
 			else for ( f.wd ) fmt( is, "%*c" );
 			return is;
 		} // if
+
+		// getline
+		if ( f.flags.delimit ) {
+			char fmtstr[] = "%[^ ]s";					// delimit inserted into space
+			fmtstr[3] = f.delimit;
+			fmt( is, fmtstr, f.s );						// read upto delimiter
+			fmt( is, "%*c" );							// ignore delimiter
+			return is;
+		} // if
+
+		// incl/excl
 		size_t len = 0;
 		if ( f.scanset ) len = strlen( f.scanset );
@@ -977,5 +989,5 @@
 		fmtstr[start] = '['; start += 1;
 		if ( f.flags.inex ) { fmtstr[start] = '^'; start += 1; }
-		strcpy( &fmtstr[start], f.scanset );				// copy includes '\0'
+		strcpy( &fmtstr[start], f.scanset );			// copy includes '\0'
 		len += start;
 		fmtstr[len] = ']'; fmtstr[len + 1] = '\0';
@@ -987,5 +999,5 @@
 
 	istype & ?|?( istype & is, _Istream_Char f ) {
-		fmt( is, "%*c" );									// argument variable unused
+		fmt( is, "%*c" );								// argument variable unused
 		return is;
 	} // ?|?
Index: libcfa/src/iostream.hfa
===================================================================
--- libcfa/src/iostream.hfa	(revision 3318dff9124a356ddd12a7df7cd197d06e1f9722)
+++ libcfa/src/iostream.hfa	(revision e7a8f655ee2736d3b5a902f42b4cba2d05067676)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Jul 19 14:25:52 2023
-// Update Count     : 463
+// Last Modified On : Wed Aug  9 16:47:05 2023
+// Update Count     : 500
 //
 
@@ -130,9 +130,9 @@
 	ostype & ?|?( ostype &, const char [] );
 	OSTYPE_VOID( const char [] );
-	// ostype & ?|?( ostype &, const char16_t * );
+	// ostype & ?|?( ostype &, const char16_t [] );
 	#if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
-	// ostype & ?|?( ostype &, const char32_t * );
+	// ostype & ?|?( ostype &, const char32_t [] );
 	#endif // ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 )
-	// ostype & ?|?( ostype &, const wchar_t * );
+	// ostype & ?|?( ostype &, const wchar_t [] );
 	ostype & ?|?( ostype &, const void * );
 	OSTYPE_VOID( const void * );
@@ -390,6 +390,6 @@
 
 //	istype & ?|?( istype &, const char [] );
-	istype & ?|?( istype &, char [] );
-	ISTYPE_VOID( char * );
+//	istype & ?|?( istype &, char [] );
+//	ISTYPE_VOID( char [] );
 
 	// manipulators
@@ -405,5 +405,8 @@
 struct _Istream_Cstr {
 	char * s;
-	const char * scanset;
+	union {
+		const char * scanset;
+		char delimit;
+	};
 	int wd;												// width
 	union {
@@ -412,4 +415,5 @@
 			unsigned char ignore:1;						// do not change input argument
 			unsigned char inex:1;						// include/exclude characters in scanset
+			unsigned char delimit:1;					// delimit character
 		} flags;
 	};
@@ -417,14 +421,18 @@
 
 static inline {
-	_Istream_Cstr skip( const char scanset[] ) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; }
-	_Istream_Cstr skip( unsigned int n ) { return (_Istream_Cstr){ 0p, 0p, n, { .all : 0 } }; }
-	_Istream_Cstr incl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; }
+	_Istream_Cstr skip( const char scanset[] ) { return (_Istream_Cstr){ 0p, {scanset}, -1, {.all : 0} }; }
+	_Istream_Cstr skip( unsigned int wd ) { return (_Istream_Cstr){ 0p, {0p}, wd, {.all : 0} }; }
+	_Istream_Cstr & getline( _Istream_Cstr & fmt ) { fmt.delimit = '\n'; fmt.flags.delimit = true; return fmt; }
+	_Istream_Cstr & getline( const char delimit, _Istream_Cstr & fmt ) { fmt.delimit = delimit; fmt.flags.delimit = true; return fmt; }
+//	_Istream_Cstr incl( const char scanset[], char s[] ) { return (_Istream_Cstr){ s, {scanset}, -1, { .flags.inex : false } }; }
+//	_Istream_Cstr incl( const char scanset[], unsigned int wd, char s[] ) { return (_Istream_Cstr){ s, {scanset}, wd, {.flags.inex : false} }; }
 	_Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
-	_Istream_Cstr excl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; }
+//	_Istream_Cstr excl( const char scanset[], char s[] ) { return (_Istream_Cstr){ s, {scanset}, -1, { .flags.inex : true } }; }
+//	_Istream_Cstr excl( const char scanset[], unsigned int wd, char s[] ) { return (_Istream_Cstr){ s, {scanset}, wd, {.flags.inex : true} }; }
 	_Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
-	_Istream_Cstr ignore( char s[] ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; }
+	_Istream_Cstr ignore( char s[] ) { return (_Istream_Cstr)@{ s, {0p}, -1, {.flags.ignore : true} }; }
 	_Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; }
-	_Istream_Cstr wdi( unsigned int w, char s[] ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; }
-	_Istream_Cstr & wdi( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; }
+	_Istream_Cstr wdi( unsigned int wd, char s[] ) { return (_Istream_Cstr)@{ s, {0p}, wd, {.all : 0} }; }
+//	_Istream_Cstr & wdi( unsigned int wd, _Istream_Cstr & fmt ) { fmt.wd = wd; return fmt; }
 } // distribution
 forall( istype & | basic_istream( istype ) ) {
@@ -457,6 +465,6 @@
 	_Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ (T &)val, -1, true }; } \
 	_Istream_Manip(T) & ignore( _Istream_Manip(T) & fmt ) { fmt.ignore = true; return fmt; } \
-	_Istream_Manip(T) wdi( unsigned int w, T & val ) { return (_Istream_Manip(T))@{ val, w, false }; } \
-	_Istream_Manip(T) & wdi( unsigned int w, _Istream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \
+	_Istream_Manip(T) wdi( unsigned int wd, T & val ) { return (_Istream_Manip(T))@{ val, wd, false }; } \
+	_Istream_Manip(T) & wdi( unsigned int wd, _Istream_Manip(T) & fmt ) { fmt.wd = wd; return fmt; } \
 } /* distribution */ \
 forall( istype & | basic_istream( istype ) ) { \
