Index: libcfa/src/iostream.cfa
===================================================================
--- libcfa/src/iostream.cfa	(revision f842032a0a09c7dcfe63ef8705bff30bf6b1b1b0)
+++ libcfa/src/iostream.cfa	(revision 37ceccbccec1df04d3e17e8c2deb88d47c942720)
@@ -1,2 +1,3 @@
+
 //
 // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
@@ -10,6 +11,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Oct 19 19:29:54 2023
-// Update Count     : 1800
+// Last Modified On : Sun Oct  8 12:10:21 2023
+// Update Count     : 1564
 //
 
@@ -47,5 +48,5 @@
 		return os;
 	} // ?|?
-	OSYPE_VOID_IMPL( bool )
+	OSTYPE_VOID_IMPL( bool )
 
 	ostype & ?|?( ostype & os, char c ) {
@@ -784,4 +785,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( bool & )
 
 	istype & ?|?( istype & is, char & c ) {
@@ -795,4 +797,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( char & )
 
 	istype & ?|?( istype & is, signed char & sc ) {
@@ -800,4 +803,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( signed char & )
 
 	istype & ?|?( istype & is, unsigned char & usc ) {
@@ -805,4 +809,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( unsigned char & )
 
 	istype & ?|?( istype & is, short int & si ) {
@@ -810,4 +815,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( short int & )
 
 	istype & ?|?( istype & is, unsigned short int & usi ) {
@@ -815,4 +821,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( unsigned short int & )
 
 	istype & ?|?( istype & is, int & i ) {
@@ -820,4 +827,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( int & )
 
 	istype & ?|?( istype & is, unsigned int & ui ) {
@@ -825,4 +833,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( unsigned int & )
 
 	istype & ?|?( istype & is, long int & li ) {
@@ -830,4 +839,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( long int & )
 
 	istype & ?|?( istype & is, unsigned long int & ulli ) {
@@ -835,4 +845,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( unsigned long int & )
 
 	istype & ?|?( istype & is, long long int & lli ) {
@@ -840,4 +851,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( long long int & )
 
 	istype & ?|?( istype & is, unsigned long long int & ulli ) {
@@ -845,4 +857,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( unsigned long long int & )
 
 	#if defined( __SIZEOF_INT128__ )
@@ -850,4 +863,5 @@
 		return (istype &)(is | (unsigned int128 &)llli);
 	} // ?|?
+	ISTYPE_VOID_IMPL( int128 & )
 
 	istype & ?|?( istype & is, unsigned int128 & ullli ) {
@@ -866,4 +880,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( unsigned int128 & )
 	#endif // __SIZEOF_INT128__
 
@@ -872,4 +887,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( float & )
 
 	istype & ?|?( istype & is, double & d ) {
@@ -877,4 +893,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( double & )
 
 	istype & ?|?( istype & is, long double & ld ) {
@@ -882,4 +899,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( long double & )
 
 	istype & ?|?( istype & is, float _Complex & fc ) {
@@ -889,4 +907,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( float _Complex & )
 
 	istype & ?|?( istype & is, double _Complex & dc ) {
@@ -896,4 +915,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( double _Complex & )
 
 	istype & ?|?( istype & is, long double _Complex & ldc ) {
@@ -903,4 +923,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( long double _Complex & )
 
 	istype & ?|?( istype & is, const char fmt[] ) {
@@ -908,4 +929,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( const char * )
 
 	// manipulators
@@ -915,5 +937,5 @@
 
 	void ?|?( istype & is, istype & (* manip)( istype & ) ) {
-		manip( is );
+		manip( is ); ends( is );
 	} // ?|?
 
@@ -944,108 +966,94 @@
 			char fmtstr[ sizeof("%*[]") + nscanset ];
 			int pos = 0;
-			strcpy( &fmtstr[pos], "%*[" );  pos += 3;
+			fmtstr[pos] = '%';                  pos += 1;
+			fmtstr[pos] = '*';                  pos += 1;
+			fmtstr[pos] = '[';                  pos += 1;
 			strcpy( &fmtstr[pos], f.scanset );  pos += nscanset;
-			strcpy( &fmtstr[pos], "]" );
-			fmt( is, fmtstr, "" );						// skip scanset
-		} else {
-			char ch;
-//			fprintf( stderr, "skip " );
-			for ( f.wd ) {								// skip N characters
-			  if ( eof( is ) ) break;
-				fmt( is, "%c", &ch );
-//				fprintf( stderr, "`%c' ", ch );
-			} // for
-		} // if
+			fmtstr[pos] = ']';                  pos += 1;
+			fmtstr[pos] = '\0';
+			fmt( is, fmtstr, (void*)0 );  // last arg is dummy: suppress gcc warning
+		}
+		else for ( f.wd ) fmt( is, "%*c" );
 		return is;
 	}
+	ISTYPE_VOID_IMPL( _Istream_Cskip )
 
 	istype & ?|?( istype & is, _Istream_Cstr f ) {
-		const char * scanset;
-		size_t nscanset = 0;
+		const char * scanset = f.scanset;
 		if ( f.flags.delimiter ) scanset = f.delimiter;	// getline ?
-		else scanset = f.scanset;
-		if ( scanset ) nscanset = strlen( scanset );
-
-		char fmtstr[nscanset + 32];						// storage for scanset and format codes
+
+		size_t len = 0;
+		if ( scanset ) len = strlen( scanset );
+		char fmtstr[len + 16];
+		int start = 1;
 		fmtstr[0] = '%';
-
-		int pos = 1;
-		int args;
-		bool check = true;
-
-		if ( f.flags.ignore ) { check = false; fmtstr[1] = '*'; pos += 1; }
-		int rwd = f.wd;
-		if ( f.wd != -1 ) {								// => just ignore versus ignore with width
+		if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
+		// no maximum width necessary because text ignored => width is read width
+		if ( f.wd != -1 ) {
 			// wd is buffer bytes available (for input chars + null terminator)
 			// rwd is count of input chars
-			// no maximum width necessary because text ignored => width is read width
-			if ( f.flags.rwd ) check = false;
-			else rwd = f.wd - 1;
-			pos += sprintf( &fmtstr[pos], "%d", rwd );
+			int rwd;
+			if (f.flags.rwd) {
+				verify (f.wd >= 0);
+				rwd = f.wd;
+			} else {
+				verify (f.wd >= 1);
+				rwd = f.wd - 1;
+			} // if
+			start += sprintf( &fmtstr[start], "%d", rwd );
+		}
+
+		if ( ! scanset ) {
+			// %s, %*s, %ws, %*ws
+			fmtstr[start] = 's'; fmtstr[start + 1] = '\0';
+			// printf( "cstr %s\n", fmtstr );
+		} else {
+			// incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
+			// excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx]
+			fmtstr[start] = '['; start += 1;
+			if ( f.flags.inex ) { fmtstr[start] = '^'; start += 1; }
+			strcpy( &fmtstr[start], scanset );			// copy includes '\0'
+			len += start;
+			fmtstr[len] = ']'; fmtstr[len + 1] = '\0';
+			// printf( "incl/excl %s\n", fmtstr );
 		} // if
 
-		if ( ! scanset ) {								// %s, %*s, %ws, %*ws
-//			fprintf( stderr, "cstr %s\n", f.s );
-			strcpy( &fmtstr[pos], "s%n" );
-			int len = 0;								// may not be set in fmt
-			if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
-			else args = fmt( is, fmtstr, f.s, &len );
-//			fprintf( stderr, "cstr %s %d %d %d %s\n", fmtstr, args, len, f.wd, f.s );
-			if ( check && len >= rwd && ! eof( is ) ) {	// might not fit
+		int check = f.wd - 2;
+		if (! f.flags.ignore ) {
+			if ( ! f.flags.rwd ) f.s[check] = '\0';		// insert sentinel
+		}
+		len = fmt( is, fmtstr, f.s );
+		//fprintf( stderr, "KK %s %zd %d %c %s\n", fmtstr, len, check, f.s[check], f.s );
+
+		if ( ! f.flags.ignore && ! f.flags.rwd && f.s[check] != '\0' ) { // sentinel overwritten ?
+			// buffer filled, but would we have kept going?
+			if ( ! eof( is ) ) {
 				char peek;
-				fmt( is, "%c", &peek );					// check for whitespace terminator
-//				fprintf( stderr, "peek %d '%c'\n", args, peek );
-				if ( ! eof( is ) ) {
-					ungetc( is, peek );
-					if ( ! isspace( peek ) ) throw ExceptionInst( cstring_length );
-				} // if
-			} // if
-		} else {
-			if ( f.flags.delimiter ) {					// getline
-//				fprintf( stderr, "getline\n" );
-				sprintf( &fmtstr[pos], "[%s%s]%%n", f.flags.inex ? "^" : "", scanset );
-//				fprintf( stderr, "getline %s %d\n", fmtstr, f.wd );
-				int len = 0;							// may not be set in fmt
-				if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
-				else args = fmt( is, fmtstr, f.s, &len );
-//				fprintf( stderr, "getline %s %d %d %d\n", fmtstr, args, f.wd, eof( is ) );
-				if ( check && len == rwd && ! eof( is ) ) {	// might not fit
-					char peek;
-					fmt( is, "%c", &peek );				// check for delimiter
-//					fprintf( stderr, "peek %d '%c'\n", args, peek );
-					if ( ! eof( is ) ) {
-						if ( peek != f.delimiter[0] ) {
-							ungetc( is, peek );
-							throw ExceptionInst( cstring_length );
-						} // if
-					} // if
-				} else fmt( is, "%*c" );				//  remove delimiter
-			} else {
-				// incl %[xxx],  %*[xxx],  %w[xxx],  %*w[xxx]
-				// excl %[^xxx], %*[^xxx], %w[^xxx], %*w[^xxx]
-				sprintf( &fmtstr[pos], "[%s%s]%%n", f.flags.inex ? "^" : "", scanset );
-//				fprintf( stderr, "incl/excl %s %d\n", fmtstr, f.wd );
-				int len = 0;							// may not be set in fmt
-				if ( f.flags.ignore ) args = fmt( is, fmtstr, &len ); // no string argument for '*'
-				else args = fmt( is, fmtstr, f.s, &len );
-//				fprintf( stderr, "incl/excl %s \"%s\" %d %d %d %d %d %c\n", fmtstr, f.s, args, f.wd, len, eof( is ), check, f.s[f.wd] );
-				if ( check && len == rwd && ! eof( is ) ) {	// might not fit
-//					fprintf( stderr, "overflow\n" );
-					char peek;
-					fmt( is, "%c", &peek );				// check for whitespace terminator
-//					fprintf( stderr, "peek %d '%c'\n", args, peek );
-					if ( ! eof( is ) ) {
-						ungetc( is, peek );
-						if ( f.flags.inex ^ strchr( f.scanset, peek ) != 0p ) throw ExceptionInst( cstring_length );
-					} // if
-				} // if
+				fmt( is, "%c", &peek );
+				ungetc( is, peek );
+				bool hasMore;
+				if (f.flags.delimiter) { // getline
+					hasMore = (peek != f.delimiter[0]);
+				} else if (f.scanset) { // incl/excl
+					bool peekMatch = strchr(f.scanset, peek) != 0p;
+					hasMore = f.flags.inex ? (!peekMatch) : (peekMatch);
+				} else { // %s
+					hasMore = !isspace(peek);
+				}
+				if (hasMore) throw (cstring_length){ &cstring_length_vt };
 			} // if
 		} // if
-		if ( args == 1 && eof( is ) ) {					// data but scan ended at EOF
-//			fprintf( stderr, "clear\n" );
-			clear( is );								// => reset EOF => detect again on next read
-		} // if
-		return is;
-	} // ?|?
+
+		if ( f.flags.delimiter ) {						// getline ?
+			if ( len == 0 ) f.s[0] = '\0';				// empty read => argument unchanged => set empty
+			if ( ! eof( is ) ) {						// ignore delimiter, may not be present because of width
+				char delimiter;
+				fmt( is, "%c", &delimiter );
+				if ( delimiter != f.delimiter[0] ) ungetc( is, delimiter );
+			} // if
+		} //if
+		return is;
+	} // ?|?
+	ISTYPE_VOID_IMPL( _Istream_Cstr )
 
 	istype & ?|?( istype & is, _Istream_Char f ) {
@@ -1053,4 +1061,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( _Istream_Char )
 } // distribution
 
@@ -1069,4 +1078,5 @@
 		return is; \
 	} /* ?|? */ \
+	ISTYPE_VOID_IMPL( _Istream_Manip(T) ) \
 } // distribution
 
@@ -1096,4 +1106,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( _Istream_Manip(float _Complex) )
 
 	istype & ?|?( istype & is, _Istream_Manip(double _Complex) dc ) {
@@ -1106,4 +1117,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( _Istream_Manip(double _Complex) )
 
 	istype & ?|?( istype & is, _Istream_Manip(long double _Complex) ldc ) {
@@ -1116,4 +1128,5 @@
 		return is;
 	} // ?|?
+	ISTYPE_VOID_IMPL( _Istream_Manip(long double _Complex) )
 } // distribution
 
