Index: libcfa/src/Makefile.am
===================================================================
--- libcfa/src/Makefile.am	(revision bbe3719f51f151b5ad865f6a0ca92c072ca4f23e)
+++ libcfa/src/Makefile.am	(revision a5d1fe752ccee8b0ce0b7ff75dff6c7e0de50ca9)
@@ -48,4 +48,5 @@
 	math.hfa \
 	time_t.hfa \
+	bits/algorithm.hfa \
 	bits/align.hfa \
 	bits/containers.hfa \
@@ -59,5 +60,4 @@
 	containers/array.hfa \
 	concurrency/iofwd.hfa \
-	concurrency/mutex_stmt.hfa \
 	containers/list.hfa \
 	containers/queueLockFree.hfa \
@@ -78,4 +78,5 @@
 	memory.hfa \
 	parseargs.hfa \
+	parseconfig.hfa \
 	rational.hfa \
 	stdlib.hfa \
@@ -91,5 +92,4 @@
 libsrc = ${inst_headers_src} ${inst_headers_src:.hfa=.cfa} \
 	assert.cfa \
-	bits/algorithm.hfa \
 	bits/debug.cfa \
 	exception.c \
@@ -107,5 +107,6 @@
 	concurrency/invoke.h \
 	concurrency/future.hfa \
-	concurrency/kernel/fwd.hfa
+	concurrency/kernel/fwd.hfa \
+	concurrency/mutex_stmt.hfa
 
 inst_thread_headers_src = \
Index: libcfa/src/parseconfig.cfa
===================================================================
--- libcfa/src/parseconfig.cfa	(revision a5d1fe752ccee8b0ce0b7ff75dff6c7e0de50ca9)
+++ libcfa/src/parseconfig.cfa	(revision a5d1fe752ccee8b0ce0b7ff75dff6c7e0de50ca9)
@@ -0,0 +1,230 @@
+#include <fstream.hfa>
+#include <parseargs.hfa>
+#include <stdlib.hfa>
+#include <string.h>
+#include "parseconfig.hfa"
+
+
+// *********************************** exceptions ***********************************
+
+
+// TODO: Add names of missing config entries to exception (see further below)
+static vtable(Missing_Config_Entries) Missing_Config_Entries_vt;
+
+[ void ] ?{}( & Missing_Config_Entries this, unsigned int num_missing ) {
+	this.virtual_table = &Missing_Config_Entries_vt;
+	this.num_missing = num_missing;
+}
+
+// TODO: use string interface when it's ready (and implement exception msg protocol)
+[ void ] msg( * Missing_Config_Entries ex ) {
+	serr | nlOff;
+	serr | "The config file is missing " | ex->num_missing;
+	serr | nlOn;
+	if ( ex->num_missing == 1 ) {
+		serr | " entry.";
+	} else {
+		serr | " entries.";
+	}
+} // msg
+
+
+static vtable(Parse_Failure) Parse_Failure_vt;
+
+[ void ] ?{}( & Parse_Failure this, [] char failed_key, [] char failed_value ) {
+	this.virtual_table = &Parse_Failure_vt;
+
+	this.failed_key = alloc( strlen( failed_key ) );
+	this.failed_value = alloc( strlen( failed_value ) );
+	strcpy( this.failed_key, failed_key );
+	strcpy( this.failed_value, failed_value );
+}
+
+[ void ] ^?{}( & Parse_Failure this ) with ( this ) {
+	free( failed_key );
+	free( failed_value );
+}
+
+// TODO: use string interface when it's ready (and implement exception msg protocol)
+[ void ] msg( * Parse_Failure ex ) {
+	serr | "Config entry " | ex->failed_key | " could not be parsed. It has value " | ex->failed_value | ".";
+}
+
+
+static vtable(Validation_Failure) Validation_Failure_vt;
+
+[ void ] ?{}( & Validation_Failure this, [] char failed_key, [] char failed_value ) {
+	this.virtual_table = &Validation_Failure_vt;
+
+	this.failed_key = alloc( strlen( failed_key ) );
+	this.failed_value = alloc( strlen( failed_value ) );
+	strcpy( this.failed_key, failed_key );
+	strcpy( this.failed_value, failed_value );
+}
+
+[ void ] ^?{}( & Validation_Failure this ) with ( this ) {
+	free( failed_key );
+	free( failed_value );
+}
+
+// TODO: use string interface when it's ready (and implement exception msg protocol)
+[ void ] msg( * Validation_Failure ex ) {
+	serr | "Config entry " | ex->failed_key | " could not be validated. It has value " | ex->failed_value | ".";
+}
+
+
+// *********************************** main code ***********************************
+
+
+[ void ] ?{}( & KVPairs kvp ) with ( kvp ) {				// default constructor
+	size = 0; max_size = 0; data = 0p;
+}
+
+[ void ] ?{}( & KVPairs kvp, size_t size ) { 				// initialization
+	kvp.[ size, max_size ] = [ 0, size ];
+	kvp.data = alloc( size );
+}
+
+[ void ] ^?{}( & KVPairs kvp ) with ( kvp ) {				// destructor
+	for ( i; size ) free( data[i] );
+	free( data );
+	size = 0; max_size = 0; data = 0p;
+}
+
+[ void ] add_kv_pair( & KVPairs kv_pairs, [] char key, [] char value ) with ( kv_pairs ) {
+	if ( max_size == 0 ) {
+		max_size = 1;
+		data = alloc( max_size );
+	} else if ( size == max_size ) {
+		max_size *= 2;
+		data = alloc( max_size, data`realloc );
+	}
+
+	data[size].0 = alloc( strlen( key ) );
+	data[size].1 = alloc( strlen( value ) );
+	strcpy( data[size].0, key );
+	strcpy( data[size].1, value );
+	++size;
+} // add_kv_pair
+
+
+[ bool ] comments( & ifstream in, [] char name ) {
+	while () {
+		in | name;
+	  if ( eof( in ) ) return true;
+	  if ( name[0] != '#' ) return false;
+		in | nl;									// ignore remainder of line
+	} // while
+} // comments
+
+// Parse configuration from a file formatted in tabular (CS 343) style
+[ * KVPairs ] parse_tabular_config_format( [] const char config_file, size_t num_entries ) {
+	// TODO: Change this to a unique_ptr when we fully support returning them (move semantics)
+	* KVPairs kv_pairs = new( num_entries );
+
+	ifstream in;
+	try {
+		open( in, config_file );					// open the configuration file for input
+
+		[64] char key;
+		[256] char value;
+
+		while () {									// parameter names can appear in any order
+		  	// NOTE: Must add check to see if already read in value for this key,
+			// once we switch to using hash table as intermediate storage
+		  if ( comments( in, key ) ) break;			// eof ?
+			in | value;
+
+			add_kv_pair( *kv_pairs, key, value );
+
+		  if ( eof( in ) ) break;
+			in | nl;								// ignore remainder of line
+		} // for
+	} catch( Open_Failure * ex; ex->istream == &in ) {
+		delete( kv_pairs );
+		throw *ex;
+	} // try
+	close( in );
+
+	return kv_pairs;
+} // parse_tabular_config_format
+
+// Parse configuration values from intermediate format
+[ void ] parse_config(
+		[] const char config_file,
+		[] config_entry entries,
+		size_t num_entries,
+		KVPairs * (*parser)(const char [], size_t)
+) {
+	* KVPairs kv_pairs = parser( config_file, num_entries );
+
+	int entries_so_far = 0;
+	for ( i; kv_pairs->size ) {
+	  if ( entries_so_far == num_entries ) break;
+
+		char * src_key, * src_value;
+		[ src_key, src_value ] = kv_pairs->data[i];
+
+		for ( j; num_entries ) {
+		  if ( strcmp( src_key, entries[j].key ) != 0 ) continue;
+		  	// Parse the data
+		  	if ( !entries[j].parse( src_value, entries[j].variable ) ) {
+				* Parse_Failure ex = new( src_key, src_value );
+				delete( kv_pairs );
+				throw *ex;
+			}
+
+			// Validate the data
+			if ( !entries[j].validate( entries[j].variable ) ) {
+				* Validation_Failure ex = new( src_key, src_value );
+				delete( kv_pairs );
+				throw *ex;
+			}
+
+			++entries_so_far;
+
+			break;
+		}
+	}
+	// TODO: Once we get vector2+hash_table, we can more easily add the missing config keys to this error
+	if ( entries_so_far < num_entries ) {
+		delete( kv_pairs );
+		throw (Missing_Config_Entries){ num_entries - entries_so_far };
+	}
+
+	delete( kv_pairs );
+} // parse_config
+
+
+// *********************************** validation ***********************************
+
+
+forall(T | Relational( T ))
+[ bool ] is_nonnegative( & T value ) {
+	T zero_val = 0;
+	return value >= zero_val;
+}
+
+forall(T | Relational( T ))
+[ bool ] is_positive( & T value ) {
+	T zero_val = 0;
+	return value > zero_val;
+}
+
+forall(T | Relational( T ))
+[ bool ] is_nonpositive( & T value ) {
+	T zero_val = 0;
+	return value <= zero_val;
+}
+
+forall(T | Relational( T ))
+[ bool ] is_negative( & T value ) {
+	T zero_val = 0;
+	return value < zero_val;
+}
+
+
+// Local Variables: //
+// tab-width: 4 //
+// compile-command: "cfa parseconfig.cfa" //
+// End: //
Index: libcfa/src/parseconfig.hfa
===================================================================
--- libcfa/src/parseconfig.hfa	(revision a5d1fe752ccee8b0ce0b7ff75dff6c7e0de50ca9)
+++ libcfa/src/parseconfig.hfa	(revision a5d1fe752ccee8b0ce0b7ff75dff6c7e0de50ca9)
@@ -0,0 +1,125 @@
+#pragma once
+
+#include <math.trait.hfa>
+
+
+// *********************************** initial declarations ***********************************
+
+
+struct config_entry {
+	const char * key;
+	void * variable;
+	bool (*parse)( const char *, void * );
+	bool (*validate)( void * );
+};
+
+bool null_validator( void * ) { return true; }
+
+static inline void ?{}( config_entry & this ) {}
+
+forall(T & | { bool parse( const char *, T & ); })
+static inline void ?{}( config_entry & this, const char * key, T & variable ) {
+	this.key      = key;
+	this.variable = (void *)&variable;
+	this.parse    = (bool (*)(const char *, void *))(bool (*)(const char *, T &))parse;
+	this.validate = null_validator;
+}
+
+forall(T & | { bool parse( const char *, T & ); })
+static inline void ?{}( config_entry & this, const char * key, T & variable, bool (*validate)(T &) ) {
+	this.key      = key;
+	this.variable = (void *)&variable;
+	this.parse    = (bool (*)(const char *, void *))(bool (*)(const char *, T &))parse;
+	this.validate = (bool (*)(void *))(bool (*)(T &))validate;
+}
+
+forall(T &)
+static inline void ?{}( config_entry & this, const char * key, T & variable, bool (*parse)(const char *, T &) ) {
+	this.key      = key;
+	this.variable = (void *)&variable;
+	this.parse    = (bool (*)(const char *, void *))(bool (*)(const char *, T &))parse;
+	this.validate = null_validator;
+}
+
+forall(T &)
+static inline void ?{}( config_entry & this, const char * key, T & variable, bool (*parse)(const char *, T &), bool (*validate)(T &) ) {
+	this.key      = key;
+	this.variable = (void *)&variable;
+	this.parse    = (bool (*)(const char *, void *))(bool (*)(const char *, T &))parse;
+	this.validate = (bool (*)(void *))(bool (*)(T &))validate;
+}
+
+// TODO: Replace KVPairs with vector2 when it's fully functional
+struct KVPairs {
+	size_t size, max_size;
+	* [ * char, * char ] data;
+};
+
+[ void ] add_kv_pair( & KVPairs kv_pairs, [] char key, [] char value );
+
+
+// *********************************** exceptions ***********************************
+
+
+exception Missing_Config_Entries {
+	unsigned int num_missing;
+};
+
+[ void ] msg( * Missing_Config_Entries ex );
+
+exception Parse_Failure {
+	* char failed_key;
+	* char failed_value;
+};
+
+[ void ] msg( * Parse_Failure ex );
+
+exception Validation_Failure {
+	* char failed_key;
+	* char failed_value;
+};
+
+[ void ] msg( * Validation_Failure ex );
+
+
+// *********************************** main code ***********************************
+
+
+[ * KVPairs ] parse_tabular_config_format( [] const char config_file, size_t num_entries );
+
+[ void ] parse_config(
+	[] const char config_file,
+	[] config_entry entries,
+	size_t num_entries,
+	KVPairs * (*parser)(const char [], size_t)  // TODO: add sensible default parser when resolver bug is fixed
+);
+
+bool parse( const char *, const char * & );
+bool parse( const char *, int & );
+bool parse( const char *, unsigned & );
+bool parse( const char *, unsigned long & );
+bool parse( const char *, unsigned long long & );
+bool parse( const char *, float & );
+bool parse( const char *, double & );
+
+
+// *********************************** validation ***********************************
+
+
+forall(T | Relational( T ))
+[ bool ] is_nonnegative( & T );
+
+forall(T | Relational( T ))
+[ bool ] is_positive( & T );
+
+forall(T | Relational( T ))
+[ bool ] is_nonpositive( & T );
+
+forall(T | Relational( T ))
+[ bool ] is_negative( & T );
+
+
+// Local Variables: //
+// mode: c //
+// tab-width: 4 //
+// End: //
