Index: libcfa/src/Makefile.am
===================================================================
--- libcfa/src/Makefile.am	(revision 4069faade93e68df42b8c7af24253b6a041b469b)
+++ libcfa/src/Makefile.am	(revision d45ed83c96c9b73e97d7e2a855ddc87c32d1559b)
@@ -39,5 +39,5 @@
 #----------------------------------------------------------------------------------------------------------------
 if BUILDLIB
-headers_nosrc = bitmanip.hfa math.hfa gmp.hfa time_t.hfa bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa
+headers_nosrc = bitmanip.hfa math.hfa gmp.hfa time_t.hfa bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa containers/list.hfa
 headers = fstream.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa time.hfa stdlib.hfa common.hfa \
 	  containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
Index: libcfa/src/containers/list.hfa
===================================================================
--- libcfa/src/containers/list.hfa	(revision d45ed83c96c9b73e97d7e2a855ddc87c32d1559b)
+++ libcfa/src/containers/list.hfa	(revision d45ed83c96c9b73e97d7e2a855ddc87c32d1559b)
@@ -0,0 +1,274 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2020 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// list -- lets a user-defined stuct form intrusive linked lists
+//
+// Author           : Michael Brooks
+// Created On       : Wed Apr 22 18:00:00 2020
+// Last Modified By : Michael Brooks
+// Last Modified On : Wed Apr 22 18:00:00 2020
+// Update Count     : 1
+//
+
+#include <assert.h>
+
+#define __DLISTED_MGD_COMMON(ELEM, NODE, LINKS_FLD) \
+static inline ELEM& $tempcv_n2e(NODE &node) { \
+	return node; \
+} \
+\
+static inline NODE& $tempcv_e2n(ELEM &node) { \
+	return node; \
+} \
+\
+static inline ELEM & ?`prev(NODE &node) { \
+    $dlinks(ELEM) & ls = node.LINKS_FLD; \
+	$mgd_link(ELEM) * l = &ls.prev; \
+	ELEM * e = l->elem; \
+	return *e; \
+} \
+\
+static inline ELEM & ?`next(NODE &node) { \
+    $dlinks(ELEM) & ls = node.LINKS_FLD; \
+	$mgd_link(ELEM) * l = &ls.next; \
+	ELEM * e = l->elem; \
+	return *e; \
+} \
+\
+static inline $mgd_link(ELEM) & $prev_link(NODE &node) { \
+    $dlinks(ELEM) & ls = node.LINKS_FLD; \
+	$mgd_link(ELEM) * l = &ls.prev; \
+	return *l; \
+} \
+\
+static inline $mgd_link(ELEM) & $next_link(NODE &node) { \
+    $dlinks(ELEM) & ls = node.LINKS_FLD; \
+	$mgd_link(ELEM) * l = &ls.next; \
+	return *l; \
+}
+
+#define __DLISTED_MGD_JUSTEXPL(STRUCT, IN_THELIST, STRUCT_IN_THELIST) \
+struct STRUCT_IN_THELIST { \
+	inline STRUCT; \
+}; \
+\
+void ?{}(STRUCT_IN_THELIST &) = void; \
+\
+static inline STRUCT_IN_THELIST& ?`IN_THELIST(STRUCT &this) { \
+	return (STRUCT_IN_THELIST&)this; \
+}
+
+#define __DLISTED_MGD_JUSTIMPL(STRUCT)
+
+forall( dtype tE ) {
+	struct $mgd_link {
+		tE *elem;
+		void *terminator;
+		_Bool is_terminator;
+		// will collapse to single pointer with tag bit
+	};
+	inline void ?{}( $mgd_link(tE) &this, tE* elem ) {
+		(this.elem){ elem };
+		(this.terminator){ 0p };
+		(this.is_terminator){ 0 };
+	}
+	inline void ?{}( $mgd_link(tE) &this, void * terminator ) {
+		(this.elem){ 0p };
+		(this.terminator){ terminator };
+		(this.is_terminator){ 1 };
+	}
+	forall ( otype tInit | { void ?{}( $mgd_link(tE) &, tInit); } )
+	void ?=?( $mgd_link(tE) &this, tInit i ) {
+		^?{}( this );
+		?{}( this, i );
+	}
+	struct $dlinks {
+		// containing item is not listed
+		// iff
+		// links have (elem == 0p && terminator == 0p)
+		$mgd_link(tE) next;
+		$mgd_link(tE) prev;
+	};
+	inline void ?{}( $dlinks(tE) &this ) {
+		(this.next){ (tE *)0p };
+		(this.prev){ (tE *)0p };
+	}
+}
+
+#define DLISTED_MGD_EXPL_IN(STRUCT, LIST_SUF) \
+  $dlinks(STRUCT) $links_ ## LIST_SUF;
+
+#define DLISTED_MGD_EXPL_OUT(STRUCT, LIST_SUF) \
+  __DLISTED_MGD_JUSTEXPL(STRUCT, in_##LIST_SUF, STRUCT ## _in_ ## LIST_SUF) \
+  __DLISTED_MGD_COMMON(STRUCT, STRUCT##_in_##LIST_SUF,  $links_ ## LIST_SUF)
+
+#define DLISTED_MGD_IMPL_IN(STRUCT) \
+  $dlinks(STRUCT) $links;
+
+#define DLISTED_MGD_IMPL_OUT(STRUCT) \
+  __DLISTED_MGD_JUSTIMPL(STRUCT) \
+  __DLISTED_MGD_COMMON(STRUCT, STRUCT, $links)
+
+trait $dlistable(dtype Tnode, dtype Telem) {
+	$mgd_link(Telem) & $prev_link(Tnode &);
+	$mgd_link(Telem) & $next_link(Tnode &);
+	Telem& $tempcv_n2e(Tnode &);
+	Tnode& $tempcv_e2n(Telem &);
+};
+
+forall (dtype Tnode, dtype Telem | $dlistable(Tnode, Telem)) {
+
+	// implemented as a sentinel item in an underlying cicrular list
+	// theList.$links.next is first
+	// theList.$links.prev is last
+	// note this allocation preserves prev-next composition as an identity
+	struct dlist {
+		$dlinks(Telem) $links;
+	};
+
+	// an empty dlist
+	// links refer to self, making a tight circle
+	void ?{}( dlist(Tnode, Telem) & this ) {
+		$mgd_link(Telem) selfRef = (void *) &this;
+		( this.$links ) { selfRef, selfRef };
+	}
+
+	Telem & ?`first( dlist(Tnode, Telem) &l ) {
+		return * l.$links.next.elem;
+	}
+
+	Telem & ?`last( dlist(Tnode, Telem) &l ) {
+		return * l.$links.prev.elem;
+	}
+
+	static inline void insert_after(Tnode &list_pos, Telem &to_insert) {
+		assert (&list_pos != 0p);
+		assert (&to_insert != 0p);
+		Tnode &singleton_to_insert = $tempcv_e2n(to_insert);
+		assert($prev_link(singleton_to_insert).elem == 0p);
+		assert($next_link(singleton_to_insert).elem == 0p);
+		$prev_link(singleton_to_insert) = & $tempcv_n2e(list_pos);
+		$next_link(singleton_to_insert) = $next_link(list_pos).elem;
+		if ($next_link(list_pos).is_terminator) {
+			dlist(Tnode, Telem) *list = $next_link(list_pos).terminator;
+			$dlinks(Telem) *list_links = & list->$links;
+			$mgd_link(Telem) *list_last = & list_links->prev;
+			*list_last = &to_insert;
+		} else {
+			Telem *list_pos_next = $next_link(list_pos).elem;
+			if (list_pos_next) {
+				Tnode & lpn_inlist = $tempcv_e2n(*list_pos_next);
+				$prev_link(lpn_inlist) = &to_insert;
+			}
+		}
+		$next_link(list_pos) = &to_insert;
+	}
+
+	static inline void insert_before(Tnode &list_pos, Telem &to_insert) {
+		assert (&list_pos != 0p);
+		assert (&to_insert != 0p);
+		Tnode &singleton_to_insert = $tempcv_e2n(to_insert);
+		assert($prev_link(singleton_to_insert).elem == 0p);
+		assert($next_link(singleton_to_insert).elem == 0p);
+		$next_link(singleton_to_insert) = & $tempcv_n2e(list_pos);
+		$prev_link(singleton_to_insert) = $prev_link(list_pos).elem;
+		if ($prev_link(list_pos).is_terminator) {
+			dlist(Tnode, Telem) *list = $prev_link(list_pos).terminator;
+			$dlinks(Telem) *list_links = & list->$links;
+			$mgd_link(Telem) *list_first = & list_links->next;
+			*list_first = &to_insert;
+		} else {
+			Telem *list_pos_prev = $prev_link(list_pos).elem;
+			if (list_pos_prev) {
+				Tnode & lpp_inlist = $tempcv_e2n(*list_pos_prev);
+				$next_link(lpp_inlist) = &to_insert;
+			}
+		}
+		$prev_link(list_pos) = &to_insert;
+	}
+
+    static inline void insert_first(dlist(Tnode, Telem) &list, Telem &to_insert) {
+		assert (&list != 0p);
+		assert (&to_insert != 0p);
+		Tnode &singleton_to_insert = $tempcv_e2n(to_insert);
+		assert($prev_link(singleton_to_insert).elem == 0p);
+		assert($next_link(singleton_to_insert).elem == 0p);
+
+		$prev_link(singleton_to_insert) = (void*) &list;
+		$next_link(singleton_to_insert) = list.$links.next;
+
+		$dlinks(Telem) *listLinks = & list.$links;
+		if (listLinks->next.is_terminator) {
+			$mgd_link(Telem) * listPrevReference = & listLinks->prev;
+			*listPrevReference = &to_insert;
+		} else {
+			Tnode & next_inlist = $tempcv_e2n(*list.$links.next.elem);
+			$prev_link(next_inlist) = &to_insert;
+		}
+		$mgd_link(Telem) * listNextReference = & listLinks->next;
+		*listNextReference = &to_insert;
+	}
+
+    static inline void insert_last(dlist(Tnode, Telem) &list, Telem &to_insert) {
+		assert (&list != 0p);
+		assert (&to_insert != 0p);
+		Tnode &singleton_to_insert = $tempcv_e2n(to_insert);
+		assert($next_link(singleton_to_insert).elem == 0p);
+		assert($prev_link(singleton_to_insert).elem == 0p);
+
+		$next_link(singleton_to_insert) = (void*) &list;
+		$prev_link(singleton_to_insert) = list.$links.prev;
+
+		$dlinks(Telem) *listLinks = & list.$links;
+		if (listLinks->prev.is_terminator) {
+			$mgd_link(Telem) * listNextReference = & listLinks->next;
+			*listNextReference = &to_insert;
+		} else {
+			Tnode & prev_inlist = $tempcv_e2n(*list.$links.prev.elem);
+			$next_link(prev_inlist) = &to_insert;
+		}
+		$mgd_link(Telem) * listPrevReference = & listLinks->prev;
+		*listPrevReference = &to_insert;
+	}
+
+    static inline void remove(Tnode &list_pos) {
+		assert( &list_pos != 0p );
+
+		$mgd_link(Telem) &incoming_from_prev = *0p;
+		$mgd_link(Telem) &incoming_from_next = *0p;
+
+		if ( $prev_link(list_pos).is_terminator ) {
+			dlist(Tnode, Telem) * tgt_before = $prev_link(list_pos).terminator;
+			$dlinks(Telem) * links_before = & tgt_before->$links;
+			&incoming_from_prev = & links_before->next;
+		} else if ($prev_link(list_pos).elem) {
+			Telem * tgt_before = $prev_link(list_pos).elem;
+			Tnode & list_pos_before = $tempcv_e2n(*tgt_before);
+			&incoming_from_prev = & $next_link(list_pos_before);
+		}
+
+		if ( $next_link(list_pos).is_terminator ) {
+			dlist(Tnode, Telem) * tgt_after = $next_link(list_pos).terminator;
+			$dlinks(Telem) * links_after = & tgt_after->$links;
+			&incoming_from_next = & links_after->prev;
+		} else if ($next_link(list_pos).elem) {
+			Telem * tgt_after  = $next_link(list_pos).elem;
+			Tnode & list_pos_after  = $tempcv_e2n(*tgt_after );
+			&incoming_from_next = & $prev_link(list_pos_after );
+		}
+
+		if (& incoming_from_prev) {
+			incoming_from_prev = $next_link(list_pos);
+		}
+		if (& incoming_from_next) {
+			incoming_from_next = $prev_link(list_pos);
+		}
+
+		$next_link(list_pos) = (Telem*) 0p;
+		$prev_link(list_pos) = (Telem*) 0p;
+	}
+}
+
Index: libcfa/src/iostream.cfa
===================================================================
--- libcfa/src/iostream.cfa	(revision 4069faade93e68df42b8c7af24253b6a041b469b)
+++ libcfa/src/iostream.cfa	(revision d45ed83c96c9b73e97d7e2a855ddc87c32d1559b)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Apr 26 20:31:36 2020
-// Update Count     : 985
+// Last Modified On : Thu Apr 30 10:50:31 2020
+// Update Count     : 1001
 //
 
@@ -463,21 +463,37 @@
 			int bits = high1( f.val );					/* position of most significant bit */ \
 			if ( bits == 0 ) bits = 1;					/* 0 value => force one bit to print */ \
-			int spaces = f.wd - bits;					/* can be negative */ \
-			if ( ! f.flags.nobsdp ) { spaces -= 2; }	/* base prefix takes space */ \
-			/* printf( "%d %d\n", bits, spaces ); */ \
+			int spaces; \
 			if ( ! f.flags.left ) {						/* right justified ? */ \
 				/* Note, base prefix then zero padding or spacing then prefix. */ \
-				if ( f.flags.pad0 || f.flags.pc ) { \
+				if ( f.flags.pc ) { \
+					spaces = f.wd - f.pc; \
+					if ( ! f.flags.nobsdp ) { spaces -= 2; } /* base prefix takes space */ \
+					if ( spaces > 0 ) fmt( os, "%*s", spaces, " " ); /* space pad */ \
 					if ( ! f.flags.nobsdp ) { fmt( os, "0%c", f.base ); } \
-					if ( f.flags.pc ) spaces = f.pc - bits; \
+					spaces = f.pc - bits; \
 					if ( spaces > 0 ) fmt( os, "%0*d", spaces, 0 ); /* zero pad */ \
 				} else { \
-					if ( spaces > 0 ) fmt( os, "%*s", spaces, " " ); /* space pad */ \
-					if ( ! f.flags.nobsdp ) { fmt( os, "0%c", f.base ); } \
+					spaces = f.wd - bits; \
+					if ( ! f.flags.nobsdp ) { spaces -= 2; } /* base prefix takes space */ \
+					if ( f.flags.pad0 ) { \
+						if ( ! f.flags.nobsdp ) { fmt( os, "0%c", f.base ); } \
+						if ( spaces > 0 ) fmt( os, "%0*d", spaces, 0 ); /* zero pad */ \
+					} else { \
+						if ( spaces > 0 ) fmt( os, "%*s", spaces, " " ); /* space pad */ \
+						if ( ! f.flags.nobsdp ) { fmt( os, "0%c", f.base ); } \
+					} /* if */ \
 				} /* if */ \
-			} else if ( ! f.flags.nobsdp ) { \
-				fmt( os, "0%c", f.base ); \
+			} else { \
+				if ( ! f.flags.nobsdp ) fmt( os, "0%c", f.base ); \
+				if ( f.flags.pc ) { \
+					spaces = f.pc - bits; \
+					if ( spaces > 0 ) fmt( os, "%0*d", spaces, 0 ); /* zero pad */ \
+					spaces = f.wd - f.pc; \
+				} else { /* pad0 flag ignored with left flag */ \
+					spaces = f.wd - bits; \
+				} /* if */ \
+				if ( ! f.flags.nobsdp ) { spaces -= 2; } /* base prefix takes space */ \
 			} /* if */ \
-			int shift = (bits - 1) / 4 * 4; /* floor( bits - 1, 4 ) */ \
+			int shift = floor( bits - 1, 4 ); \
 			typeof( f.val ) temp = f.val; \
 			fmt( os, "%s", shortbin[(temp >> shift) & 0xf] ); \
@@ -599,5 +615,5 @@
 						fmt.wd = 0; \
 						/* if ( fmt2.val > 1 && fmt.flags.pc && fmt.pc > 0 ) fmt.pc -= 1; */ \
-						/* printf( "L %llo %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt2.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
+						/* printf( "L %llo %llo %llo %d %d '%c' %x %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all, fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
 						(ostype &)(os | fmt | "" | fmt2); \
 						sepOff( os ); \
@@ -605,5 +621,5 @@
 						int msigd = ceiling( high1( fmt.val ), 3 ) + 1; \
 						fmt2.wd = f.wd - (fmt.pc > msigd ? fmt.pc : msigd) - 1; \
-						if ( fmt2.wd < 21 ) fmt2.wd = 21; \
+						if ( (int)fmt2.wd < 21 ) fmt2.wd = 21; /* cast deals with negative value */ \
 						fmt2.flags.pc = true; fmt2.pc = 21; \
 					} else { \
@@ -612,5 +628,5 @@
 						/*if ( ! fmt.flags.nobsdp && fmt.pc < fmt.wd ) fmt.wd -= 1;*/ \
 						fmt2.wd = 1; \
-						/* printf( "R %llo %llo %llo %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt2.val, fmt.wd, fmt.pc, fmt.base, fmt.all ); */ \
+						/* printf( "R %llo %llo %llo %d %d '%c' %x %llo %d %d '%c' %x\n", msig, lsig, fmt.val, fmt.wd, fmt.pc, fmt.base, fmt.all, fmt2.val, fmt2.wd, fmt2.pc, fmt2.base, fmt2.all ); */ \
 						(ostype &)(os | fmt | "" | fmt2); \
 						sepOff( os ); \
