Index: libcfa/src/Makefile.am
===================================================================
--- libcfa/src/Makefile.am	(revision b43151554ff02e51061ab185ce928a72bf46fbce)
+++ libcfa/src/Makefile.am	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
@@ -11,6 +11,6 @@
 ## Created On       : Sun May 31 08:54:01 2015
 ## Last Modified By : Peter A. Buhr
-## Last Modified On : Wed Dec  9 22:46:14 2020
-## Update Count     : 250
+## Last Modified On : Sat Apr 24 09:09:56 2021
+## Update Count     : 254
 ###############################################################################
 
@@ -69,4 +69,5 @@
 	common.hfa \
 	fstream.hfa \
+	strstream.hfa \
 	heap.hfa \
 	iostream.hfa \
Index: libcfa/src/strstream.cfa
===================================================================
--- libcfa/src/strstream.cfa	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
+++ libcfa/src/strstream.cfa	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
@@ -0,0 +1,133 @@
+// 
+// Cforall Version 1.0.0 Copyright (C) 2021 University of Waterloo
+// 
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// strstream.cfa -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Thu Apr 22 22:24:35 2021
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat Apr 24 11:15:47 2021
+// Update Count     : 73
+// 
+
+#include "strstream.hfa"
+
+#include <stdio.h>										// vsnprintf
+#include <stdarg.h>										// varargs
+#include <string.h>										// strncpy, strerror
+#include <assert.h>
+#include <errno.h>										// errno
+#include <unistd.h>										// sbrk, sysconf
+
+// *********************************** strstream ***********************************
+
+
+#define IO_MSG "I/O error: "
+
+// private
+bool sepPrt$( strstream & os ) { setNL$( os, false ); return os.sepOnOff$; }
+void sepReset$( strstream & os ) { os.sepOnOff$ = os.sepDefault$; }
+void sepReset$( strstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }
+const char * sepGetCur$( strstream & os ) { return os.sepCur$; }
+void sepSetCur$( strstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }
+bool getNL$( strstream & os ) { return os.sawNL$; }
+void setNL$( strstream & os, bool state ) { os.sawNL$ = state; }
+bool getANL$( strstream & os ) { return os.nlOnOff$; }
+bool getPrt$( strstream & os ) { return os.prt$; }
+void setPrt$( strstream & os, bool state ) { os.prt$ = state; }
+
+// public
+void ?{}( strstream & os, char buf[], size_t size ) {
+	os.buf$ = buf;
+	os.size$ = size;
+	os.cursor$ = 0;
+	os.sepDefault$ = true;
+	os.sepOnOff$ = false;
+	os.nlOnOff$ = true;
+	os.prt$ = false;
+	os.sawNL$ = false;
+	sepSetCur$( os, sepGet( os ) );
+	sepSet( os, " " );
+	sepSetTuple( os, ", " );
+} // ?{}
+
+void sepOn( strstream & os ) { os.sepOnOff$ = ! getNL$( os ); }
+void sepOff( strstream & os ) { os.sepOnOff$ = false; }
+
+bool sepDisable( strstream & os ) {
+	bool temp = os.sepDefault$;
+	os.sepDefault$ = false;
+	sepReset$( os );
+	return temp;
+} // sepDisable
+
+bool sepEnable( strstream & os ) {
+	bool temp = os.sepDefault$;
+	os.sepDefault$ = true;
+	if ( os.sepOnOff$ ) sepReset$( os );				// start of line ?
+	return temp;
+} // sepEnable
+
+void nlOn( strstream & os ) { os.nlOnOff$ = true; }
+void nlOff( strstream & os ) { os.nlOnOff$ = false; }
+
+const char * sepGet( strstream & os ) { return os.separator$; }
+void sepSet( strstream & os, const char s[] ) {
+	assert( s );
+	strncpy( os.separator$, s, strstream_sepSize - 1 );
+	os.separator$[strstream_sepSize - 1] = '\0';
+} // sepSet
+
+const char * sepGetTuple( strstream & os ) { return os.tupleSeparator$; }
+void sepSetTuple( strstream & os, const char s[] ) {
+	assert( s );
+	strncpy( os.tupleSeparator$, s, strstream_sepSize - 1 );
+	os.tupleSeparator$[strstream_sepSize - 1] = '\0';
+} // sepSet
+
+void ends( strstream & os ) {
+	if ( getANL$( os ) ) nl( os );
+	else setPrt$( os, false );							// turn off
+} // ends
+
+int fmt( strstream & os, const char format[], ... ) {
+	va_list args;
+	va_start( args, format );
+	int len = vsnprintf( os.buf$ + os.cursor$, os.size$ - os.cursor$, format, args );
+	os.cursor$ += len;
+	if ( os.cursor$ >= os.size$ ) {						// cursor exceeded buffer size?
+		#define fmtmsg IO_MSG "strstream truncated write, buffer too small.\n"
+		write( STDERR_FILENO, fmtmsg, sizeof(fmtmsg) - 1 );
+		abort();
+	} // if
+	va_end( args );
+
+	setPrt$( os, true );								// called in output cascade
+	sepReset$( os );									// reset separator
+	return len;
+} // fmt
+
+int flush( strstream & ) {								// match trait, not used
+	return 0;
+} // flush
+
+strstream & write( strstream & os ) {
+	return write( os, stdout );
+} // write
+strstream & write( strstream & os, FILE * stream ) {
+	if ( fwrite( os.buf$, 1, os.cursor$, stream ) != os.cursor$ ) {
+		#define writemsg IO_MSG "strstream write error.\n"
+		write( STDERR_FILENO, writemsg, sizeof(writemsg) - 1 );
+		abort();
+	} // if
+	return os;
+} // write
+
+strstream & sstr;
+
+// Local Variables: //
+// tab-width: 4 //
+// End: //
Index: libcfa/src/strstream.hfa
===================================================================
--- libcfa/src/strstream.hfa	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
+++ libcfa/src/strstream.hfa	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
@@ -0,0 +1,81 @@
+// 
+// Cforall Version 1.0.0 Copyright (C) 2021 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+// 
+// strstream.hfa -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Thu Apr 22 22:20:59 2021
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat Apr 24 11:17:33 2021
+// Update Count     : 37
+// 
+
+#pragma once
+
+#include "iostream.hfa"
+#include <stdio.h>
+
+
+// *********************************** strstream ***********************************
+
+
+enum { strstream_sepSize = 16 };
+struct strstream {										// satisfied basic_ostream
+	char * buf$;
+	size_t size$;
+	size_t cursor$;
+	bool sepDefault$;
+	bool sepOnOff$;
+	bool nlOnOff$;
+	bool prt$;											// print text
+	bool sawNL$;
+	const char * sepCur$;
+	char separator$[strstream_sepSize];
+	char tupleSeparator$[strstream_sepSize];
+}; // strstream
+
+// Satisfies basic_ostream
+
+// private
+bool sepPrt$( strstream & );
+void sepReset$( strstream & );
+void sepReset$( strstream &, bool );
+const char * sepGetCur$( strstream & );
+void sepSetCur$( strstream &, const char [] );
+bool getNL$( strstream & );
+void setNL$( strstream &, bool );
+bool getANL$( strstream & );
+bool getPrt$( strstream & );
+void setPrt$( strstream &, bool );
+
+// public
+void sepOn( strstream & );
+void sepOff( strstream & );
+bool sepDisable( strstream & );
+bool sepEnable( strstream & );
+void nlOn( strstream & );
+void nlOff( strstream & );
+
+const char * sepGet( strstream & );
+void sepSet( strstream &, const char [] );
+const char * sepGetTuple( strstream & );
+void sepSetTuple( strstream &, const char [] );
+
+void ends( strstream & );
+int fmt( strstream &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
+int flush( strstream & );
+
+strstream & write( strstream & os );					// use stdout, default value not working
+strstream & write( strstream & os, FILE * stream = stdout );
+
+void ?{}( strstream &, char buf[], size_t size );
+
+extern strstream & sstr;
+
+// Local Variables: //
+// mode: c //
+// tab-width: 4 //
+// End: //
Index: tests/.expect/strstream.txt
===================================================================
--- tests/.expect/strstream.txt	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
+++ tests/.expect/strstream.txt	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
@@ -0,0 +1,3 @@
+3 0x5          7 1.234568e+07 987.654n
+3 0x5          7 1.234568e+07 987.654n
+3 0x5          7 1.234568e+07 987.654n
Index: tests/strstream.cfa
===================================================================
--- tests/strstream.cfa	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
+++ tests/strstream.cfa	(revision fec63b21f5efc819f13b798d37a05390d81a66ee)
@@ -0,0 +1,15 @@
+#include <fstream.hfa>
+#include <strstream.hfa>
+
+int main() {
+    enum { size = 256 };
+    char buf[size];
+    strstream sstr = { buf, size };
+    int i = 3, j = 5, k = 7;
+    double x = 12345678.9, y = 98765.4321e-11;
+
+    sstr | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y));
+    write( sstr );
+    printf( "%s", buf );
+    sout | i | hex(j) | wd(10, k) | sci(x) | unit(eng(y));
+}
