Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/GenPoly/Box.cc	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -25,5 +25,4 @@
 #include "PolyMutator.h"
 #include "FindFunction.h"
-#include "ScopedMap.h"
 #include "ScrubTyVars.h"
 
@@ -38,4 +37,6 @@
 
 #include "ResolvExpr/TypeEnvironment.h"
+#include "ResolvExpr/TypeMap.h"
+#include "ResolvExpr/typeops.h"
 
 #include "SymTab/Mangler.h"
@@ -73,6 +74,8 @@
 			/// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
 			Expression *makeOffsetArray( StructInstType *type );
+			/// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
+			void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
 			/// passes extra type parameters into a polymorphic function application
-			void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
+			void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
 			/// wraps a function application with a new temporary for the out-parameter return value
 			Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
@@ -99,5 +102,5 @@
 			typedef std::map< std::string, DeclarationWithType *> AdapterMap;
 			std::map< std::string, DeclarationWithType *> assignOps;
-			ScopedMap< std::string, DeclarationWithType *> scopedAssignOps;
+			ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;
 			std::stack< AdapterMap > adapters;
 			DeclarationWithType *retval;
@@ -246,12 +249,12 @@
 		}
 
-		/// returns T if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be), NULL otherwise
-		ReferenceToType *isAssignment( DeclarationWithType *decl ) {
+		/// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
+		TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) {
 			if ( decl->get_name() == "?=?" ) {
 				if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
 					if ( funType->get_parameters().size() == 2 ) {
 						if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
-							if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( pointer->get_base() ) ) {
-								if ( ReferenceToType *refType2 = dynamic_cast< ReferenceToType *>( funType->get_parameters().back()->get_type() ) ) {
+							if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
+								if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
 									if ( refType->get_name() == refType2->get_name() ) {
 										return refType;
@@ -265,4 +268,30 @@
 			return 0;
 		}
+		
+		/// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
+		/// Only picks assignments where neither parameter is cv-qualified
+		Type *isAssignment( DeclarationWithType *decl ) {
+			if ( decl->get_name() == "?=?" ) {
+				if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
+					if ( funType->get_parameters().size() == 2 ) {
+						Type::Qualifiers defaultQualifiers;
+						Type *paramType1 = funType->get_parameters().front()->get_type();
+						if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0;
+						Type *paramType2 = funType->get_parameters().back()->get_type();
+						if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
+						
+						if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
+							Type *baseType1 = pointerType->get_base();
+							if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0;
+							SymTab::Indexer dummy;
+							if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) {
+								return baseType1;
+							} // if
+						} // if
+					} // if
+				} // if
+			} // if
+			return 0;
+		}
 
 		void Pass1::findAssignOps( const std::list< TypeDecl *> &forall ) {
@@ -272,5 +301,5 @@
 				for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
 					std::string typeName;
-					if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert ) ) ) {
+					if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) {
 						assignOps[ typeInst->get_name() ] = *assert;
 					} // if
@@ -281,7 +310,7 @@
 		DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
 			// if this is a polymorphic assignment function, put it in the map for this scope
-			if ( ReferenceToType *refType = isAssignment( functionDecl ) ) {
-				if ( ! dynamic_cast< TypeInstType* >( refType ) ) {
-					scopedAssignOps.insert( refType->get_name(), functionDecl );
+			if ( Type *assignedType = isAssignment( functionDecl ) ) {
+				if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) {
+					scopedAssignOps.insert( assignedType, functionDecl );
 				}
 			}
@@ -398,5 +427,28 @@
 		}
 
-		void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
+		void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
+			Type *polyBase = hasPolyBase( parmType, exprTyVars );
+			if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
+				std::string sizeName = sizeofName( polyBase );
+				if ( seenTypes.count( sizeName ) ) return;
+
+				arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
+				arg++;
+				arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
+				arg++;
+				if ( dynamic_cast< StructInstType* >( polyBase ) ) {
+					if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
+						arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
+						arg++;
+					} else {
+						throw SemanticError( "Cannot pass non-struct type for generic struct" );
+					}
+				}
+
+				seenTypes.insert( sizeName );
+			}
+		}
+
+		void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
 			// pass size/align for type variables
 			for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
@@ -424,28 +476,16 @@
 			std::list< Expression* >::const_iterator fnArg = arg;
 			std::set< std::string > seenTypes; //< names for generic types we've seen
+
+			// a polymorphic return type may need to be added to the argument list
+			if ( polyRetType ) {
+				Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
+				passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
+			}
+			
+			// add type information args for presently unseen types in parameter list
 			for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
-				Type *polyBase = hasPolyBase( (*fnParm)->get_type(), exprTyVars );
-				if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
-					std::string sizeName = sizeofName( polyBase );
-					if ( seenTypes.count( sizeName ) ) continue;
-
-					VariableExpr *fnArgBase = getBaseVar( *fnArg );
-					assert( fnArgBase && ! fnArgBase->get_results().empty() );
-					Type *argBaseType = fnArgBase->get_results().front();
-					arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
-					arg++;
-					arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
-					arg++;
-					if ( dynamic_cast< StructInstType* >( polyBase ) ) {
-						if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
-							arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
-							arg++;
-						} else {
-							throw SemanticError( "Cannot pass non-struct type for generic struct" );
-						}
-					}
-
-					seenTypes.insert( sizeName );
-				}
+				VariableExpr *fnArgBase = getBaseVar( *fnArg );
+				if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue;
+				passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes );
 			}
 		}
@@ -470,6 +510,7 @@
 			ObjectDecl *newObj = makeTemporary( retType->clone() );
 			Expression *paramExpr = new VariableExpr( newObj );
-			// If the type of the temporary is not polymorphic, box temporary by taking its address; otherwise the
-			// temporary is already boxed and can be used directly.
+
+			// If the type of the temporary is not polymorphic, box temporary by taking its address;
+			// otherwise the temporary is already boxed and can be used directly.
 			if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) {
 				paramExpr = new AddressExpr( paramExpr );
@@ -520,4 +561,5 @@
 			assert( env );
 			Type *concrete = replaceWithConcrete( appExpr, polyType );
+			// add out-parameter for return value	
 			return addRetParam( appExpr, function, concrete, arg );
 		}
@@ -542,6 +584,6 @@
 			assert( ! arg->get_results().empty() );
 			if ( isPolyType( param, exprTyVars ) ) {
-				if ( dynamic_cast< TypeInstType *>( arg->get_results().front() ) ) {
-					// if the argument's type is a type parameter, we don't need to box again!
+				if ( isPolyType( arg->get_results().front() ) ) {
+					// if the argument's type is polymorphic, we don't need to box again!
 					return;
 				} else if ( arg->get_results().front()->get_isLvalue() ) {
@@ -622,5 +664,5 @@
 			assert( arg );
 			if ( isPolyType( realParam->get_type(), tyVars ) ) {
-				if ( dynamic_cast<TypeInstType *>(arg->get_type()) == NULL ) {
+				if ( ! isPolyType( arg->get_type() ) ) {
 					UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
 					deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
@@ -917,6 +959,10 @@
 			std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
 
-			if ( ReferenceToType *polyType = isPolyRet( function ) ) {
-				ret = addPolyRetParam( appExpr, function, polyType, arg );
+			TyVarMap exprTyVars;
+			makeTyVarMap( function, exprTyVars );
+			ReferenceToType *polyRetType = isPolyRet( function );
+
+			if ( polyRetType ) {
+				ret = addPolyRetParam( appExpr, function, polyRetType, arg );
 			} else if ( needsAdapter( function, scopeTyVars ) ) {
 				// std::cerr << "needs adapter: ";
@@ -930,8 +976,5 @@
 			arg = appExpr->get_args().begin();
 
-			TyVarMap exprTyVars;
-			makeTyVarMap( function, exprTyVars );
-
-			passTypeVars( appExpr, arg, exprTyVars );
+			passTypeVars( appExpr, polyRetType, arg, exprTyVars );
 			addInferredParams( appExpr, function, arg, exprTyVars );
 
@@ -992,4 +1035,13 @@
 		}
 
+		/// Wraps a function declaration in a new pointer-to-function variable expression
+		VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {
+			// line below cloned from FixFunction.cc
+			ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
+			                                          new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
+			functionObj->set_mangleName( functionDecl->get_mangleName() );
+			return new VariableExpr( functionObj );
+		}
+		
 		Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
 			if ( retval && returnStmt->get_expr() ) {
@@ -1007,26 +1059,63 @@
 
 				// find assignment operator for (polymorphic) return type
-				DeclarationWithType *assignDecl = 0;
+				ApplicationExpr *assignExpr = 0;
 				if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
+					// find assignment operator for type variable
 					std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
 					if ( assignIter == assignOps.end() ) {
 						throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
 					} // if
-					assignDecl = assignIter->second;
+					assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
 				} else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
-					ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = scopedAssignOps.find( refType->get_name() );
-					if ( assignIter == scopedAssignOps.end() ) {
+					// find assignment operator for generic type
+					DeclarationWithType *functionDecl = scopedAssignOps.find( refType );
+					if ( ! functionDecl ) {
 						throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
 					}
-					DeclarationWithType *functionDecl = assignIter->second;
-					// line below cloned from FixFunction.cc
-					assignDecl = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
-					                             new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
-					assignDecl->set_mangleName( functionDecl->get_mangleName() );
+
+					// wrap it up in an application expression
+					assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) );
+					assignExpr->set_env( env->clone() );
+
+					// find each of its needed secondary assignment operators
+					std::list< Expression* > &tyParams = refType->get_parameters();
+					std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall();
+					std::list< Expression* >::const_iterator tyIt = tyParams.begin();
+					std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
+					for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
+						if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype)
+
+						std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
+						assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
+						DeclarationWithType *actualDecl = asserts.front();
+						TypeInstType *actualType = isTypeInstAssignment( actualDecl );
+						assert( actualType && "First assertion of type with assertions should be assignment operator" );
+						TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
+						assert( formalTypeExpr && "type parameters must be type expressions" );
+						Type *formalType = formalTypeExpr->get_type();
+						assignExpr->get_env()->add( actualType->get_name(), formalType );
+						
+						DeclarationWithType *assertAssign = 0;
+						if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
+							std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
+							if ( assertAssignIt == assignOps.end() ) {
+								throw SemanticError( "No assignment operation found for ", formalTypeInstType );
+							}
+							assertAssign = assertAssignIt->second;
+						} else {
+							assertAssign = scopedAssignOps.find( formalType );
+							if ( ! assertAssign ) {
+								throw SemanticError( "No assignment operation found for ", formalType );
+							}
+						}
+						
+
+						assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
+							= ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
+					}
 				}
-				assert( assignDecl );
+				assert( assignExpr );
 
 				// replace return statement with appropriate assignment to out parameter
-				ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) );
 				Expression *retParm = new NameExpr( retval->get_name() );
 				retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
@@ -1180,5 +1269,5 @@
 			}
 
-			// add size/align for generic types to parameter list
+			// add size/align for generic parameter types to parameter list
 			std::set< std::string > seenTypes; // sizeofName for generic types we've seen
 			for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
@@ -1295,5 +1384,6 @@
 
 				if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
-					if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
+					if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty()
+					     || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
 					else continue;
 				} else return i;
@@ -1341,4 +1431,5 @@
 			if ( ! objectType ) return memberExpr;
 
+			Expression *newMemberExpr = 0;
 			if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
 				// look up offset index
@@ -1350,13 +1441,22 @@
 				fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) );
 				fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
-
-				delete memberExpr;
-				return fieldLoc;
-			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {
+				newMemberExpr = fieldLoc;
+			} else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
 				// union members are all at offset zero, so build appropriately-dereferenced variable
-				Expression *derefdVar = makeDerefdVar( varExpr->clone(), varDepth );
-				delete memberExpr;
-				return derefdVar;
+				newMemberExpr = makeDerefdVar( varExpr->clone(), varDepth );
 			} else return memberExpr;
+			assert( newMemberExpr );
+
+			Type *memberType = memberExpr->get_member()->get_type();
+			if ( ! isPolyType( memberType, scopeTyVars ) ) {
+				// Not all members of a polymorphic type are themselves of polymorphic type; in this case the member expression should be wrapped and dereferenced to form an lvalue
+				CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) );
+				UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
+				derefExpr->get_args().push_back( ptrCastExpr );
+				newMemberExpr = derefExpr;
+			}
+
+			delete memberExpr;
+			return newMemberExpr;
 		}
 
@@ -1379,5 +1479,5 @@
 				delete offsetofExpr;
 				return offsetInd;
-			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( ty ) ) {
+			} else if ( dynamic_cast< UnionInstType* >( ty ) ) {
 				// all union members are at offset zero
 				delete offsetofExpr;
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// AlternativeFinder.cc -- 
+// AlternativeFinder.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Sat May 16 23:52:08 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul  3 17:58:39 2015
-// Update Count     : 22
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Feb 10 17:00:04 2016
+// Update Count     : 24
 //
 
@@ -41,5 +41,5 @@
 
 extern bool resolvep;
-#define PRINT( text ) if ( resolvep ) { text } 
+#define PRINT( text ) if ( resolvep ) { text }
 //#define DEBUG_COST
 
@@ -107,10 +107,10 @@
 					if ( candidate->cost < mapPlace->second.candidate->cost ) {
 						PRINT(
-							std::cout << "cost " << candidate->cost << " beats " << mapPlace->second.candidate->cost << std::endl;
+							std::cerr << "cost " << candidate->cost << " beats " << mapPlace->second.candidate->cost << std::endl;
 						)
 						selected[ mangleName ] = current;
 					} else if ( candidate->cost == mapPlace->second.candidate->cost ) {
 						PRINT(
-							std::cout << "marking ambiguous" << std::endl;
+							std::cerr << "marking ambiguous" << std::endl;
 						)
 						mapPlace->second.isAmbiguous = true;
@@ -122,5 +122,5 @@
 
 			PRINT(
-				std::cout << "there are " << selected.size() << " alternatives before elimination" << std::endl;
+				std::cerr << "there are " << selected.size() << " alternatives before elimination" << std::endl;
 			)
 
@@ -182,6 +182,6 @@
 			begin++;
 			PRINT(
-				std::cout << "findSubExprs" << std::endl;
-				printAlts( finder.alternatives, std::cout );
+				std::cerr << "findSubExprs" << std::endl;
+				printAlts( finder.alternatives, std::cerr );
 			)
 			*out++ = finder;
@@ -204,6 +204,6 @@
 		}
 		PRINT(
-			std::cout << "alternatives before prune:" << std::endl;
-			printAlts( alternatives, std::cout );
+			std::cerr << "alternatives before prune:" << std::endl;
+			printAlts( alternatives, std::cerr );
 		)
 		AltList::iterator oldBegin = alternatives.begin();
@@ -221,5 +221,5 @@
 		alternatives.erase( oldBegin, alternatives.end() );
 		PRINT(
-			std::cout << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
+			std::cerr << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
 		)
 	}
@@ -261,8 +261,8 @@
 		for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
 			PRINT(
-				std::cout << "actual expression:" << std::endl;
-				(*actualExpr)->print( std::cout, 8 );
-				std::cout << "--- results are" << std::endl;
-				printAll( (*actualExpr)->get_results(), std::cout, 8 );
+				std::cerr << "actual expression:" << std::endl;
+				(*actualExpr)->print( std::cerr, 8 );
+				std::cerr << "--- results are" << std::endl;
+				printAll( (*actualExpr)->get_results(), std::cerr, 8 );
 			)
 			std::list< DeclarationWithType* >::iterator startFormal = formal;
@@ -278,12 +278,12 @@
 				}
 				PRINT(
-					std::cout << std::endl << "converting ";
-					(*actual)->print( std::cout, 8 );
-					std::cout << std::endl << " to ";
-					(*formal)->get_type()->print( std::cout, 8 );
+					std::cerr << std::endl << "converting ";
+					(*actual)->print( std::cerr, 8 );
+					std::cerr << std::endl << " to ";
+					(*formal)->get_type()->print( std::cerr, 8 );
 				)
 				Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
 				PRINT(
-					std::cout << std::endl << "cost is" << newCost << std::endl;
+					std::cerr << std::endl << "cost is" << newCost << std::endl;
 				)
 
@@ -323,12 +323,12 @@
 		for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
 			PRINT(
-				std::cout << std::endl << "converting ";
-				assert->second.actualType->print( std::cout, 8 );
-				std::cout << std::endl << " to ";
-				assert->second.formalType->print( std::cout, 8 );
+				std::cerr << std::endl << "converting ";
+				assert->second.actualType->print( std::cerr, 8 );
+				std::cerr << std::endl << " to ";
+				assert->second.formalType->print( std::cerr, 8 );
 				)
 				Cost newCost = conversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
 			PRINT(
-				std::cout << std::endl << "cost of conversion is " << newCost << std::endl;
+				std::cerr << std::endl << "cost of conversion is " << newCost << std::endl;
 				)
 				if ( newCost == Cost::infinity ) {
@@ -448,10 +448,10 @@
 		std::list< DeclarationWithType* > candidates;
 		decls.lookupId( curDecl->get_name(), candidates );
-///   if ( candidates.empty() ) { std::cout << "no candidates!" << std::endl; }
+///   if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; }
 		for ( std::list< DeclarationWithType* >::const_iterator candidate = candidates.begin(); candidate != candidates.end(); ++candidate ) {
 			PRINT(
-				std::cout << "inferRecursive: candidate is ";
-				(*candidate)->print( std::cout );
-				std::cout << std::endl;
+				std::cerr << "inferRecursive: candidate is ";
+				(*candidate)->print( std::cerr );
+				std::cerr << std::endl;
 			)
 			AssertionSet newHave, newerNeed( newNeed );
@@ -482,9 +482,9 @@
 				varExpr->get_results().push_front( adjType->clone() );
 				PRINT(
-					std::cout << "satisfying assertion " << curDecl->get_uniqueId() << " ";
-					curDecl->print( std::cout );
-					std::cout << " with declaration " << (*candidate)->get_uniqueId() << " ";
-					(*candidate)->print( std::cout );
-					std::cout << std::endl;
+					std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
+					curDecl->print( std::cerr );
+					std::cerr << " with declaration " << (*candidate)->get_uniqueId() << " ";
+					(*candidate)->print( std::cerr );
+					std::cerr << std::endl;
 				)
 				ApplicationExpr *appExpr = static_cast< ApplicationExpr* >( newerAlt.expr );
@@ -501,13 +501,13 @@
 	void AlternativeFinder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
 //	PRINT(
-//	    std::cout << "inferParameters: assertions needed are" << std::endl;
-//	    printAll( need, std::cout, 8 );
+//	    std::cerr << "inferParameters: assertions needed are" << std::endl;
+//	    printAll( need, std::cerr, 8 );
 //	    )
 		SymTab::Indexer decls( indexer );
 		PRINT(
-			std::cout << "============= original indexer" << std::endl;
-			indexer.print( std::cout );
-			std::cout << "============= new indexer" << std::endl;
-			decls.print( std::cout );
+			std::cerr << "============= original indexer" << std::endl;
+			indexer.print( std::cerr );
+			std::cerr << "============= new indexer" << std::endl;
+			decls.print( std::cerr );
 		)
 		addToIndexer( have, decls );
@@ -515,5 +515,5 @@
 		inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
 //	PRINT(
-//	    std::cout << "declaration 14 is ";
+//	    std::cerr << "declaration 14 is ";
 //	    Declaration::declFromId
 //	    *out++ = newAlt;
@@ -532,6 +532,6 @@
 			makeExprList( actualAlt, appExpr->get_args() );
 			PRINT(
-				std::cout << "need assertions:" << std::endl;
-				printAssertionSet( resultNeed, std::cout, 8 );
+				std::cerr << "need assertions:" << std::endl;
+				printAssertionSet( resultNeed, std::cerr, 8 );
 			)
 			inferParameters( resultNeed, resultHave, newAlt, openVars, out );
@@ -543,5 +543,7 @@
 		AlternativeFinder funcOpFinder( indexer, env );
 
-		AlternativeFinder funcFinder( indexer, env ); {
+		AlternativeFinder funcFinder( indexer, env );
+
+		{
 			NameExpr *fname = 0;;
 			if ( ( fname = dynamic_cast<NameExpr *>( untypedExpr->get_function()))
@@ -573,6 +575,6 @@
 		for ( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
 			PRINT(
-				std::cout << "working on alternative: " << std::endl;
-				func->print( std::cout, 8 );
+				std::cerr << "working on alternative: " << std::endl;
+				func->print( std::cerr, 8 );
 			)
 			// check if the type is pointer to function
@@ -606,6 +608,6 @@
 					}
 					PRINT(
-						std::cout << "known function ops:" << std::endl;
-						printAlts( funcOpFinder.alternatives, std::cout, 8 );
+						std::cerr << "known function ops:" << std::endl;
+						printAlts( funcOpFinder.alternatives, std::cerr, 8 );
 					)
 				}
@@ -639,12 +641,12 @@
 				FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
 				assert( function );
-				std::cout << "Case +++++++++++++" << std::endl;
-				std::cout << "formals are:" << std::endl;
-				printAll( function->get_parameters(), std::cout, 8 );
-				std::cout << "actuals are:" << std::endl;
-				printAll( appExpr->get_args(), std::cout, 8 );
-				std::cout << "bindings are:" << std::endl;
-				withFunc->env.print( std::cout, 8 );
-				std::cout << "cost of conversion is:" << cvtCost << std::endl;
+				std::cerr << "Case +++++++++++++" << std::endl;
+				std::cerr << "formals are:" << std::endl;
+				printAll( function->get_parameters(), std::cerr, 8 );
+				std::cerr << "actuals are:" << std::endl;
+				printAll( appExpr->get_args(), std::cerr, 8 );
+				std::cerr << "bindings are:" << std::endl;
+				withFunc->env.print( std::cerr, 8 );
+				std::cerr << "cost of conversion is:" << cvtCost << std::endl;
 			)
 			if ( cvtCost != Cost::infinity ) {
@@ -824,5 +826,5 @@
 		}
 	}
-	
+
 	void AlternativeFinder::visit( UntypedOffsetofExpr *offsetofExpr ) {
 		AlternativeFinder funcFinder( indexer, env );
@@ -833,5 +835,5 @@
 		}
 	}
-	
+
 	void AlternativeFinder::visit( OffsetofExpr *offsetofExpr ) {
 		alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
@@ -843,9 +845,9 @@
 		assert( function->get_parameters().size() == 1 );
 		PRINT(
-			std::cout << "resolvAttr: funcDecl is ";
-			funcDecl->print( std::cout );
-			std::cout << " argType is ";
-			argType->print( std::cout );
-			std::cout << std::endl;
+			std::cerr << "resolvAttr: funcDecl is ";
+			funcDecl->print( std::cerr );
+			std::cerr << " argType is ";
+			argType->print( std::cerr );
+			std::cerr << std::endl;
 		)
 		if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/ResolvExpr/CastCost.cc	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 06:57:43 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Mon Oct 05 14:48:45 2015
-// Update Count     : 5
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Feb  2 15:34:36 2016
+// Update Count     : 7
 //
 
@@ -69,5 +69,6 @@
 		PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
 		if ( destAsPointer && basicType->isInteger() ) {
-			cost = Cost( 1, 0, 0 );
+			//cost = Cost( 1, 0, 0 );
+			cost = Cost::infinity;
 		} else {
 			ConversionCost::visit( basicType );
@@ -87,10 +88,12 @@
 					cost = Cost( 0, 0, 1 );
 				} else if ( castResult < 0 ) {
-					cost = Cost( 1, 0, 0 );
+					cost = Cost::infinity;
+					//cost = Cost( 1, 0, 0 );
 				} // if
 			} // if
 		} else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
 			if ( destAsBasic->isInteger() ) {
-				cost = Cost( 1, 0, 0 );
+				//cost = Cost( 1, 0, 0 );
+				cost = Cost::infinity;
 			} // if
 		}
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/ResolvExpr/Resolver.cc	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 12:17:01 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jul 24 17:33:54 2015
-// Update Count     : 178
+// Last Modified On : Tue Feb  9 21:57:52 2016
+// Update Count     : 179
 //
 
@@ -322,5 +322,5 @@
 												BasicType::SignedInt);
 				} else {
-					DeclarationWithType * decl = lookupId(n);
+					DeclarationWithType * decl = lookupId( n );
 					initContext = decl->get_type();
 				}
@@ -344,6 +344,5 @@
 					if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_results().front() ) ) {
 						if ( isCharType( pt->get_base() ) ) {
-							// strip cast if we're initializing a char[] with a char *, e.g.
-							// char x[] = "hello";
+							// strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
 							CastExpr *ce = dynamic_cast< CastExpr * >( newExpr );
 							singleInit->set_value( ce->get_arg() );
Index: src/ResolvExpr/TypeMap.h
===================================================================
--- src/ResolvExpr/TypeMap.h	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
+++ src/ResolvExpr/TypeMap.h	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -0,0 +1,212 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ScopedMap.h --
+//
+// Author           : Aaron B. Moss
+// Created On       : Fri Feb 19 13:55:00 2016
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Fri Feb 19 13:55:00 2016
+// Update Count     : 1
+//
+
+#ifndef _TYPEMAP_H
+#define _TYPEMAP_H
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "SynTree/Type.h"
+#include "SynTree/Visitor.h"
+
+namespace ResolvExpr {
+
+	/// A map from types to some value; lookup is done by structural decomposition on types.
+	/// The TypeMap stores its values by reference, so stored objects should be kept alive by the caller.
+	/// The scoping mechanism essentially by keeping a list of changes to roll back, then rolling them back
+	/// WARNING: This map is only incompletely and approximately consistent with the resolution rules in Unify.cc;
+	/// it has potential, if extended, to form the basis of a resolver that is more performant than the current
+	/// linear-search-by-unification approach, but is only currently used for finding assignment operators in GenPoly::box.
+	template< typename Value >
+	class TypeMap {
+		/// Map of names to types
+		typedef typename std::map< std::string, Value* > ValueMap;
+		typedef typename ValueMap::iterator ValueMapIterator;
+		
+		Value *voidValue;                                     ///< Value for void type
+		Value *basicValue[BasicType::NUMBER_OF_BASIC_TYPES];  ///< Values for basic types
+		Value *pointerValue;                                  ///< Value for all pointer types
+		Value *voidPointerValue;                              ///< Value for void* types
+		Value *functionPointerValue;                          ///< Value for all function pointer types
+		ValueMap structValue;                                 ///< Values for struct types, indexed by name
+		ValueMap unionValue;                                  ///< Values for struct types, indexed by name
+		ValueMap enumValue;                                   ///< Values for struct types, indexed by name
+
+		/// Information needed to roll back one scope change
+		struct Rollback {
+			/// One scope of pointer rollbacks
+			typedef std::vector< std::pair< Value **, Value* > > PointerScope;
+			/// One scope of map rollbacks
+			typedef std::vector< std::pair< ValueMapIterator, Value* > > MapScope;
+			
+			PointerScope pointers;  ///< Value pointers to roll back to their previous state
+			MapScope mapNodes;      ///< Value map iterators to roll back to their previous state
+
+			void addRollback( Value **loc, Value *old ) {
+				pointers.push_back( std::make_pair( loc, old ) );
+			}
+
+			void addRollback( ValueMapIterator loc, Value *old ) {
+				mapNodes.push_back( std::make_pair( loc, old ) );
+			}
+		};
+
+		std::vector< Rollback > scopes;  ///< Scope rollback information
+		
+		struct Lookup : public Visitor {
+			Lookup( TypeMap<Value> &typeMap ) : typeMap( typeMap ), found( 0 ), toInsert( 0 ) {}
+
+			/// Inserts a new value into the map; returns the old value (if set, NULL otherwise).
+			/// key must be non-null.
+			Value *insert( Type *key, Value *val ) {
+				toInsert = val;
+				key->accept( *this );
+				return found;
+			}
+
+			/// Looks up a value in the map.
+			/// key must be non-null.
+			Value *find( Type *key ) {
+				//toInsert = 0;
+				key->accept( *this );
+				return found;
+			}
+			
+			void findAndReplace( Value *&loc ) {
+				found = loc;
+				if ( toInsert ) {
+					typeMap.scopes.back().addRollback( &loc, found );
+					loc = toInsert;
+				}
+			}
+
+			void findAndReplace( ValueMap &map, const std::string &name ) {
+				ValueMapIterator loc = map.find( name );
+				if ( loc != map.end() ) {
+					found = loc->second;
+					if ( toInsert ) {
+						typeMap.scopes.back().addRollback( loc, found );
+						loc->second = toInsert;
+					}
+				} else if ( toInsert ) {
+					loc = map.insert( loc, std::make_pair( name, toInsert ) );
+					typeMap.scopes.back().addRollback( loc, found );
+				}
+			}
+			
+			virtual void visit( VoidType *voidType ) {
+				findAndReplace( typeMap.voidValue );
+			}
+			
+			virtual void visit( BasicType *basicType ) {
+				findAndReplace( typeMap.basicValue[basicType->get_kind()] );
+			}
+			
+			virtual void visit( PointerType *pointerType ) {
+				// NOTE This is one of the places where the apporoximation of the resolver is (deliberately) poor;
+				// A better version would likely not equate all pointer types to a match.
+				if ( dynamic_cast< FunctionType* >( pointerType->get_base() ) ) {
+					findAndReplace( typeMap.functionPointerValue );
+				} else if ( dynamic_cast< VoidType* >( pointerType->get_base() ) ) {
+					findAndReplace( typeMap.voidPointerValue );
+				} else {
+					findAndReplace( typeMap.pointerValue );
+				}
+			}
+			
+			virtual void visit( ArrayType *arrayType ) {
+				if ( dynamic_cast< FunctionType* >( arrayType->get_base() ) ) {
+					findAndReplace( typeMap.functionPointerValue );
+				} else {
+					findAndReplace( typeMap.pointerValue );
+				}
+			}
+			
+			virtual void visit( FunctionType *functionType ) {
+				findAndReplace( typeMap.functionPointerValue );
+			}
+			
+			virtual void visit( StructInstType *structType ) {
+				findAndReplace( typeMap.structValue, structType->get_name() );
+			}
+			
+			virtual void visit( UnionInstType *unionType ) {
+				findAndReplace( typeMap.unionValue, unionType->get_name() );
+			}
+			
+			virtual void visit( EnumInstType *enumType ) {
+				findAndReplace( typeMap.enumValue, enumType->get_name() );
+			}
+
+			TypeMap<Value> &typeMap;  ///< map storage
+			Value *found;             ///< Value found (NULL if none yet)
+			Value *toInsert;          ///< Value to insert (NULL if a lookup)
+		};  // class Lookup
+		friend class Lookup;
+		
+	public:
+		/// Starts a new scope
+		void beginScope() {
+			Rollback scope;
+			scopes.push_back(scope);
+		}
+
+		/// Ends a scope; rolls back any changes made during that scope
+		void endScope() {
+			Rollback &scope = scopes.back();
+			/// Roll back pointer changes
+			for (unsigned i = 0; i < scope.pointers.size(); ++i) {
+				*scope.pointers[i].first = scope.pointers[i].second;
+			}
+			/// Roll back map changes
+			for (unsigned i = 0; i < scope.mapNodes.size(); ++i) {
+				scope.mapNodes[i].first->second = scope.mapNodes[i].second;
+			}
+			scopes.pop_back();
+		}
+		
+		TypeMap() : voidValue( 0 ), pointerValue( 0 ), voidPointerValue( 0 ), functionPointerValue( 0 ), structValue(), unionValue(), enumValue(), scopes() {
+			beginScope();
+			for (int i = 0; i < BasicType::NUMBER_OF_BASIC_TYPES; ++i) { basicValue[i] = 0; }
+		}
+
+		/// Inserts a new value into the map; returns the old value (if set, NULL otherwise).
+		/// key, val must be non-null.
+		Value *insert( Type *key, Value *val ) {
+			Lookup searcher( *this );
+			return searcher.insert( key, val );
+		}
+
+		/// Looks up a value in the map.
+		/// key must be non-null
+		Value *find( Type *key ) {
+			Lookup searcher( *this );
+			return searcher.find( key );
+		}
+		
+	}; // class TypeMap
+
+}  // namespace ResolvExpr
+
+#endif // _TYPEMAP_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/SymTab/Validate.cc	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -382,5 +382,5 @@
 		// it's not a semantic error if the struct is not found, just an implicit forward declaration
 		if ( st ) {
-			assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
+			//assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
 			structInst->set_baseStruct( st );
 		} // if
@@ -659,4 +659,25 @@
 	}
 
+	/// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
+	TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
+		TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
+
+		if ( src->get_kind() == TypeDecl::Any ) {
+			// just include assignment operator assertion
+			TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
+			FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
+			assignFunctionType->get_returnVals().push_back(
+				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
+			assignFunctionType->get_parameters().push_back(
+				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
+			assignFunctionType->get_parameters().push_back(
+				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
+			FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
+			dst->get_assertions().push_back( assignAssert );
+		}
+
+		return dst;
+	}
+
 	Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
 		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
@@ -666,9 +687,12 @@
 		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
 		std::list< Expression* > structParams;  // List of matching parameters to put on types
+		TypeSubstitution genericSubs; // Substitutions to make to member types of struct
 		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
 			isGeneric = true;
-			TypeDecl *typeParam = (*param)->clone();
+			TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
 			assignType->get_forall().push_back( typeParam );
-			structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
+			TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
+			genericSubs.add( (*param)->get_name(), newParamType );
+			structParams.push_back( new TypeExpr( newParamType ) );
 		}
 
@@ -701,10 +725,24 @@
 				}
 
-				if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
-					makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
-					if ( isGeneric ) makeArrayAssignment( srcParam, returnVal, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+				if ( isGeneric ) {
+					// rewrite member type in terms of the type variables on this operator
+					DeclarationWithType *fixedMember = dwt->clone();
+					genericSubs.apply( fixedMember );
+
+					// assign to both destination and return value
+					if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
+						makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+						makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					} else {
+						makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
+						makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					} // if
 				} else {
-					makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
-					if ( isGeneric ) makeScalarAssignment( srcParam, returnVal, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					// assign to destination
+					if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
+						makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					} else {
+						makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					} // if
 				} // if
 			} // if
@@ -724,5 +762,5 @@
 		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
 			isGeneric = true;
-			TypeDecl *typeParam = (*param)->clone();
+			TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
 			assignType->get_forall().push_back( typeParam );
 			unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
Index: src/Tests/Makefile
===================================================================
--- src/Tests/Makefile	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/Tests/Makefile	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -8,5 +8,5 @@
 OUTPUTS = ${addprefix ${OUTPUTDIR}/,${EXAMPLES:.c=.txt}}
 
-.SILENT :
+#.SILENT :
 
 all :
@@ -19,5 +19,5 @@
 
 ${OUTPUTDIR}/%.txt : %.c ${CFA} Makefile
-	-${CFA} -n ${CFAOPT} < $< > $@ 2>&1
+	-${CFA} -n ${CFAOPT} $< > $@ 2>&1
 
 ${OUTPUTDIR}/report : ${OUTPUTS} ${EXPECTDIR}
Index: src/examples/abs.c
===================================================================
--- src/examples/abs.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/abs.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 18:26:16 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  3 11:14:58 2016
-// Update Count     : 43
+// Last Modified On : Wed Feb 17 09:32:04 2016
+// Update Count     : 44
 //
 
@@ -18,6 +18,4 @@
 
 int main( void ) {
-	ofstream *sout = ofstream_stdout();
-
 	char ch = -65;
 	sout | "char\t\t\t"					| ch     | "\tabs " | abs( ch ) | endl;
Index: src/examples/alloc.c
===================================================================
--- src/examples/alloc.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/alloc.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -11,6 +11,6 @@
 // Created On       : Wed Feb  3 07:56:22 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  3 16:32:04 2016
-// Update Count     : 38
+// Last Modified On : Wed Feb 17 11:43:23 2016
+// Update Count     : 40
 // 
 
@@ -27,6 +27,4 @@
 
 int main( void ) {
-    ofstream * sout = ofstream_stdout();
-
     size_t size = 10;
     int * p;
@@ -100,5 +98,4 @@
     free( x );
 #endif
-    free( sout );
 }
 
Index: src/examples/ato.c
===================================================================
--- src/examples/ato.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
+++ src/examples/ato.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -0,0 +1,56 @@
+//                               -*- Mode: C -*- 
+// 
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+// 
+// ato.c -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Thu Feb  4 08:10:57 2016
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb 17 11:44:03 2016
+// Update Count     : 42
+// 
+
+#include <fstream>
+#include <stdlib>										// ato, strto
+extern "C" {
+#include <stdio.h>
+#include <float.h>
+}
+
+int main( void ) {
+	int i = ato( "-123" );
+	sout | i | ' ' | "-123" | endl;
+	unsigned int ui = ato( "123" );
+	sout | ui | ' ' | "123" | endl;
+	long int li = ato( "-123" );
+	sout | li | ' ' | "-123" | endl;
+	unsigned long int uli = ato( "123" );
+	sout | uli | ' ' | "123" | endl;
+	long long int lli = ato( "-123" );
+	sout | lli | ' ' | "-123" | endl;
+	unsigned long long int ulli = ato( "123" );
+	sout | ulli | ' ' | "123" | endl;
+	float f = ato( "-123.456" );
+	sout | f | ' ' | "-123.456" | endl;
+	double d = ato( "-123.4567890123456" );
+	sout | d | ' ' | "-123.4567890123456" | endl;
+	long double ld = ato( "-123.45678901234567890123456789" );
+	sout | ld | ' ' | "-123.45678901234567890123456789" | endl;
+	float _Complex fc = ato( "-123.456-123.456i" );
+	sout | fc | ' ' | "-123.456-123.456i" | endl;
+	double _Complex dc = ato( "-123.4567890123456+123.4567890123456i" );
+	sout | dc | ' ' | "-123.4567890123456+123.4567890123456i" | endl;
+	long double _Complex ldc = ato( "123.45678901234567890123456789-123.45678901234567890123456789i" );
+	sout | ldc | ' ' | "123.45678901234567890123456789-123.45678901234567890123456789i" | endl;
+	long double _Complex ldc2 = ato( "123.45678901234-123.4567890i" );
+	sout | ldc2 | ' ' | "123.45678901234567890123456789-123.45678901234567890123456789i" | endl;
+} // main
+
+// Local Variables: //
+// tab-width: 4 //
+// compile-command: "cfa ato.c" //
+// End: //
Index: src/examples/fstream_test.c
===================================================================
--- src/examples/fstream_test.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/fstream_test.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:11:33 2016
-// Update Count     : 42
+// Last Modified On : Wed Feb 17 11:45:43 2016
+// Update Count     : 43
 //
 
@@ -17,6 +17,4 @@
 
 int main( void ) {
-	ofstream *sout = ofstream_stdout();
-	ifstream *sin = ifstream_stdin();
 	int nombre;
 	sout | "Entrez un nombre, s'il vous plaît:\n";
Index: src/examples/hello.c
===================================================================
--- src/examples/hello.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/hello.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:11:49 2016
-// Update Count     : 7
+// Last Modified On : Wed Feb 17 12:11:45 2016
+// Update Count     : 8
 //
 
@@ -17,6 +17,4 @@
 
 int main() {
-	ofstream *sout = ofstream_stdout();
-	ifstream *sin = ifstream_stdin();
 	sout | "Bonjour au monde!\n";
 }
Index: src/examples/identity.c
===================================================================
--- src/examples/identity.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/identity.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:11:58 2016
-// Update Count     : 8
+// Last Modified On : Wed Feb 17 12:17:32 2016
+// Update Count     : 10
 //
 
@@ -22,5 +22,4 @@
 
 int main() {
-	ofstream *sout = ofstream_stdout();
 	sout | "char\t\t\t"					| identity( 'z' ) | endl;
 	sout | "signed int\t\t"				| identity( 4 ) | endl;
@@ -30,7 +29,7 @@
 	sout | "signed long long int\t"		| identity( 4ll ) | endl;
 	sout | "unsigned long long int\t"	| identity( 4ull ) | endl;
-	sout | "float\t\t\t" 				| identity( 4.0f ) | endl;
-	sout | "double\t\t\t"				| identity( 4.0 ) | endl;
-	sout | "long double\t\t"			| identity( 4.0l ) | endl;
+	sout | "float\t\t\t" 				| identity( 4.1f ) | endl;
+	sout | "double\t\t\t"				| identity( 4.1 ) | endl;
+	sout | "long double\t\t"			| identity( 4.1l ) | endl;
 }
 
Index: src/examples/minmax.c
===================================================================
--- src/examples/minmax.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/minmax.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  3 11:14:49 2016
-// Update Count     : 46
+// Last Modified On : Wed Feb 17 12:17:53 2016
+// Update Count     : 47
 //
 
@@ -18,5 +18,4 @@
 
 int main( void ) {
-	ofstream *sout = ofstream_stdout();
 	// char does not have less or greater than.
 	int ?<?( char op1, char op2 ) { return (int)op1 < (int)op2; }
Index: src/examples/quad.c
===================================================================
--- src/examples/quad.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/quad.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:13:48 2016
-// Update Count     : 5
+// Last Modified On : Wed Feb 17 12:19:24 2016
+// Update Count     : 6
 //
 
@@ -27,5 +27,4 @@
 
 int main() {
-	ofstream *sout = ofstream_stdout();
 	int N = 2;
 	sout | "result of quad of " | N | " is " | quad( N ) | endl;
Index: src/examples/quoted_keyword.c
===================================================================
--- src/examples/quoted_keyword.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/quoted_keyword.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:13:58 2016
-// Update Count     : 8
+// Last Modified On : Wed Feb 17 12:19:45 2016
+// Update Count     : 9
 //
 
@@ -28,5 +28,4 @@
 
 int main() {
-	ofstream *sout = ofstream_stdout();
 	sout | `catch` + st.`type` + st.`struct` + `throw` | endl;
 }
Index: src/examples/random.c
===================================================================
--- src/examples/random.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/random.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -7,6 +7,4 @@
 
 int main() {
-	ofstream *sout = ofstream_stdout();
-
 	randseed( getpid() );								// set random seed
 
Index: src/examples/searchsort.c
===================================================================
--- src/examples/searchsort.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
+++ src/examples/searchsort.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -0,0 +1,82 @@
+//                               -*- Mode: C -*- 
+// 
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+// 
+// searchsort.c -- 
+// 
+// Author           : Peter A. Buhr
+// Created On       : Thu Feb  4 18:17:50 2016
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb 17 12:21:04 2016
+// Update Count     : 46
+// 
+
+#include <fstream>
+#include <stdlib>										// bsearch, qsort
+
+int main( void ) {
+	const unsigned int size = 10;
+	int iarr[size];
+
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		iarr[i] = size - i;
+		sout | iarr[i] | ", ";
+	} // for
+	sout | endl;
+	qsort( iarr, size );
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		sout | iarr[i] | ", ";
+	} // for
+	sout | endl;
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		int *v = bsearch( size - i, iarr, size );
+		sout | *v | ", ";
+	} // for
+	sout | endl | endl;
+
+	double darr[size];
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		darr[i] = size - i + 0.5;
+		sout | darr[i] | ", ";
+	} // for
+	sout | endl;
+	qsort( darr, size );
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		sout | darr[i] | ", ";
+	} // for
+	sout | endl;
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		double *v = bsearch( size - i + 0.5, darr, size );
+		sout | *v | ", ";
+	} // for
+	sout | endl | endl;
+
+	struct S { int i, j; } sarr[size];
+	int ?<?( S t1, S t2 ) { return t1.i < t2.i && t1.j < t2.j; }
+	ofstream * ?|?( ofstream * os, S v ) { return os | v.i | ' ' | v.j; }
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		sarr[i].i = size - i;
+		sarr[i].j = size - i + 1;
+		sout | sarr[i] | ", ";
+	} // for
+	sout | endl;
+	qsort( sarr, size );
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		sout | sarr[i] | ", ";
+	} // for
+	sout | endl;
+	for ( unsigned int i = 0; i < size; i += 1 ) {
+		S temp = { size - i, size - i + 1 };
+		S *v = bsearch( temp, sarr, size );
+		sout | *v | ", ";
+	} // for
+	sout | endl | endl;
+} // main
+
+// Local Variables: //
+// tab-width: 4 //
+// compile-command: "cfa searchsort.c" //
+// End: //
Index: src/examples/square.c
===================================================================
--- src/examples/square.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/square.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:14:16 2016
-// Update Count     : 25
+// Last Modified On : Wed Feb 17 12:21:58 2016
+// Update Count     : 26
 //
 
@@ -23,5 +23,4 @@
 int main() {
 #if 0
-	ofstream *sout = ofstream_stdout();
 	sout | "result of squaring 9 is " | endl;
 
Index: src/examples/sum.c
===================================================================
--- src/examples/sum.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/sum.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Feb  5 16:47:44 2016
-// Update Count     : 139
+// Last Modified On : Tue Feb 16 23:49:31 2016
+// Update Count     : 189
 //
 
@@ -33,59 +33,59 @@
 
 // Required to satisfy sumable as char does not have addition.
-// const char 0;
-// char ?+?( char op1, char op2 ) { return (int)op1 + op2; } // cast forces integer addition or recursion
-// char ++?( char *op ) { *op += 1; return *op; }
-// char ?++( char *op ) { char temp = *op; *op += 1; return temp; }
+const char 0;
+char ?+?( char t1, char t2 ) { return (int)t1 + t2; }	// cast forces integer addition, otherwise recursion
+char ?+=?( char *t1, char t2 ) { *t1 = *t1 + t2; return *t1; }
+char ++?( char *t ) { *t += 1; return *t; }
+char ?++( char *t ) { char temp = *t; *t += 1; return temp; }
 
 int main( void ) {
 	const int low = 5, High = 15, size = High - low;
-	ofstream *sout = ofstream_stdout();
-#if 0
 
-	char s = 0, a[size];
-	char v = low;
+	char s = 0, a[size], v = low;
 	for ( int i = 0; i < size; i += 1, v += 1 ) {
 		s += v;
 		a[i] = v;
-	}
+	} // for
 	sout | "sum from " | low | " to " | High | " is "
 		 | (int)sum( size, a ) | ", check " | (int)s | endl;
 
-	int s = 0, a[size];
-	int v = low;
+	int s = 0, a[size], v = low;
 	for ( int i = 0; i < size; i += 1, v += 1 ) {
 		s += (int)v;
 		a[i] = (int)v;
-	}
+	} // for
 	sout | "sum from " | low | " to " | High | " is "
 		 | sum( size, (int *)a ) | ", check " | (int)s | endl;
 
-	float s = 0.0, a[size];
-	float v = low / 10.0;
+	float s = 0.0, a[size], v = low / 10.0;
 	for ( int i = 0; i < size; i += 1, v += 0.1f ) {
 		s += (float)v;
 		a[i] = (float)v;
-	}
+	} // for
 	sout | "sum from " | low / 10.0 | " to " | High / 10.0 | " is "
 		 | sum( size, (float *)a ) | ", check " | (float)s | endl;
-#endif
-	double s = 0, a[size];
-	double v = low / 10.0;
 
+	double s = 0, a[size], v = low / 10.0;
 	for ( int i = 0; i < size; i += 1, v += 0.1 ) {
 		s += (double)v;
 		a[i] = (double)v;
-	}
+	} // for
 	sout | "sum from " | low / 10.0 | " to " | High / 10.0 | " is "
 		 | sum( size, (double *)a ) | ", check " | (double)s | endl;
 
-	// struct S { int i, j; } sarr[size];
-	// struct S 0 = { 0, 0 };
-	// struct S 1 = { 1, 1 };
-	// S ?+?( S t1, S t2 ) { S s = { t1.i + t1.j, t2.i + t2.j }; return s; }
-	// S ?+=?( S *t1, S t2 ) { *t1 = *t1 + t2; return *t1; }
-	// S ++?( S *t ) { *t += 1; return *t; }
-	// S ?++( S *t ) { S temp = *t; *t += 1; return temp; }
-	// sum( size, sarr );
+	struct S { int i, j; } 0 = { 0, 0 }, 1 = { 1, 1 };
+	S ?+?( S t1, S t2 ) { S s = { t1.i + t2.i, t1.j + t2.j }; return s; }
+	S ?+=?( S *t1, S t2 ) { *t1 = *t1 + t2; return *t1; }
+	S ++?( S *t ) { *t += 1; return *t; }
+	S ?++( S *t ) { S temp = *t; *t += 1; return temp; }
+	ofstream * ?|?( ofstream * os, S v ) { return os | v.i | ' ' | v.j; }
+
+	S s = 0, a[size], v = { low, low };
+	for ( int i = 0; i < size; i += 1, v += (S)1 ) {
+		s += (S)v;
+		a[i] = (S)v;
+	} // for
+	sout | "sum from " | low | " to " | High | " is "
+		 | sum( size, (S *)a ) | ", check " | (S)s | endl;
 } // main
 
Index: src/examples/swap.c
===================================================================
--- src/examples/swap.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/swap.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  3 11:14:04 2016
-// Update Count     : 63
+// Last Modified On : Wed Feb 17 12:22:12 2016
+// Update Count     : 64
 //
 
@@ -18,6 +18,4 @@
 
 int main( void ) {
-	ofstream *sout = ofstream_stdout();
-
 	char c1 = 'a', c2 = 'b';
 	sout | "char\t\t\t" | c1 | ' ' | c2 | "\t\t\tswap ";
Index: src/examples/twice.c
===================================================================
--- src/examples/twice.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/twice.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:14:44 2016
-// Update Count     : 12
+// Last Modified On : Wed Feb 17 12:23:25 2016
+// Update Count     : 13
 //
 
@@ -27,5 +27,4 @@
 	char ?++( char *op ) { char temp = *op; *op += 1; return temp; }
 
-	ofstream *sout = ofstream_stdout();
 	sout | twice( 'a' ) | ' ' | twice( 1 ) | ' ' | twice( 3.2 ) | endl;
 }
Index: src/examples/vector_test.c
===================================================================
--- src/examples/vector_test.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/examples/vector_test.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:14:52 2016
-// Update Count     : 17
+// Last Modified On : Wed Feb 17 12:23:55 2016
+// Update Count     : 18
 //
 
@@ -20,6 +20,4 @@
 
 int main( void ) {
-	ofstream *sout = ofstream_stdout();
-	ifstream *sin = ifstream_stdin();
 	vector_int vec = vector_int_allocate();
 
Index: src/libcfa/fstream
===================================================================
--- src/libcfa/fstream	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/libcfa/fstream	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Jan 27 23:47:41 2016
-// Update Count     : 3
+// Last Modified On : Wed Feb 17 14:02:01 2016
+// Update Count     : 22
 //
 
@@ -19,25 +19,27 @@
 #include "iostream"
 
-typedef struct ofstream ofstream;
+// implement context ostream
+struct ofstream;
 
-// implement context ostream
-ofstream *write( ofstream *, const char *, streamsize_type );
-int fail( ofstream * );
+int fail( ofstream * os );
+int flush( ofstream * os );
+void open( ofstream ** os, const char * name, const char * mode );
+void close( ofstream * os );
+ofstream * write( ofstream * os, const char * data, streamsize_type size );
 
-ofstream *ofstream_stdout();
-ofstream *ofstream_stderr();
-ofstream *ofstream_fromfile( const char *name );
-void ofstream_close( ofstream *os );
-
-typedef struct ifstream ifstream;
+extern ofstream * sout, * serr;
 
 // implement context istream
-ifstream *read( ifstream *, char *, streamsize_type );
-ifstream *unread( ifstream *, char );
-int fail( ifstream * );
-int eof( ifstream * );
+struct ifstream;
 
-ifstream *ifstream_stdin();
-ifstream *ifstream_fromfile( const char *name );
+int fail( ifstream * is );
+int eof( ifstream * is );
+void open( ifstream ** is, const char * name, const char * mode );
+void close( ifstream * is );
+ifstream * get( ifstream * is, int * data );
+ifstream * read( ifstream * is, char * data, streamsize_type size );
+ifstream * ungetc( ifstream * is, char c );
+
+extern ifstream *sin;
 
 #endif // __FSTREAM_H__
Index: src/libcfa/fstream.c
===================================================================
--- src/libcfa/fstream.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/libcfa/fstream.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 26 17:12:59 2016
-// Update Count     : 6
+// Last Modified On : Wed Feb 17 14:03:05 2016
+// Update Count     : 76
 //
 
@@ -23,102 +23,120 @@
 struct ofstream {
 	FILE *file;
-	int fail;
 };
 
-ofstream *write( ofstream *os, const char *data, streamsize_type size ) {
-	if ( ! os->fail ) {
-		fwrite( data, size, 1, os->file );
-		os->fail = ferror( os->file );
+#define IO_MSG "I/O error "
+
+int fail( ofstream * os ) {
+	return ferror( os->file );
+} // fail
+
+int flush( ofstream * os ) {
+	return fflush( os->file );
+} // flush
+
+void open( ofstream ** os, const char * name, const char * mode ) {
+	FILE *t = fopen( name, mode );
+	if ( t == 0 ) {										// do not change unless successful
+		perror( IO_MSG "open output" );
+		exit( EXIT_FAILURE );
+	} // if
+	(*os)->file = t;
+} // open
+
+void close( ofstream * os ) {
+	if ( os->file == stdout || os->file == stderr ) return;
+
+	if ( fclose( os->file ) == EOF ) {
+		perror( IO_MSG "close output" );
+	} // if 
+} // close
+
+ofstream * write( ofstream * os, const char * data, streamsize_type size ) {
+	if ( fail( os ) ) {
+		fprintf( stderr, "attempt write I/O on failed stream\n" );
+		exit( EXIT_FAILURE );
+	} // if
+
+	if ( fwrite( data, 1, size, os->file ) != size ) {
+		perror( IO_MSG "write" );
+		exit( EXIT_FAILURE );
 	} // if
 	return os;
 } // write
 
-int fail( ofstream *os ) {
-	return os->fail;
-} // fail
+static ofstream soutFile = { (FILE *)(&_IO_2_1_stdout_) };
+ofstream *sout = &soutFile;
+static ofstream serrFile = { (FILE *)(&_IO_2_1_stderr_) };
+ofstream *serr = &serrFile;
 
-static ofstream *make_ofstream() {
-	ofstream *new_stream = malloc( sizeof( ofstream ) );
-	new_stream->fail = 0;
-	return new_stream;
-} // make_ofstream
-
-ofstream *ofstream_stdout() {
-	ofstream *stdout_stream = make_ofstream();
-	stdout_stream->file = stdout;
-	return stdout_stream;
-} // ofstream_stdout
-
-ofstream *ofstream_stderr() {
-	ofstream *stderr_stream = make_ofstream();
-	stderr_stream->file = stderr;
-	return stderr_stream;
-} // ofstream_stderr
-
-ofstream *ofstream_fromfile( const char *name ) {
-	ofstream *file_stream = make_ofstream();
-	file_stream->file = fopen( name, "w" );
-	file_stream->fail = file_stream->file == 0;
-	return file_stream;
-}
-
-void ofstream_close( ofstream *os ) {
-	if ( os->file != stdout && os->file != stderr ) {
-		os->fail = fclose( os->file );
-	}
-	free( os );
-}
+//---------------------------------------
 
 struct ifstream {
 	FILE *file;
-	int fail;
-	int eof;
 };
 
-ifstream *read( ifstream *is, char *data, streamsize_type size ) {
-	if ( ! is->fail && ! is->eof ) {
-		fread( data, size, 1, is->file );
-		is->fail = ferror( is->file );
-		is->eof = feof( is->file );
-	}
+int fail( ifstream * is ) {
+	return ferror( is->file );
+} // fail
+
+int eof( ifstream * is ) {
+	return feof( is->file );
+} // eof
+
+ifstream * get( ifstream * is, int * data ) {
+	if ( fscanf( is->file, "%d", data ) == EOF ) {
+		if ( ferror( is->file ) ) {
+			fprintf( stderr, "invalid int read\n" );
+			exit( EXIT_FAILURE );
+		} // if
+	} // if
 	return is;
-}
+} // read
+
+ifstream * read( ifstream * is, char * data, streamsize_type size ) {
+	if ( fail( is ) ) {
+		fprintf( stderr, "attempt read I/O on failed stream\n" );
+		exit( EXIT_FAILURE );
+	} // if
+
+	if ( fread( data, size, 1, is->file ) == 0 ) {
+		perror( IO_MSG "read" );
+		exit( EXIT_FAILURE );
+	} // if
+	return is;
+} // read
   
-ifstream *unread( ifstream *is, char c ) {
-	if ( ! is->fail ) {
-		if ( ! EOF == ungetc( c, is->file ) ) {
-			is->fail = 1;
-		}
-	}
+ifstream *ungetc( ifstream * is, char c ) {
+	if ( fail( is ) ) {
+		fprintf( stderr, "attempt ungetc I/O on failed stream\n" );
+		exit( EXIT_FAILURE );
+	} // if
+
+	if ( ungetc( c, is->file ) == EOF ) {
+		perror( IO_MSG "ungetc" );
+		exit( EXIT_FAILURE );
+	} // if
 	return is;
-}
+} // ungetc
 
-int fail( ifstream *is ) {
-	return is->fail;
-}
+void open( ifstream ** is, const char * name, const char * mode ) {
+	FILE *t = fopen( name, mode );
+	if ( t == 0 ) {										// do not change unless successful
+		perror( IO_MSG "open input" );
+		exit( EXIT_FAILURE );
+	} // if
+	(*is)->file = t;
+} // open
 
-int eof( ifstream *is ) {
-	return is->eof;
-}
+void close( ifstream * is ) {
+	if ( is->file == stdin ) return;
 
-static ifstream *make_ifstream() {
-	ifstream *new_stream = malloc( sizeof( ifstream ) );
-	new_stream->fail = 0;
-	new_stream->eof = 0;
-	return new_stream;
-}
+	if ( fclose( is->file ) == EOF ) {
+		perror( IO_MSG "close input" );
+	} // if 
+} // close
 
-ifstream *ifstream_stdin() {
-	ifstream *stdin_stream = make_ifstream();
-	stdin_stream->file = stdin;
-	return stdin_stream;
-}
-
-ifstream *ifstream_fromfile( const char *name ) {
-	ifstream *file_stream = make_ifstream();
-	file_stream->file = fopen( name, "r" );
-	file_stream->fail = file_stream->file == 0;
-	return file_stream;
-}
+static ifstream sinFile = { (FILE *)(&_IO_2_1_stdin_) };
+ifstream *sin = &sinFile;
 
 // Local Variables: //
Index: src/libcfa/iostream
===================================================================
--- src/libcfa/iostream	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/libcfa/iostream	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jan 29 15:50:36 2016
-// Update Count     : 29
+// Last Modified On : Wed Feb 17 14:04:24 2016
+// Update Count     : 32
 //
 
@@ -22,8 +22,8 @@
 
 context ostream( dtype ostype ) {
-	ostype *write( ostype *, const char *, streamsize_type );
 	int fail( ostype * );
+	int flush( ostype * );
+	ostype * write( ostype *, const char *, streamsize_type );
 };
-
 context writeable( type T ) {
 	forall( dtype ostype | ostream( ostype ) ) ostype * ?|?( ostype *, T );
@@ -52,21 +52,18 @@
 
 // writes the range [begin, end) to the given stream
-forall( type elt_type | writeable( elt_type ),
-		type iterator_type | iterator( iterator_type, elt_type ),
-		dtype os_type | ostream( os_type ) )
+forall( type elt_type | writeable( elt_type ), type iterator_type | iterator( iterator_type, elt_type ), dtype os_type | ostream( os_type ) )
 void write( iterator_type begin, iterator_type end, os_type *os );
 
-forall( type elt_type | writeable( elt_type ),
-		type iterator_type | iterator( iterator_type, elt_type ),
-		dtype os_type | ostream( os_type ) )
+forall( type elt_type | writeable( elt_type ), type iterator_type | iterator( iterator_type, elt_type ), dtype os_type | ostream( os_type ) )
 void write_reverse( iterator_type begin, iterator_type end, os_type *os );
 
-//******************************************************************************
+//---------------------------------------
 
 context istream( dtype istype ) {
-	istype *read( istype *, char *, streamsize_type );
-	istype *unread( istype *, char );
 	int fail( istype * );
 	int eof( istype * );
+	istype * get( istype *, int * );
+	istype * read( istype *, char *, streamsize_type );
+	istype * ungetc( istype *, char );
 };
 
Index: src/libcfa/iostream.c
===================================================================
--- src/libcfa/iostream.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/libcfa/iostream.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Feb  1 14:20:30 2016
-// Update Count     : 60
+// Last Modified On : Wed Feb 17 14:19:56 2016
+// Update Count     : 76
 //
 
@@ -19,4 +19,5 @@
 #include <stdio.h>
 #include <string.h>										// strlen
+#include <float.h>										// DBL_DIG, LDBL_DIG
 #include <complex.h>									// creal, cimag
 }
@@ -72,5 +73,5 @@
 ostype * ?|?( ostype *os, double d ) {
 	char buffer[32];
-	return write( os, buffer, sprintf( buffer, "%g", d ) );
+	return write( os, buffer, sprintf( buffer, "%.*lg", DBL_DIG, d ) );
 } // ?|?
 
@@ -78,5 +79,5 @@
 ostype * ?|?( ostype *os, long double d ) {
 	char buffer[32];
-	return write( os, buffer, sprintf( buffer, "%Lg", d ) );
+	return write( os, buffer, sprintf( buffer, "%.*Lg", LDBL_DIG, d ) );
 } // ?|?
 
@@ -110,26 +111,24 @@
 forall( dtype ostype, dtype retostype | ostream( ostype ) | ostream( retostype ) ) 
 retostype * ?|?( ostype *os, retostype * (*manip)(ostype*) ) {
-  return manip(os);
+  return manip( os );
 }
 
 forall( dtype ostype | ostream( ostype ) ) 
 ostype * endl( ostype * os ) {
-  os | "\n";
-  // flush
-  return os;
+	os | "\n";
+	flush( os );
+	return os;
 } // endl
 
-forall( type elt_type | writeable( elt_type ),
-		type iterator_type | iterator( iterator_type, elt_type ),
+//---------------------------------------
+
+forall( type elt_type | writeable( elt_type ), type iterator_type | iterator( iterator_type, elt_type ),
 		dtype os_type | ostream( os_type ) )
 void write( iterator_type begin, iterator_type end, os_type *os ) {
-	void print( elt_type i ) {
-		os | i | ' ';
-	}
+	void print( elt_type i ) { os | i | ' '; }
 	for_each( begin, end, print );
 } // ?|?
 
-forall( type elt_type | writeable( elt_type ),
-		type iterator_type | iterator( iterator_type, elt_type ),
+forall( type elt_type | writeable( elt_type ), type iterator_type | iterator( iterator_type, elt_type ),
 		dtype os_type | ostream( os_type ) )
 void write_reverse( iterator_type begin, iterator_type end, os_type *os ) {
@@ -138,4 +137,5 @@
 } // ?|?
 
+//---------------------------------------
 
 forall( dtype istype | istream( istype ) )
@@ -146,22 +146,5 @@
 forall( dtype istype | istream( istype ) )
 istype * ?|?( istype *is, int *ip ) {
-	char cur;
-  
-	// skip some whitespace
-	do {
-		is | &cur;
-		if ( fail( is ) || eof( is ) ) return is;
-	} while ( !( cur >= '0' && cur <= '9' ) );
-  
-	// accumulate digits
-	*ip = 0;
-	while ( cur >= '0' && cur <= '9' ) {
-		*ip = *ip * 10 + ( cur - '0' );
-		is | &cur;
-		if ( fail( is ) || eof( is ) ) return is;
-	}
-  
-	unread( is, cur );
-	return is;
+	return get( is, ip );
 } // ?|?
 
Index: src/libcfa/stdlib.c
===================================================================
--- src/libcfa/stdlib.c	(revision c44e6220a6e2d35bc4df195fa8e088f34d12387f)
+++ src/libcfa/stdlib.c	(revision ae7f1e091b3ca8bf1fd175be398b5a9629c2eea8)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 17:10:29 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Feb  5 15:41:24 2016
-// Update Count     : 128
+// Last Modified On : Wed Feb 10 15:45:56 2016
+// Update Count     : 140
 //
 
@@ -23,5 +23,4 @@
 #include <string.h>										// memset
 #include <malloc.h>										// malloc_usable_size
-#include <stdio.h>
 #include <math.h>										// fabsf, fabs, fabsl
 #include <complex.h>									// _Complex_I, cabsf, cabs, cabsl
@@ -106,51 +105,50 @@
 long int ato( const char * ptr ) {
 	long int li;
-	if ( sscanf( ptr, "%ld", &li ) == EOF ) {};			// check return code
+	if ( sscanf( ptr, "%ld", &li ) == EOF ) {}			// check return code
 	return li;
 }
 unsigned long int ato( const char * ptr ) {
 	unsigned long int uli;
-	if ( sscanf( ptr, "%lu", &uli ) == EOF ) {};		// check return code
+	if ( sscanf( ptr, "%lu", &uli ) == EOF ) {}			// check return code
 	return uli;
 }
 long long int ato( const char * ptr ) {
 	long long int lli;
-	if ( sscanf( ptr, "%lld", &lli ) == EOF ) {};		// check return code
+	if ( sscanf( ptr, "%lld", &lli ) == EOF ) {}		// check return code
 	return lli;
 }
 unsigned long long int ato( const char * ptr ) {
 	unsigned long long int ulli;
-	if ( sscanf( ptr, "%llu", &ulli ) == EOF ) {};		// check return code
+	if ( sscanf( ptr, "%llu", &ulli ) == EOF ) {}		// check return code
 	return ulli;
 }
 float ato( const char * ptr ) {
 	float f;
-	if ( sscanf( ptr, "%f", &f ) == EOF ) {};			// check return code
+	if ( sscanf( ptr, "%f", &f ) == EOF ) {}			// check return code
 	return f;
 }
 double ato( const char * ptr ) {
 	double d;
-	if ( sscanf( ptr, "%lf", &d ) == EOF ) {};			// check return code
+	if ( sscanf( ptr, "%lf", &d ) == EOF ) {}			// check return code
 	return d;
 }
 long double ato( const char * ptr ) {
 	long double ld;
-	printf( "FRED " );
-	if ( sscanf( ptr, "%.32Lf", &ld ) == EOF ) {};		// check return code
+	if ( sscanf( ptr, "%Lf", &ld ) == EOF ) {}			// check return code
 	return ld;
 }
 float _Complex ato( const char * ptr ) {
 	float re, im;
-	if ( sscanf( ptr, "%g%g", &re, &im ) == EOF ) {};	// check return code
+	if ( sscanf( ptr, "%g%gi", &re, &im ) == EOF ) {}	// check return code
 	return re + im * _Complex_I;
 }
 double _Complex ato( const char * ptr ) {
 	double re, im;
-	if ( sscanf( ptr, "%.16lg%.16lg", &re, &im ) == EOF ) {}; // check return code
+	if ( sscanf( ptr, "%lf%lfi", &re, &im ) == EOF ) {} // check return code
 	return re + im * _Complex_I;
 }
 long double _Complex ato( const char * ptr ) {
 	long double re, im;
-	if ( sscanf( ptr, "%.32Lg%.32Lg", &re, &im ) == EOF ) {}; // check return code
+	if ( sscanf( ptr, "%Lf%Lfi", &re, &im ) == EOF ) {}	// check return code
 	return re + im * _Complex_I;
 }	
