Index: CMT/HEAD/source/cmt_vcs.cxx
===================================================================
--- CMT/HEAD/source/cmt_vcs.cxx	(revision 534)
+++ CMT/HEAD/source/cmt_vcs.cxx	(revision 535)
@@ -18,4 +18,6 @@
 #include "cmt_error.h"
 
+#include "cmt_syntax.h"
+
 /**
 
@@ -92,4 +94,345 @@
 };
 
+//--------------------------------------------------------------------
+static void show_packages ()
+{
+  Package::PackageVector& vector = Package::packages ();
+
+  int i;
+  int j;
+
+  cout << "### Packages: ";
+  for (i = 0; i < vector.size (); i++)
+    {
+      Package& p = vector[i];
+      cout << p.get_name () << "[";
+      Use::UsePtrVector& uses = p.get_uses ();
+      for (j = 0; j < uses.size (); j++)
+	{
+	  Use* u = uses[j];
+	  cout << u << ",";
+	}
+
+      cout << "] ";
+    }
+  cout << endl;
+
+  {
+    Use::UsePtrVector& uses = Use::get_ordered_uses ();
+    //    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
+
+    cout << "### Uses: ";
+    for (i = 0; i < uses.size (); i++)
+      {
+	Use* u = uses[i];
+	cout << "[" << u << "]" << u->get_package_name () << " ";
+      }
+  }
+
+  cout << endl;
+}
+
+//--------------------------------------------------------------------
+
+class GlobalProjectAction : public IProjectAction
+{
+public:
+  GlobalProjectAction (const cmt_string& package,
+		       const cmt_string& version = "",
+			const cmt_string& path = "")
+    : m_package (package), m_version (version), m_path (path)
+  {
+    m_home_dir = CmtSystem::pwd ();
+    m_current = Use::current();
+    m_current_name = m_current.get_package_name ();
+    m_current.set_package_name ("m_current");
+  }
+
+  bool run (const Project& project)
+  {
+    if (project.is_current ()) return true;
+    CmtMessage::verbose ("run: " + project.get_cmtpath ());
+    const Use* use = &(project.get_container ());
+    if (use->get_package_name () != "" && use->located ())
+      {
+	CmtMessage::verbose ("container " + use->get_info () +
+			     " (" + use->real_path + ")");
+	Use* cuse = Use::add (use->real_path,
+			      use->get_package_name (),
+			      use->version,
+			      "", "", "", 0); // 0 == NOT used by current
+	if (cuse)
+	  {
+	    cmt_string cmt (use->get_full_path ());
+	    cmt += CmtSystem::file_separator ();
+	    cmt += "cmt";
+	    if (!CmtSystem::cd (cmt))
+	      {
+		CmtMessage::error ("Cannot move to directory " + cmt);
+		CmtError::set (CmtError::file_access_error, cmt);
+		if (!CmtSystem::cd (m_home_dir))
+		  {
+		    CmtMessage::error ("Cannot move to directory " + m_home_dir);
+		    CmtError::set (CmtError::file_access_error, m_home_dir);
+		  }
+		return true;
+	      }
+	    //cerr << "parsing: " << "requirements" << endl; 
+	    SyntaxParser::parse_requirements ("requirements", cuse);
+	    //cerr << "parsed: " << "requirements" << endl; 
+	    //show_packages ();
+	  }
+	else
+	  {
+	    CmtMessage::error ("Cannot add container " + use->get_package_name () +
+			       " " + use->version + " " + use->real_path);
+	  }
+	if (!CmtSystem::cd (m_home_dir))
+	  {
+	    CmtMessage::error ("Cannot move to directory " + m_home_dir);
+	    CmtError::set (CmtError::file_access_error, m_home_dir);
+	  }
+      }
+    return true;
+  }
+
+private:
+  cmt_string m_home_dir;
+  cmt_string m_package;
+  cmt_string m_version;
+  cmt_string m_path;
+  cmt_string m_cmtpath;
+  Use m_current;
+  cmt_string m_current_name;
+};
+
+//--------------------------------------------------------------------
+/**
+ *
+ *   Packages: keep info on all packages that can be found
+ *   in current context - CMTPATHs.
+ *
+ */
+
+class Packages
+{
+public:
+  static Packages& instance ();
+  //  void clear ();
+  //  void install (const cmt_string& line);
+  //  bool is_installed (const cmt_string& line);
+
+  Use* find (const cmt_string& name,
+	     const cmt_string& version = "",
+	     const cmt_string& path = "");
+
+private:
+  Packages ();
+  void exclude_current_project ();
+  void restore_current_project ();
+
+  int m_i;
+  Project* m_cur;
+  Project m_null;
+  bool m_initialized;
+};
+
+//--------------------------------------------------------------------
+Packages::Packages ()
+  : m_i (-1), m_cur (0), m_initialized (false)
+{
+  m_null.set_cmtpath (CmtSystem::get_temporary_name ());
+}
+
+//--------------------------------------------------------------------
+Packages& Packages::instance ()
+{
+  static Packages pkgs;
+  return (pkgs);
+}
+
+//--------------------------------------------------------------------
+Use* Packages::find (const cmt_string& name,
+		     const cmt_string& version,
+		     const cmt_string& path)
+{
+  if (name == "") return 0;
+  //  cerr << "find: " << name << " " << version << " " << path << endl;
+  exclude_current_project ();
+  if (path != "")
+    {
+      //cerr << "find: No need to find path: " << name << " " << path << endl;
+      //      Use use_obj (name, "", path);
+      Use use_obj (name, version, path);
+      Use* use = &use_obj;
+      //use->set (name, version, path);
+      use->get_package ()->remove_use (use);
+      if (use->move_to ())
+	{
+	  CmtSystem::cd (Cmt::get_current_dir ());
+	  /*
+	  cerr << "real_path: " << use->real_path
+	       << " style: " << use->style
+	       << " structuring_style: " << use->structuring_style
+	       << " full_path: " << use->get_full_path () << endl;
+	  */
+	  Use::UseVector& instances = Use::get_instances ();
+	  Use& use_object = instances.add ();
+	  use_object = *use;
+	  /*
+	  use_object.set (use->get_package_name (), use->version, use->path,
+			  use->version_alias, use->path_alias);
+	  use_object.get_package ()->remove_use (&use_object);
+	  */
+	  restore_current_project ();
+	  return (&use_object);
+	}
+      else
+	{
+	  CmtSystem::cd (Cmt::get_current_dir ());
+	  CmtMessage::warning (CmtError::get_error_name (CmtError::package_not_found)
+			       + ": " + use->get_info ());
+	}
+    }
+  //
+  // Second try is among the CMTPATHs
+  //
+  if (!m_initialized)
+    {
+      m_initialized = true;
+
+      GlobalProjectAction pa (name, version, path);
+      
+      Project::reverse_broadcast (pa);
+  //  Project::broadcast (pa);
+    }
+  //  cerr << "find: " << name << " " << version << " " << path << " Done." << endl;
+  //show_packages ();
+
+  Package* p = Package::find (name);
+  if (p == 0)
+    {
+      restore_current_project ();
+      return 0;
+    }
+    //return PackageInfo (name, version, path, "");
+  Use::UsePtrVector& uses = p->get_uses ();
+  Use* p_use (0);
+  //  cerr << "find for: " << name << endl;
+  for (int use_index = 0; use_index < uses.size (); use_index++)
+    {
+      Use* use = uses[use_index];
+      char index[8];
+      sprintf (index, "%d", use->m_index);
+      CmtMessage::verbose ("find: " + use->get_info () +
+			   " (" + use->real_path + ")" + 
+			   " m_index: " + index + 
+			   " located: " + (use->located () ? "1" : "0"));
+      if (use->located ()) p_use = use;
+      //      if (use->m_index >= 0) return use;
+      if (use->m_index >= 0) break;
+    }
+  if (p_use)
+    {
+//       cerr << "find: Try to validate: " << p_use->get_info ()
+// 	   << ": " << p_use->real_path << endl;
+      //      Use use_obj (name, "", path);
+      Use use_obj (name, version, p_use->path);
+      Use* use = &use_obj;
+      use->get_package ()->remove_use (use);
+      if (use->move_to ())
+	{
+	  CmtSystem::cd (Cmt::get_current_dir ());
+	  if (use->version == p_use->version)
+	    {
+	      CmtMessage::verbose ("Validated: " + p_use->get_info () +
+				   " (" + p_use->real_path + ")");
+	      restore_current_project ();
+	      return p_use;
+	    }
+	  Use* n_use = Use::add (use->real_path,
+				 use->get_package_name (),
+				 use->version,
+				 use->version_alias,
+				 use->path_alias,
+				 use->native_version,
+				 0); // 0 == NOT used by current
+	  CmtSystem::cd (Cmt::get_current_dir ());
+	  restore_current_project ();
+	  return n_use;
+	}
+      else
+	{
+	  CmtSystem::cd (Cmt::get_current_dir ());
+	  CmtMessage::verbose (CmtError::get_error_name (CmtError::package_not_found)
+			       + ": " + use->get_info ());
+	  restore_current_project ();
+	  return 0;
+	}
+    }
+
+  restore_current_project ();
+  return p_use;
+  //  return PackageInfo (name, version, path, "");
+  //  return pa.info ();
+}
+
+//--------------------------------------------------------------------
+void Packages::exclude_current_project ()
+{
+  if (m_i != -1 || m_cur != 0) return;
+  //  cerr << "exclude_current_project: " << m_i << ": " << m_cur << endl;
+  Project::ProjectPtrVector& Ordered = Project::ordered_projects ();
+  int i = -1;
+  //  m_cur = 0;
+  //  Project null;
+  for (i = 0; i < Ordered.size (); i++)
+    if (Ordered[i]->is_current ()) break;
+  if (i >= 0 && i < Ordered.size ())
+    {
+      m_i = i;
+      m_cur = Ordered[i];
+      Ordered[i] = &m_null;
+    }
+}
+
+//--------------------------------------------------------------------
+void Packages::restore_current_project ()
+{
+  Project::ProjectPtrVector& Ordered = Project::ordered_projects ();
+  if (m_i >= 0 && m_i < Ordered.size ())
+    {
+      Ordered[m_i] = m_cur;
+      m_i = -1;
+      m_cur = 0;
+    }
+}
+
+//--------------------------------------------------------------------
+/*
+void Packages::clear ()
+{
+  m_installed = "";
+}
+
+void Packages::install (const cmt_string& line)
+{
+  m_installed += "|";
+  m_installed += line;
+  m_installed += "|";
+}
+
+bool Packages::is_installed (const cmt_string& line)
+{
+  if (m_installed.find (line) != cmt_string::npos)
+    {
+      return (true);
+    }
+  
+  return (false);
+}
+*/
+
+//--------------------------------------------------------------------
 /**
 
@@ -129,43 +472,35 @@
 };
 
-class Walkthru : public Awk
+//--------------------------------------------------------------------
+/**
+ *
+ * Helper classes
+ *
+ */
+
+/*
+class SelectSubUses : public Awk
 {
 public:
-  Walkthru (const Vcs::Checkout& checkout,
-	    bool config, bool with_version_directory,
-	    Vcs::VcsType type);
-  //  RecursivePass2 (CvsImplementation& cvs);
+
   void begin ();
   void filter (const cmt_string& line);
+  //  const cmt_string& result () const;
+  bool has (const cmt_string& package) const;
 
 private:
-  const Vcs::Checkout& m_checkout;
-  bool m_config;
-  bool m_with_version_directory;
-  Vcs::VcsType m_type;
-  //  CvsImplementation& m_cvs;
+  void append (const cmt_string& package);
+  cmt_string m_result;
+  bool m_first;
 };
 
-Walkthru::Walkthru (const Vcs::Checkout& checkout,
-		    bool config, bool with_version_directory,
-		    Vcs::VcsType type)
-  : m_checkout (checkout),
-    m_config (config), m_with_version_directory (with_version_directory),
-    m_type (type)
-{
-}
-
-void Walkthru::begin ()
-{
-}
-
-void Walkthru::filter (const cmt_string& line)
-{
-//   History& h = History::instance ();
-  
-//   if (h.is_installed (line)) return;
-  
-//   h.install (line);
-  
+void SelectSubUses::begin ()
+{
+  m_first = true;
+  m_result = "";
+}
+
+void SelectSubUses::filter (const cmt_string& line)
+{
   CmtSystem::cmt_string_vector words;
   
@@ -183,9 +518,9 @@
   cmt_string version;
   cmt_string path;
-
-  for (int i = 1; i < words.size (); i++)
+  cerr << line;
+  for (int i = 2; i < words.size (); i++)
     {
       const cmt_string& s = words[i];
-
+      cerr << " `" + s + "'"; 
       if (s[0] == '-') continue;
 
@@ -201,38 +536,150 @@
 	  break;
 	case need_path:
-	  path = s;
+	  if (s.find ("(") != 0)
+	    path = s;
 	  state = no_need;
 	  break;
         }
     }
-
+  cerr << endl;
+
+  if (package == "" ||
+      package == "CMT" ||
+      package == "cmt")
+    return;
+  append (package);
+}
+
+void SelectSubUses::append (const cmt_string& package)
+{
+  if (m_first)
+    {
+      m_first = false;
+      m_result = "|" + package + "|";
+    }
+  else
+    {
+      if (!has (package))
+	m_result += package + "|";
+    }
+  cerr << "m_result: " << m_result << endl;
+}
+
+bool SelectSubUses::has (const cmt_string& package) const
+{
+  return (m_result.find ("|" + package + "|") != cmt_string::npos);
+}
+*/
+
+//--------------------------------------------------------------------
+class Walkthru : public Awk
+{
+public:
+  Walkthru (IUseVisitor& visitor);
+  //  RecursivePass2 (CvsImplementation& cvs);
+  void begin ();
+  void filter (const cmt_string& line);
+
+private:
+  //  CvsImplementation& m_cvs;
+  IUseVisitor& m_visitor;
+};
+
+//--------------------------------------------------------------------
+Walkthru::Walkthru (IUseVisitor& visitor)
+  : m_visitor (visitor)
+{
+}
+
+//--------------------------------------------------------------------
+void Walkthru::begin ()
+{
+}
+
+//--------------------------------------------------------------------
+void Walkthru::filter (const cmt_string& line)
+{
+  CmtSystem::cmt_string_vector words;
+  
+  CmtSystem::split (line, " \t", words);
+
+  enum
+    {
+      need_package,
+      need_version,
+      need_path,
+      no_need
+    } state = need_package;
+
+  cmt_string package;
+  cmt_string version;
+  cmt_string path;
+  //  cerr << line;
+  for (int i = 1; i < words.size (); i++)
+    {
+      const cmt_string& s = words[i];
+      //      cerr << " `" + s + "'"; 
+      if (s[0] == '-') continue;
+
+      switch (state)
+        {
+	case need_package:
+	  package = s;
+	  state = need_version;
+	  break;
+	case need_version:
+	  version = s;
+	  state = need_path;
+	  break;
+	case need_path:
+	  if (s.find ("(") != 0 && s.find ("#") != 0)
+	    path = s;
+	  state = no_need;
+	  break;
+        }
+    }
+  //  cerr << endl;
+  
+  if (package == "" ||
+      package == "CMT" ||
+      package == "cmt" ||
+      package == CmtSystem::get_home_package () ||
+      package == CmtSystem::get_user_context_package ()
+      )
+    return;
+  /*
   if (version == "")
-    {
-      version = "*";
-    }
-
-  if (version.find ("*") != cmt_string::npos &&
-      !m_checkout.m_context)
-    {
-      /*
-	cerr << "# ================= Package " << package 
-	<< " version " << version << " " << path 
-	<< " has wild cards and will not be considered." << endl;
-      */
+    version = "*";
+  */
+
+  if (version.find ("*") != cmt_string::npos)
+    {
+// 	cerr << "# ================= Package " << package 
+// 	<< " version " << version << " " << path 
+// 	<< " has wild cards and will not be considered." << endl;
       CmtMessage::warning (package + " " + version +
 			   (path != "" ? " " + path : "") +
-			   " has wildcards in version and will not be considered.");
+			   ": Skipped due to wildcards in version."
+			   " Consider using -C option.");
     }
   else
     {
+      Use use_obj (package, version, path);
+      Use* use = &use_obj;
+      //use->set (name, version, path);
+      use->get_package ()->remove_use (use);
+      m_visitor.in (use);
       //      static const cmt_string empty;
       //      m_cvs.do_checkout_phase2 (path, package, version, empty);
-      cmt_string module ((path != "") ? path + "/" + package : package);
-      Vcs::checkout_module (m_checkout,
-			    m_config, m_with_version_directory,
-			    module, version,
-			    m_type);
-    }
-}
+//       cmt_string module ((path != "") ? path + "/" + package : package);
+//       Vcs::checkout_module (m_checkout,
+// 			    m_config, m_with_version_directory,
+// 			    module, version,
+// 			    m_type);
+    }
+
+}
+
+//--------------------------------------------------------------------
 
 /**
@@ -1180,4 +1627,5 @@
   void add_cmtpath (const cmt_string& dir)
   {
+    return;
     static cmt_string CMTPATH;
 
@@ -3228,4 +3676,5 @@
 }
 
+//--------------------------------------------------------------------
 void Vcs::help ()
 {
@@ -3238,4 +3687,6 @@
   cerr << "   -R          Process used products recursively." << endl;
   cerr << "   -r rev      Check out version tag. (is sticky)" << endl;
+  cerr << "   -C          Determine version tag and/or package container from context." << endl;
+  cerr << "   -i          Do not check out, show package(s) information only." << endl;
   cerr << "   -vd dir     Use this version directory instead of version tag." << endl;
   cerr << "   -d dir      Check out into dir instead of module name." << endl;
@@ -3257,4 +3708,5 @@
 }
 
+//--------------------------------------------------------------------
 /**
  * When running cmt cvs commands, we stand by definition outside of any existing 
@@ -3262,4 +3714,5 @@
  * This function manually prepends CMTPATH entries to the environment variable.
  */
+//--------------------------------------------------------------------
 void Vcs::add_cmtpath (const cmt_string& dir)
 {
@@ -3293,4 +3746,5 @@
 }
 
+//--------------------------------------------------------------------
 bool Vcs::need_version_directory ()
 {
@@ -3312,6 +3766,7 @@
 }
 
-int Vcs::parse_checkout (const CmtSystem::cmt_string_vector& arguments,
-			 Checkout& checkout, bool& config)
+//--------------------------------------------------------------------
+int Vcs::parse_arguments (const CmtSystem::cmt_string_vector& arguments,
+			  Checkout& checkout, bool& config)
 {
   if (arguments.size () < 1)
@@ -3420,4 +3875,12 @@
 	      //m_head = false;
 	    }
+	  else if (option == "-C")
+	    {
+	      checkout.m_context = true;
+	    }
+	  else if (option == "-i")
+	    {
+	      checkout.m_info = true;
+	    }
 	  else if (option == "-d")
 	    {
@@ -3470,4 +3933,10 @@
 	  else
 	    {
+	      if (option.size () == 0)
+		{
+		  CmtMessage::warning ("Skipping bad module `" +
+				       option + "'");
+		  continue;
+		}
 	      checkout.m_modules.push_back (option);
 	    }
@@ -3497,4 +3966,139 @@
 }
 
+//--------------------------------------------------------------------
+class Modules
+{
+public:
+  //  Use::UsePtrVector m_packages;
+  //  cmt_vector<PackageInfo> m_packages;
+  Use::UseVector m_packages;
+  cmt_string m_uses;
+};
+
+//--------------------------------------------------------------------
+int Vcs::parse_checkout (Checkout& checkout,
+			 Modules& modules)
+  //			 cmt_string& uses)
+{
+  int retval (0);
+
+  if (checkout.m_requirements != "")
+    {
+      if (!CmtSystem::test_file (checkout.m_requirements))
+	{
+	  CmtError::set (CmtError::path_not_found, checkout.m_requirements);
+	  ++retval;
+	}
+      else
+	{
+	  cmt_string text;
+	  if (!text.read (checkout.m_requirements))
+	    {
+	      CmtError::set (CmtError::file_access_error, checkout.m_requirements);
+	      ++retval;
+	    }
+	  else
+	    {
+	      modules.m_uses = text;
+	    }
+	}
+    }
+
+  const cmt_string& version_tag = checkout.m_version_tag;
+  if (version_tag == "HEAD" || version_tag == "head" ||
+      version_tag == "TRUNK" || version_tag == "trunk")
+    checkout.m_head = true;
+  
+  cmt_string uses;
+  for (int arg = 0; arg < checkout.m_modules.size (); arg++)
+    {
+      cmt_string use ("use");
+      cmt_string name = checkout.m_modules[arg];
+      cmt_string package;
+      cmt_string version;
+      cmt_string path;
+      /*
+	if (checkout.m_context)
+	{
+	name.replace_all ("//", "/");
+	}
+      */
+      while (name.size () > 0 && name[name.size () - 1] == '/')
+	name.erase (name.size () - 1);
+      if (name.size () == 0)
+	{
+	  CmtError::set (CmtError::syntax_error, "Bad module name `" +
+			 checkout.m_modules[arg] + "'");
+	  CmtError::print ();
+	  continue;
+	}
+      
+      int pos = name.find_last_of ('/');
+      if (pos != cmt_string::npos)
+	{
+	  package = name.substr (pos + 1);
+	  path = name.substr (0, pos);
+	}
+      else
+	{
+	  package = name;
+	}
+      if (checkout.m_context)
+	{
+	  if (version_tag == "" || path == "")
+	    {
+	      Packages& pkgs = Packages::instance ();
+	      //if (version_tag == "") - want to find 1) version
+	      //                                      2) path, if (path == "")
+	      // args: package, version_tag, path
+	      //if (path == "") - want to find 1) path
+	      //                               2) version, if (version_tag == "")
+	      // args: package, "", path
+	      // package, "", path
+	      Use* p_use = pkgs.find (package, "", path);
+	      if (p_use == 0)
+		{
+		  CmtError::set (CmtError::package_not_found, package +
+				 ": Context");
+		  CmtError::print ();
+		  ++retval;
+		  continue;
+		}
+// 	      cerr << "Obtained: " << p_use->get_info ()
+// 		   << " " << p_use->real_path << endl;
+	      if (version_tag == "" )
+		version = p_use->version;
+	      else
+		version = version_tag;
+
+	      path = p_use->path;
+	    }
+	  if (!checkout.m_head)
+	    {
+	      use += " " + package + " " + version + " " + path + "\n";
+	      CmtMessage::verbose (use);
+	      uses += use;
+	    }
+	} // end of checkout.m_context
+      else
+	{
+	  version = version_tag;
+	}
+      {
+	Use use_obj (package, version, path);
+	Use* use = &use_obj;
+	use->get_package ()->remove_use (use);
+	modules.m_packages.push_back (use_obj);
+      }
+    } // end of for-loop over checkout.m_modules
+  if (checkout.m_context)
+    {
+      resolve_uses (checkout, uses + modules.m_uses);
+    }
+
+  return retval;
+}
+
+//--------------------------------------------------------------------
 void Vcs::checkout (const CmtSystem::cmt_string_vector& arguments)
 {
@@ -3524,9 +4128,13 @@
   bool config (true);
   Checkout checkout;
-  parse_checkout (arguments, checkout, config);
+  parse_arguments (arguments, checkout, config);
 
   if (CmtError::has_pending_error ()) return;
 
-  add_cmtpath (CmtSystem::pwd ());
+  //  cmt_string uses;
+  //  parse_checkout (checkout, uses);
+  Modules modules;
+  parse_checkout (checkout, modules);
+  //  add_cmtpath (CmtSystem::pwd ());
   bool with_version_directory (need_version_directory ());
       /*
@@ -3537,10 +4145,87 @@
   if (svnroot != "")
     {
-      Svn::checkout (checkout, config, with_version_directory);
+      Svn::checkout (checkout, modules, config, with_version_directory);
       return;
     }
 }
 
-void Svn::checkout (Vcs::Checkout checkout,
+//--------------------------------------------------------------------
+class VisitorForInfo : public IUseVisitor
+{
+public:
+  VisitorForInfo ()
+  {
+  }
+
+  void in (Use* use)
+  {
+    cmt_string p = use->real_path;
+    if (use->path != "")
+      {
+	int pos = p.find_last_of (use->path);
+	if (pos != cmt_string::npos)
+	  {
+	    p.erase (pos);
+	  }
+      }
+
+    cout << use->get_package_name ()
+	 << " " << use->version;
+    
+    if (CmtSystem::absolute_path (use->path))
+      {
+	if (!Cmt::get_quiet ()) 
+	  {
+	    cout << " (" << use->path << ")";
+	  }
+      }
+    else
+      {
+	if (use->path != "") cout << " " << use->path;
+      }
+    
+    if (!Cmt::get_quiet ()) 
+      {
+	if (p != "") cout << " (" << p << ")";
+      }
+    
+    cout << endl;
+  }
+};
+
+//--------------------------------------------------------------------
+class VisitorForCheckout : public IUseVisitor
+{
+public:
+  VisitorForCheckout (const Vcs::Checkout& checkout,
+		      bool config, bool with_version_directory,
+		      Vcs::VcsType type)
+    : m_checkout (checkout),
+      m_config (config), m_with_version_directory (with_version_directory),
+      m_type (type)
+  {
+  }
+  
+  void in (Use* use)
+  {
+    cmt_string module ((use->path != "") ? use->path + "/" + use->get_package_name () :
+		       use->get_package_name ());
+    Vcs::checkout_module (m_checkout,
+			  m_config, m_with_version_directory,
+			  //			  module, version,
+			  module,
+			  use->version,
+			  m_type);
+  }
+
+private:
+  const Vcs::Checkout& m_checkout;
+  bool m_config;
+  bool m_with_version_directory;
+  Vcs::VcsType m_type;
+};
+
+//--------------------------------------------------------------------
+void Svn::checkout (Vcs::Checkout checkout, Modules modules,
 		   bool config, bool with_version_directory)
 {
@@ -3560,6 +4245,30 @@
 
   /**
+   * Checkout packages found in context
+   */
+  if (checkout.m_context)
+    {
+      Vcs::checkout_context (checkout, modules,
+			     config, with_version_directory,
+			     Vcs::Svn);
+      if (!checkout.m_head) return;
+    }
+
+  /**
    * Call checkout for each command line argument
    */
+  VisitorForInfo visitor_i;
+  VisitorForCheckout visitor_co (checkout,
+				 config, with_version_directory,
+				 Vcs::Svn);
+  for (int i = 0; i < modules.m_packages.size (); i++)
+    {
+      Use* use = &(modules.m_packages[i]);
+      if (checkout.m_info)
+	visitor_i.in (use);
+      else
+	visitor_co.in (use);
+    }
+  /*
   for (int arg = 0; arg < checkout.m_modules.size (); arg++)
     {
@@ -3572,9 +4281,13 @@
       //      do_checkout_phase1 (modules[arg], m_version_dir, version_tag);
     }
+  */
+
+  if (checkout.m_context) return;
 
   /**
    * Call checkout for used package in requirements file
    */
-  if (checkout.m_requirements != "")
+  if (checkout.m_requirements != "" &&
+      modules.m_uses != "")
     Vcs::checkout_from_requirements (checkout,
 				     config, with_version_directory,
@@ -3583,34 +4296,10 @@
 }
 
+//--------------------------------------------------------------------
 void Vcs::checkout_module (const Vcs::Checkout& checkout,
 			   bool config, bool with_version_directory,
-			   const cmt_string& module, cmt_string version_tag,
+			   cmt_string module, cmt_string version_tag,
 			   Vcs::VcsType type)
 {
-//   cmt_string checkout_command;
-//   Symbol* checkout_command_macro = Symbol::find ("svn_checkout_command");
-//   if (checkout_command_macro != 0)
-//     {
-//       checkout_command = checkout_command_macro->resolve_macro_value ();
-//     }
-//   if (checkout_command == "")
-//     {
-//       CmtError::set (CmtError::symbol_not_found,
-// 		     "Macro svn_checkout_command not defined");
-//       return;
-//     }
-  if (checkout.m_context)
-    {
-      int i;
-      if (version_tag == "")
-	// version tag not specified on the command line
-	{
-	}
-      else if ((i = version_tag.find ("*")) != cmt_string::npos)
-	// version has wildcards (or not specified) in requirements
-	{
-	}
-    }
-
   History& h = History::instance ();
   cmt_string line (module + " " + version_tag);
@@ -3631,12 +4320,16 @@
     cmd += " --without_version_directory";
 
-  if (version_tag != "")
+  if (version_tag == "" ||
+      version_tag == "HEAD" || version_tag == "head" ||
+      version_tag == "TRUNK" || version_tag == "trunk"
+      )
+    {
+      msg += (version_tag == "" ? " (HEAD)" : " (" + version_tag + ")");
+      version_tag = "";
+    }
+  else
     {
       cmd += " -r " + version_tag;
       msg += " (" + version_tag + ")";
-    }
-  else
-    {
-      msg += " (HEAD)";
     }
   if (checkout.m_offset != "")
@@ -3656,7 +4349,4 @@
    * Then call checkout for the module
    */
-  //   for (int arg = 0; arg < checkout.m_modules.size (); arg++)
-  //     {
-  //       const cmt_string& module = checkout.m_modules[arg];
   CmtMessage::info ("Working on " + module + msg);
   //      cerr << cmd + " " + module << endl;
@@ -3665,5 +4355,6 @@
     {
       CmtMessage::info (module + " done.");
-      if (checkout.m_recursive)
+      if (checkout.m_recursive && !checkout.m_context)
+	//      if (checkout.m_recursive)
 	{
 	  cmt_string requirements;
@@ -3694,6 +4385,6 @@
 		    { // checkout of trunk
 		      //
-		      static CmtSystem::cmt_string_vector versions;
-		      static cmt_string name;
+		      CmtSystem::cmt_string_vector versions;
+		      cmt_string name;
 		      
 		      name = requirements;
@@ -3750,7 +4441,6 @@
 		      if (n < 1)
 			{
-			  CmtMessage::error ("Cannot find package in " +
-					     requirements +
-					     " for recursion");
+			  CmtMessage::error ("Cannot find package for recursion"
+					     " in " + requirements);
 			  CmtError::set (CmtError::package_not_found,
 					 "in " + requirements);
@@ -3760,10 +4450,12 @@
 		}
 	    } // end of with_version_directory
-	  cmt_string cmt_req = requirements +
+	  cmt_string
+	    cmt_req = requirements +
 	    CmtSystem::file_separator () +
 	    "cmt" +
 	    CmtSystem::file_separator () +
 	    "requirements";
-	  cmt_string mgr_req = requirements +
+	  cmt_string
+	    mgr_req = requirements +
 	    CmtSystem::file_separator () +
 	    "mgr" +
@@ -3797,4 +4489,277 @@
 }
 
+//--------------------------------------------------------------------
+static void visit (const Use::UsePtrVector& uses, IUseVisitor& visitor)
+{
+  for (int i = 0; i < uses.size (); i++)
+    {
+      Use* use = uses[i];
+      if (use == 0) continue;
+      if (use->selected) continue;
+      use->selected = true;
+      if (use->discarded) continue;
+      if (use->m_hidden) continue;
+      if (!use->located ()) continue;
+      if (use->get_package_name () == "CMT") continue;
+      if (use->get_package_name () == "cmt_standalone") continue;
+      if (use->get_package_name () == CmtSystem::get_home_package ()) continue;
+      if (use->get_package_name () == CmtSystem::get_user_context_package ()) continue;
+
+      //      visitor.in (use);
+      visit (use->sub_uses, visitor);
+      visitor.in (use);
+    }
+}
+
+//--------------------------------------------------------------------
+void Vcs::checkout_context (const Vcs::Checkout& checkout, Modules modules,
+			    bool config, bool with_version_directory,
+			    Vcs::VcsType type)
+{
+  VisitorForInfo visitor_i;
+  VisitorForCheckout visitor_co (checkout,
+				 config, with_version_directory,
+				 type);
+  
+  Use* current = &(Use::current ());
+  if (checkout.m_info)
+    visit (current->sub_uses, visitor_i);
+  else
+    visit (current->sub_uses, visitor_co);
+
+}
+
+//--------------------------------------------------------------------
+int Vcs::resolve_uses (const cmt_string& text, cmt_string& uses)
+{
+  cerr << "Vcs::resolve_uses" << endl;
+  cmt_string home_dir = CmtSystem::pwd ();
+  //
+  // Resolve uses by creating a package in a temporary directory
+  //
+  cmt_string tmp_dir = CmtSystem::getenv ("TMPDIR");
+  if (tmp_dir == "")
+    {
+      tmp_dir = CmtSystem::file_separator ();
+      tmp_dir += "tmp";
+    }
+  
+  if (!CmtSystem::test_directory (tmp_dir))
+    //if (!CmtSystem::cd (tmp_dir))
+    {
+      tmp_dir = home_dir;
+    }
+  
+  tmp_dir += CmtSystem::file_separator ();
+  tmp_dir += "cmtvcs";
+  cmt_string temp = CmtSystem::get_temporary_name ();
+  CmtSystem::basename (temp, temp);
+  // Suppress dots for Windows
+  temp.replace_all (".", "");
+  tmp_dir += temp;
+
+  cerr << "tmp_dir: " << tmp_dir << endl;
+  //  tmp_dir = "/tmp/cmtvcsfileEvmagO";
+
+  if (CmtSystem::test_directory (tmp_dir))
+    {
+      if (!CmtSystem::remove_directory (tmp_dir))
+	{
+	  // CmtMessage::error ("Cannot remove temporary directory " + tmp_dir);
+	  // error message printed by CmtSystem::remove_directory
+	  return 1;
+	}
+    }
+  if (!CmtSystem::mkdir (tmp_dir))
+    {
+      CmtMessage::error ("Cannot create temporary directory " + tmp_dir);
+      return 1;
+    }
+
+  cmt_string pkgspec (temp + " v1 " + tmp_dir);
+  if (0 != CmtSystem::execute ("cmt -without_version_directory create " + pkgspec))
+    //  if (0 != CmtSystem::execute ("cmt -with_version_directory create " + pkg))
+    {
+      CmtMessage::error ("Cannot create package " + pkgspec);
+      CmtSystem::remove_directory (tmp_dir);
+      return 1;
+    }
+
+  cmt_string cmt_dir (tmp_dir +
+		      CmtSystem::file_separator () + temp +
+		      //		      CmtSystem::file_separator () + "v1" + 
+		      CmtSystem::file_separator () + "cmt");
+  
+  cmt_string reqtext;
+  cmt_string requirements (cmt_dir +
+			   CmtSystem::file_separator () + "requirements");
+  if (!reqtext.read (requirements))
+    {
+      CmtError::set (CmtError::file_access_error, requirements);
+      CmtSystem::remove_directory (tmp_dir);
+      return 1;
+    }
+
+  FILE* file = fopen (requirements, "wb");
+  if (file != NULL)
+    {
+      (reqtext + text).write (file);
+      CmtSystem::close_ostream (file, requirements);
+      //      fclose (file);
+    }
+  else
+    {
+      CmtError::set (CmtError::file_access_error, requirements);
+      CmtSystem::remove_directory (tmp_dir);
+      return 1;
+    }
+
+  if (!CmtSystem::cd (cmt_dir))
+    {
+      CmtMessage::error ("Cannot move to temporary package directory " + cmt_dir);
+      CmtSystem::remove_directory (tmp_dir);
+      return 1;
+    }
+
+  int status = CmtSystem::execute ("cmt show uses", uses);
+  //  cerr << "status: " << status << endl;
+  if (status != 0)
+    {
+      CmtMessage::error ("Cannot show uses for package " + pkgspec);
+    }
+  //  cerr << "uses:\n" + uses << endl;
+  CmtSystem::cd (home_dir);
+  CmtSystem::remove_directory (tmp_dir);
+  return  status == 0 ? 0 : -1;
+}
+
+//--------------------------------------------------------------------
+int Vcs::resolve_uses (const cmt_string& text, Use::UsePtrVector& uses)
+{
+  cerr << "Vcs::resolve_uses NEW" << endl;
+  cmt_string home_dir = CmtSystem::pwd ();
+
+  Use* current = &(Use::current());
+
+  SyntaxParser::parse_requirements_text (text, "", current);
+
+  cerr <<  "recursive: " <<  Cmt::get_recursive () << endl;
+
+  Use::show_all ();
+
+  if (CmtError::get_last_error_code () == CmtError::package_not_found)
+    CmtError::print ();
+
+  return -1;
+}
+
+//--------------------------------------------------------------------
+int Vcs::resolve_uses (const Checkout& checkout, const cmt_string& uses)
+  //int Vcs::resolve_uses (const Checkout& checkout, const Modules& modules)
+{
+  if (!checkout.m_context) return 0;
+
+  //  cerr << "Vcs::resolve_uses NEW+" << endl;
+  cmt_string home_dir = CmtSystem::pwd ();
+  //
+  // Resolve uses by creating a package in a temporary directory
+  //
+  cmt_string tmp_dir = CmtSystem::getenv ("TMPDIR");
+  if (tmp_dir == "")
+    {
+      tmp_dir = CmtSystem::file_separator ();
+      tmp_dir += "tmp";
+    }
+  
+  if (!CmtSystem::test_directory (tmp_dir))
+    //if (!CmtSystem::cd (tmp_dir))
+    {
+      tmp_dir = home_dir;
+    }
+  
+  tmp_dir += CmtSystem::file_separator ();
+  tmp_dir += "cmtvcs";
+  cmt_string temp = CmtSystem::get_temporary_name ();
+  CmtSystem::basename (temp, temp);
+  // Suppress dots for Windows
+  temp.replace_all (".", "");
+  tmp_dir += temp;
+
+  if (CmtSystem::test_directory (tmp_dir))
+    {
+      if (!CmtSystem::remove_directory (tmp_dir))
+	{
+	  CmtError::set (CmtError::file_access_error, tmp_dir);
+	  // CmtMessage::error ("Cannot remove temporary directory " + tmp_dir);
+	  // error message printed by CmtSystem::remove_directory
+	  return 1;
+	}
+    }
+  if (!CmtSystem::mkdir (tmp_dir))
+    {
+      CmtError::set (CmtError::file_access_error,
+		     "Cannot create temporary directory " + tmp_dir);
+      CmtError::print ();
+      //CmtMessage::error ("Cannot create temporary directory " + tmp_dir);
+      return 1;
+    }
+
+    if (!CmtSystem::cd (tmp_dir))
+    {
+      CmtError::set (CmtError::file_access_error,
+		     "Cannot move to temporary package directory " + tmp_dir);
+      CmtError::print ();
+     //CmtMessage::error ("Cannot move to temporary package directory " + tmp_dir);
+      CmtSystem::remove_directory (tmp_dir);
+      return 1;
+    }
+
+  Project::ProjectPtrVector& Ordered = Project::ordered_projects ();
+  int i (-1);
+  Project* cur (0);
+  Project null;
+  for (i = 0; i < Ordered.size (); i++)
+    if (Ordered[i]->is_current ()) break;
+  if (i >= 0 && i < Ordered.size ())
+    {
+      cur = Ordered[i];
+      Ordered[i] = &null;
+    }
+
+  bool cur_recursive (Cmt::get_recursive ());
+  CmtScopeFilteringMode
+    cur_scope_filtering_mode (Cmt::get_scope_filtering_mode ());
+  if (checkout.m_recursive)
+    {
+      Cmt::set_recursive (true);
+      Cmt::set_scope_filtering_mode (reach_private_uses);
+    }
+
+  SyntaxParser::parse_requirements_text (uses, "", &(Use::current()));
+
+  if (checkout.m_recursive)
+    {
+      Cmt::set_recursive (cur_recursive);
+      Cmt::set_scope_filtering_mode (cur_scope_filtering_mode);
+    }
+
+  if (i >= 0 && i < Ordered.size ())
+    {
+      Ordered[i] = cur;
+    }
+
+  CmtSystem::cd (home_dir);
+  CmtSystem::remove_directory (tmp_dir);
+
+  if (CmtError::get_last_error_code () == CmtError::package_not_found)
+    {
+      CmtError::print ();
+      return -1;
+    }
+
+  return 0;
+}
+
+//--------------------------------------------------------------------
 void Vcs::checkout_from_requirements (const Vcs::Checkout& checkout,
 				      bool config,
@@ -3808,18 +4773,23 @@
   if (!text.read (requirements))
     {
-      CmtError::set (CmtError::path_not_found, requirements);
+      CmtError::set (CmtError::file_access_error, requirements);
       return;
     }
+
   static cmt_regexp expression ("^[ \t]*use[ \t]");
-
-//   RecursivePass1 p1;
-//   p1.run (text, expression);
-//   bool result = (p1.result () != "");
-//   if (result)
-//     cerr << p1.result () << endl;
-  Walkthru wth (checkout,
-		config,
-		with_version_directory,
-		type);
-  wth.run (text, expression);
-}
+  if (checkout.m_info)
+    {
+      VisitorForInfo visitor_i;
+      Walkthru wth (visitor_i);
+      wth.run (text, expression);
+    }
+  else
+    {
+      VisitorForCheckout visitor_co (checkout,
+				     config, with_version_directory,
+				     type);
+      Walkthru wth (visitor_co);
+      wth.run (text, expression);
+    }
+}
+//--------------------------------------------------------------------
