Index: libcfa/src/iostream.cfa
===================================================================
--- libcfa/src/iostream.cfa	(revision 3543e991e011a9dddd3bbcbe5bf9f22d0266f764)
+++ libcfa/src/iostream.cfa	(revision 2f34fde3625c13aae06528957e8a62c8058241d3)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Aug 10 18:15:44 2023
-// Update Count     : 1442
+// Last Modified On : Mon Aug 14 18:37:02 2023
+// Update Count     : 1460
 //
 
@@ -972,12 +972,16 @@
 		// 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
+			enum { size = 16 };
+			char fmtstr[size];
+			snprintf( fmtstr, size, "%%%d[^%c]s", f.wd, f.delimit );
+			f.s[f.wd - 1] = '\0';						// insert sentinel
+			int len = fmt( is, fmtstr, f.s );			// read upto delimiter
+			if ( len == 0 ) f.s[0] = '\0';				// empty read => argument unchanged => set empty
+			if ( f.s[f.wd - 1] != '\0' )				// sentinel overwritten ?
+				throw (cstring_length){ &cstring_length_vt };
+			if ( ! eof( is ) ) fmt( is, "%*c" );		// ignore delimiter
 			return is;
 		} // if
 
-		// incl/excl
 		size_t len = 0;
 		if ( f.scanset ) len = strlen( f.scanset );
@@ -987,20 +991,26 @@
 		if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
 		if ( f.wd != -1 ) { start += sprintf( &fmtstr[start], "%d", f.wd ); }
-		// cstr %s, %*s, %ws, %*ws
+
 		if ( ! f.scanset ) {
+			// %s, %*s, %ws, %*ws
 			fmtstr[start] = 's'; fmtstr[start + 1] = '\0';
 			// printf( "cstr %s\n", fmtstr );
-			fmt( is, fmtstr, f.s );
-			return is;
-		} // if
-		// 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], f.scanset );			// copy includes '\0'
-		len += start;
-		fmtstr[len] = ']'; fmtstr[len + 1] = '\0';
-		// printf( "incl/excl %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], f.scanset );		// copy includes '\0'
+			len += start;
+			fmtstr[len] = ']'; fmtstr[len + 1] = '\0';
+			// printf( "incl/excl %s\n", fmtstr );
+		} // if
+
+		int check = f.wd - 1;
+		if ( f.flags.rwd ) check += 1;					// provide place for sentinel
+		f.s[check] = '\0';								// insert sentinel
 		fmt( is, fmtstr, f.s );
+		if ( f.s[check] != '\0' )						// sentinel overwritten ?
+			throw (cstring_length){ &cstring_length_vt };
 		return is;
 	} // ?|?
@@ -1081,4 +1091,5 @@
 } // distribution
 
+
 // Local Variables: //
 // tab-width: 4 //
Index: libcfa/src/iostream.hfa
===================================================================
--- libcfa/src/iostream.hfa	(revision 3543e991e011a9dddd3bbcbe5bf9f22d0266f764)
+++ libcfa/src/iostream.hfa	(revision 2f34fde3625c13aae06528957e8a62c8058241d3)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Aug  9 16:47:05 2023
-// Update Count     : 500
+// Last Modified On : Mon Aug 14 17:35:40 2023
+// Update Count     : 508
 //
 
@@ -17,4 +17,5 @@
 
 #include "iterator.hfa"
+#include "Exception.hfa"
 
 
@@ -401,4 +402,11 @@
 } // distribution
 
+
+// *********************************** exceptions ***********************************
+
+
+ExceptionDecl( cstring_length );
+
+
 // *********************************** manipulators ***********************************
 
@@ -416,4 +424,5 @@
 			unsigned char inex:1;						// include/exclude characters in scanset
 			unsigned char delimit:1;					// delimit character
+			unsigned char rwd:1;						// read width
 		} flags;
 	};
@@ -434,4 +443,8 @@
 	_Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; }
 	_Istream_Cstr wdi( unsigned int wd, char s[] ) { return (_Istream_Cstr)@{ s, {0p}, wd, {.all : 0} }; }
+	_Istream_Cstr wdi( unsigned int wd, unsigned int rwd, char s[] ) {
+		if ( wd <= rwd ) throw (cstring_length){ &cstring_length_vt };
+		return (_Istream_Cstr)@{ s, {0p}, rwd, {.flags.rwd : true} };
+	}
 //	_Istream_Cstr & wdi( unsigned int wd, _Istream_Cstr & fmt ) { fmt.wd = wd; return fmt; }
 } // distribution
