diff --git a/options.cc b/options.cc
index 59d2fde0c00afa2aaec4727f9f260268f4b724b7..2571b5bc66b7df283f5d9b11d19d4da2278c26e1 100644
--- a/options.cc
+++ b/options.cc
@@ -1,207 +1,227 @@
 #include "options.h"
 
-void string_to_T(bool &b, const string& s) {
-  if(s == "NO ARG")
-    b = !b;
-  else
-    b = (s == "true");
-}
+namespace Options {
 
-void string_to_T(string& d, const string& s) {
-  d = s;
-}
+  void string_to_T(bool &b, const string& s) {
+    if(s == "NO ARG")
+      b = !b;
+    else
+      b = (s == "true");
+  }
 
-void string_to_T(int& i, const string& s) {
-  i = atoi(s.c_str());
-}
+  void string_to_T(string& d, const string& s) {
+    d = s;
+  }
 
-void string_to_T(float& v, const string& s) {
-  v = atof(s.c_str());
-}
+  void string_to_T(int& i, const string& s) {
+    i = atoi(s.c_str());
+  }
+
+  void string_to_T(float& v, const string& s) {
+    v = atof(s.c_str());
+  }
 
-bool BaseOption::matches(const string& arg)
-{
-  string::size_type pos = 0, np;
-  while((np = key_.find(",", pos)) != string::npos) {
-    if(arg == key_.substr(pos, np - pos))
+  bool BaseOption::matches(const string& arg)
+  {
+    string::size_type pos = 0, np;
+    while((np = key_.find(",", pos)) != string::npos) {
+      if(arg == key_.substr(pos, np - pos))
+	return true;
+      pos = np + 1;
+    }
+    if(arg == key_.substr(pos, string::npos))
       return true;
-    pos = np + 1;
+    return false;
   }
-  if(arg == key_.substr(pos, string::npos))
-    return true;
-  return false;
-}
 
-ostream& operator<<(ostream &os, const BaseOption& o) {
-  return os << 
-    "\t" << o.key() << 
-    "\t" << o.help_text();
-}
+  ostream& operator<<(ostream &os, const BaseOption& o) {
+    return os << 
+      "\t" << o.key() << 
+      "\t" << o.help_text();
+  }
 
-void OptionParser::usage()
-{
-  cerr << endl << progname_ << endl << endl;
-  cerr << "Usage: " << endl << example_ << endl;
-
-  for(Options::iterator option = options_.begin(); option != options_.end(); 
-      option++)
-    {
-      if((*option)->compulsory()) {
-	static bool banner = true;
-	if(banner) {
-	  cerr << endl << "Compulsory arguments (You MUST set one or more of):" << endl;
-	  banner = false;
+  void OptionParser::usage()
+  {
+    cerr << endl << progname_ << endl << endl;
+    cerr << "Usage: " << endl << example_ << endl;
+
+    for(Options::iterator option = options_.begin(); option != options_.end(); 
+	option++)
+      {
+	if((*option)->compulsory()) {
+	  static bool banner = true;
+	  if(banner) {
+	    cerr << endl << "Compulsory arguments (You MUST set one or more of):" << endl;
+	    banner = false;
+	  }
+	  cerr << **option << endl;
 	}
-	cerr << **option << endl;
       }
-    }
 
 
-  for(Options::iterator option = options_.begin(); option != options_.end(); 
-      option++)
-    {
-      if(!(*option)->compulsory()) {
-	static bool banner = true;
-	if(banner) {
-	  cerr << endl << "Optional arguments (You may optionally specify one or more of):" << endl;
-	  banner = false;
+    for(Options::iterator option = options_.begin(); option != options_.end(); 
+	option++)
+      {
+	if(!(*option)->compulsory()) {
+	  static bool banner = true;
+	  if(banner) {
+	    cerr << endl << "Optional arguments (You may optionally specify one or more of):" << endl;
+	    banner = false;
+	  }
+	  cerr << **option << endl;
 	}
-	cerr << **option << endl;
       }
-    }
 
-  cerr << endl;
-  cerr << endl;
-}
+    cerr << endl;
+    cerr << endl;
+  }
 
-bool OptionParser::check_compulsory_arguments(bool verbose)
-{
-  bool okay = true;
+  bool OptionParser::check_compulsory_arguments(bool verbose)
+  {
+    bool okay = true;
 
-  for(Options::iterator option = options_.begin();
-      option != options_.end();
-      option++) {
+    for(Options::iterator option = options_.begin();
+	option != options_.end();
+	option++) {
     
-    if((*option)->compulsory() && (*option)->unset()) {
-      if(okay) {
-	if(verbose) {
-	  cerr << "***************************************************" << endl;
-	  cerr << "The following COMPULSORY options have not been set:" << endl;
+      if((*option)->compulsory() && (*option)->unset()) {
+	if(okay) {
+	  if(verbose) {
+	    cerr << "***************************************************" << endl;
+	    cerr << "The following COMPULSORY options have not been set:" << endl;
+	  }
+	  okay = false;
 	}
-	okay = false;
+	if(verbose)
+	  cerr << **option << endl;
       }
-      if(verbose)
-	cerr << **option << endl;
     }
-  }
-  if(!okay && verbose)
-    cerr << "***************************************************" << endl; 
+    if(!okay && verbose)
+      cerr << "***************************************************" << endl; 
 
-  return okay;
-}
-
-unsigned int OptionParser::parse_command_line(unsigned int argc, 
-					      char **argv) 
-{
-  unsigned int argcount = 1;
-  bool usage_needed = false;
+    return okay;
+  }
 
-  while(argcount < argc) {
-    unsigned int nmatches = 0;
-    unsigned int increments = 1;
+  unsigned int OptionParser::parse_command_line(unsigned int argc, 
+						char **argv) 
+    throw(X_OptionError, X_UnknownOptions, X_MissingArguments)
+  {
+    unsigned int argcount = 1;
+    bool unknown_opts = false;
+    bool missing_args = false;
+
+    while(argcount < argc) {
+      unsigned int nmatches = 0;
+      unsigned int increments = 1;
       
-    string optstr(argv[argcount]), valstr;
-    if(argcount + 1 < argc)
-      valstr = string(argv[argcount+1]);
-    else
-      valstr = string("NO ARG");
-    if(optstr[0] != '-')	// No more parsable options
-      break;
-
-    for(Options::iterator option = options_.begin();
-	option != options_.end();
-	option++) {
-      if((*option)->matches(optstr))
-	{
-	  nmatches++;
-	  if((*option)->required()) {
-	    if(valstr != "NO ARG") {
-	      (*option)->value(valstr);
-	      increments = 2;
-	    } else {
-	      cerr << optstr << " : Missing argument!" << endl;
-	      usage_needed = true;
-	    }
-	  } else if((*option)->optional()) {
-	    if(valstr[0] != '-') {
-	      (*option)->value(valstr);
-	      increments = 2;
+      string optstr(argv[argcount]), valstr;
+      if(argcount + 1 < argc)
+	valstr = string(argv[argcount+1]);
+      else
+	valstr = string("NO ARG");
+      if(optstr[0] != '-')	// No more parsable options
+	break;
+
+      for(Options::iterator option = options_.begin();
+	  option != options_.end();
+	  option++) {
+	if((*option)->matches(optstr))
+	  {
+	    nmatches++;
+	    if((*option)->required()) {
+	      if(valstr != "NO ARG") {
+		(*option)->value(valstr);
+		increments = 2;
+	      } else {
+		cerr << optstr << ": missing argument!" << endl;
+		missing_args = true;
+	      }
+	    } else if((*option)->optional()) {
+	      if(valstr[0] != '-') {
+		(*option)->value(valstr);
+		increments = 2;
+	      } else {
+		(*option)->value("NO ARG");
+	      }
 	    } else {
 	      (*option)->value("NO ARG");
 	    }
-	  } else {
-	    (*option)->value("NO ARG");
 	  }
-	}
-    }
-    if(nmatches == 0) {
-      cerr << optstr << " : Unknown option!" << endl;
-      usage_needed = true;
+      }
+      if(nmatches == 0) {
+	cerr << optstr << ": unknown option!" << endl;
+	unknown_opts = true;
+      }
+      argcount += increments;
     }
-    argcount += increments;
+  
+    if(unknown_opts && missing_args)
+      throw X_OptionError();
+    else if(unknown_opts)
+      throw X_UnknownOptions();
+    else if(missing_args)
+      throw X_MissingArguments();
+
+    return argcount;		// User should process any remaining args
   }
 
-  return argcount;		// User should process any remaining args
 }
-
-
-
 //
 // And now for the test stub...
 //
 #if defined(TESTING)
 
+using namespace Opts;
+
 Option<bool> verbose(string("-V,--verbose"), false, 
 		     string("switch on diagnostic messages"), 
-		     false, BaseOption::no_argument);
+		     false, no_argument);
 Option<bool> help(string("-h,--help"), false,
 		  string("display this message"),
-		  false, BaseOption::no_argument);
+		  false, no_argument);
 Option<float> dof(string("-d,--dof"), 100.0,
 		  string("number of degrees of freedom"),
-		  true, BaseOption::requires_argument);
+		  true, requires_argument);
 Option<string> mask(string("-m,--mask"), string("mask"),
 		    string("brain mask volume"),
-		    true, BaseOption::requires_argument);
+		    true, requires_argument);
 Option<string> resid(string("-r,--res"), string("res4d"),
 		     string("4d `residual-of-fit' image"),
-		     true, BaseOption::requires_argument);
+		     true, requires_argument);
 
 int main(unsigned int argc, char **argv) {
 
   OptionParser options("options", 
 		       "-d <number> --mask <filename> --res <filename>");
 
-  options.add(verbose);
-  options.add(help);
-  options.add(dof);
-  options.add(mask);
-  options.add(resid);
+  try {
 
-  for(unsigned int a = options.parse_command_line(argc, argv); a < argc; a++)
-    cout << argv[a] << endl;
-  
-  if(help.value())
-    options.usage();
+    options.add(verbose);
+    options.add(help);
+    options.add(dof);
+    options.add(mask);
+    options.add(resid);
 
-  if(verbose.value()) {
-    cout << "verbose = " << verbose.value() << endl;
-    cout << "help = " << help.value() << endl;
-    cout << "dof = " << dof.value() << endl;
-    cout << "mask = " << mask.value() << endl;
-    cout << "resid = " << resid.value() << endl;
-  }
+    for(unsigned int a = options.parse_command_line(argc, argv); a < argc; a++)
+      cout << argv[a] << endl;
+  
+    if(help.value())
+      options.usage();
+
+    if(verbose.value()) {
+      cout << "verbose = " << verbose.value() << endl;
+      cout << "help = " << help.value() << endl;
+      cout << "dof = " << dof.value() << endl;
+      cout << "mask = " << mask.value() << endl;
+      cout << "resid = " << resid.value() << endl;
+    }
 
+  } catch(X_OptionError& e) {
+    options.usage();
+    cerr << endl << e.what() << endl;
+  } catch(std::exception &e) {
+    cerr << e.what() << endl;
+  }    
 }
 
 #endif