//-----------------------------------------------------------
// Copyright Christian Arnault LAL-Orsay CNRS
// arnault@lal.in2p3.fr
// Modified by garonne@lal.in2p3.fr
// See the complete license in cmt_license.txt "http://www.cecill.info". 
//-----------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

//----------------------------------------------------------

#include "cmt_parser.h"
#include "cmt_version.h"

#include "cmt_database.h"
#include "cmt_include.h"
#include "cmt_script.h"
#include "cmt_generator.h"
#include "cmt_system.h"
#include "cmt.h"
#include "cmt_error.h"
#include "cmt_cvs.h"
#include "cmt_vcs.h"
#include "cmt_lock.h"
#include "cmt_triggers.h"
#include "cmt_model.h"
#include "cmt_awk.h"
#include "cmt_syntax.h"
#include "cmt_install_area.h"
#include "cmt_cmtpath_pattern.h"
#include "cmt_sequence.h"
#include "cmt_map.h"
#include "cmt_project.h"
#include "cmt_log.h"
#include "cmt_commands.h"

//----------------------------------------------------------
//
//  Static object definitions for the CmtContext class.
//

static CmtContext Me;

CmtContext::CmtContext ()
{
  clear ();
}

CmtContext::~CmtContext ()
{
}

void CmtContext::clear ()
{
  m_action         = action_none;
  m_build_nmake    = false;
  m_cmt_config     = "";
  //m_cmt_path.clear ();
  //m_cmt_path_pwds.clear ();
  //m_cmt_path_sources.clear ();
  m_cmt_root       = "";
  m_cmt_version    = "";
  m_use_cmt        = true;
  m_current_dir     = "";
  m_current_file_path = "";
  m_current_package = "";
  m_current_config  = "";
  m_current_path    = "";
  m_current_prefix  = "";
  m_current_cmtpath = "";
  m_current_offset  = "";

  m_current_access   = DeveloperMode;

  m_current_tag      = "";
  m_current_target   = "";
  m_current_version  = "";
  m_default_path     = "";

  //m_quiet            = false;

  m_disable_warnings = false;
  m_warnings         = false;
  m_recursive        = false;

  m_scope_filtering_mode = default_filtering_mode;
  m_simulation       = false;

  m_standard_macros_done = false;
  m_current_access = UserMode;
  m_current_style = cmt_style;
  m_current_structuring_style = default_structuring_style;
  m_all_sets_done = false;
  m_autoconfigure_cmtpath = false;
  m_debug = false;
  if (getenv ("CMTDEBUG") != 0) m_debug = true;
}

//----------------------------------------------------------


//----------------------------------------------------------
//
//   Utility classes
//
//----------------------------------------------------------

/**
 *  This PathScanner actor simply displays the package name/version/path
 *  It is used by the cmt show packages operation
 */
class PackageViewer : public PathScanner::actor
{
public:
  void run (const cmt_string& package,
            const cmt_string& version,
            const cmt_string& path,
            const bool without_version_directory=false);
};


/**
 *  This PathScanner actor accumulates all found packages into a cmt_string_vector
 *  It is used by the broadcast operation
 */
class PackageSelector : public PathScanner::actor
{
public:
  PackageSelector (CmtSystem::cmt_string_vector& uses);
  void run (const cmt_string& package,
            const cmt_string& version,
            const cmt_string& path,
            const bool without_version_directory=false);
private:
  CmtSystem::cmt_string_vector& m_uses;
};



/**
 *  This PathScanner actor collects all packages clients of the specified one
 *  It is used by the cmt show clients operation
 */
class ClientCollector : public PathScanner::actor
{
public:
  ClientCollector (const cmt_string& package,
		   const cmt_string& version);
  void run (const cmt_string& package,
            const cmt_string& version,
            const cmt_string& path,
            const bool without_version_directory=false);
  int count ();

private:
  const cmt_string& m_package;
  const cmt_string& m_version;
  int m_count;
};

//----------------------------------------------------------
void PackageViewer::run (const cmt_string& package,
                         const cmt_string& version,
                         const cmt_string& path,
                         const bool without_version_directory)
{
  cout << package << " " << version << " " << path << endl;
}

//----------------------------------------------------------
PackageSelector::PackageSelector (CmtSystem::cmt_string_vector& uses) : m_uses(uses)
{
}

//----------------------------------------------------------
void PackageSelector::run (const cmt_string& package,
                           const cmt_string& version,
                           const cmt_string& path,
                           const bool without_version_directory)
{
  //
  // this might be called on a package with no version directory.
  // then simply the version argument is empty.
  // 

  cmt_string r = CmtSystem::file_separator ();
  r += "requirements";

  cmt_string temp;

  if (version == "")
    {
      temp = path;
      //temp += CmtSystem::file_separator ();
      //temp += package;
      temp += CmtSystem::file_separator ();
      temp += "cmt";
      temp += r;
      
      if (!CmtSystem::test_file (temp)) return;
    }
  else
    {
      temp = path;
      //temp += CmtSystem::file_separator ();
      //temp += package;
      temp += CmtSystem::file_separator ();
      temp += version;
      temp += CmtSystem::file_separator ();
      temp += "cmt";
      temp += r;
      
      if (!CmtSystem::test_file (temp))
        {
          temp = path;
          //temp += CmtSystem::file_separator ();
          //temp += package;
          temp += CmtSystem::file_separator ();
          temp += version;
          temp += CmtSystem::file_separator ();
          temp += "mgr";
          temp += r;
          
          if (!CmtSystem::test_file (temp))
            {
              return;
            }
        }
    }

  temp.replace (r.c_str(), "");
  cmt_string& use = m_uses.add ();
  use = temp;
}

//----------------------------------------------------------
ClientCollector::ClientCollector (const cmt_string& package,
				  const cmt_string& version) :
  m_package (package), m_version (version), m_count (0)
{
}

//----------------------------------------------------------
void ClientCollector::run (const cmt_string& package,
			   const cmt_string& version,
			   const cmt_string& path,
			   const bool without_version_directory)
{
  cmt_string dir = path;
  dir += CmtSystem::file_separator ();
  dir += package;
  dir += CmtSystem::file_separator ();      
  if (version != "" && ! without_version_directory)
    {
      dir += version;
      dir += CmtSystem::file_separator ();
    }

  cmt_string req;
 
  req  = dir;
  req += "cmt";
  req += CmtSystem::file_separator ();
  req += "requirements";

  cmt_string requirements;
  cmt_string line;
  CmtSystem::cmt_string_vector words;

  if (CmtSystem::test_file (req))
    {
      requirements.read (req);
    }
  else
    {
      req = dir;
      req += "mgr";
      req += CmtSystem::file_separator ();
      req += "requirements";
      if (CmtSystem::test_file (req))
        {
          requirements.read (req);
        }
    }

  if (requirements != "")
    {
      int pos = 0;
      int max_pos = requirements.size ();

      while (pos < max_pos)
        {
          int cr = requirements.find (pos, "\r\n");
          int nl = requirements.find (pos, '\n');
          int first = nl;
          int length = 1;
                
          if (cr != cmt_string::npos)
            {
              if (nl == cmt_string::npos)
                {
                  first = cr;
                  length = 2;
                }
              else
                {
                  first = (nl < cr) ? nl : cr;
                  length = (nl < cr) ? 1 : 2;
                }
            }
                
          if (first == cmt_string::npos)
            {
              requirements.substr (pos, line);
              pos = max_pos;
            }
          else if (first > pos)
            {
              requirements.substr (pos, first - pos, line);
              pos = first + length;
            }
          else
            {
              line.erase (0);
              pos += length;
            }

          CmtSystem::split (line, " \t", words);

          if ((words.size () >= 2) && (words[0] == "use")) 
            {
              if ((words[1] == m_package) && 
                  ( (m_version == "") || (words[2] == m_version)))
                {
                  cout << "# " << package << " " << version << " " << path;
                  if (m_version == "" && words.size () > 2)
                    {
                      cout << " (use version " << words[2] << ")";
                    }
                  cout << endl;
                  m_count++;
                }
            }
        }
    }
}

//----------------------------------------------------------
int ClientCollector::count ()
{
  return (m_count);
}




//----------------------------------------------------------
//
//   The Cmt methods
//
//----------------------------------------------------------



/**
 *   Append "CONFIG" to the prefix
 */
void Cmt::build_config (const cmt_string& prefix,
                        cmt_string& config)
{
  /*
    Building the config from <prefix> 
  */

  config = prefix;
  config += "CONFIG";
}

//----------------------------------------------------------
void Cmt::build_makefile (const cmt_string& target)
{
  Constituent* constituent = 0;

  if (target.size () > 0)
    {
      /*
        Do genmake for one specific target.
      */
      constituent = Constituent::find (target);
      if (constituent != 0)
        {
          constituent->build_makefile (Me.m_simulation);
        }
    }
  else
    {
      /*
        Do genmake for all possible targets.
      */
      Constituent::build_all_makefiles (Me.m_simulation);
    }
}

//----------------------------------------------------------
void Cmt::build_msdev_file (const cmt_string& target)
{
  Constituent* constituent = 0;

  set_standard_macros ();

  if (target != "")
    {
      /*
        Do genmsdev for one specific target.
      */
      constituent = Constituent::find (target);
      if (constituent != 0)
        {
          constituent->build_msdev_file (Me.m_simulation);
        }
    }
  else
    {
      /*
        Do genmsdev for all possible targets.
      */
      Constituent::build_all_msdev_files (Me.m_simulation);
    }
}

/**
   Visual Studio.net Support                                 
*/
void Cmt::build_vsnet_file (const cmt_string& target)        
{                                                            
  Constituent* constituent = 0;                              
                                                             
  set_standard_macros ();                                    
                                                             
  if (target != "")                                          
    {                                                        
      /*                                                     
							     Do genvsnet for one specific target.                 
      */                                                     
      constituent = Constituent::find (target);              
      if (constituent != 0)                                  
        {                                                    
          constituent->build_vsnet_file (Me.m_simulation);        
        }                                                    
    }                                                        
  else                                                       
    {                                                        
      /*                                                     
							     Do genvsnet for all possible targets.                
      */                                                     
      Constituent::build_all_vsnet_files (Me.m_simulation);       
    }                                                        
}                                                            

//----------------------------------------------------------
bool Cmt::build_nmake ()
{
  return (Me.m_build_nmake);
}

//----------------------------------------------------------
void Cmt::build_OS9_makefile (const cmt_string& target)
{
  build_makefile (target);
}

/**
 *   Convert a package name to its upper case copy
 */
void Cmt::build_prefix (const cmt_string& package, cmt_string& prefix)
{
  int pos;
  char c;

  /*
    Building the prefix from <package> 
  */

  prefix = package;

  for (pos = 0; pos < package.size (); pos++)
    {
      c = package[pos];
      prefix[pos] = toupper (c);
    }
}

//----------------------------------------------------------
void Cmt::clear ()
{
  Me.m_quiet = false;
  Me.clear ();

  Database::clear ();
  Include::clear_all ();
  Script::clear_all ();
  CmtError::clear ();
}

//----------------------------------------------------------
//void Cmt::configure ()
void Cmt::configure (const ArgParser& ap)
{
  Log;
  static bool configured = false;

  if (configured) return;

  Me.clear ();

  log << "configure_cmt_message" << log_endl;
  //configure_cmt_message ();
  configure_cmt_message (ap);

  log << "configure_default_path" << log_endl;
  configure_default_path ();
  log << "configure_version_tag" << log_endl;
  configure_version_tag ();
  log << "configure_uname_tag" << log_endl;
  configure_uname_tag ();
  log << "configure_hosttype_tag" << log_endl;
  configure_hosttype_tag ();
  log << "configure_config_tag" << log_endl;
  configure_config_tag ();
  log << "configure_site_tag" << log_endl;
  configure_site_tag (0);
  log << "configure_current_dir" << log_endl;
  configure_current_dir ();
  log << "configure_home" << log_endl;
  // CMTHOME, CMTUSERCONTEXT and CMTPATH
  configure_home (0);
  //  log << "configure_current_dir" << log_endl;


  bool save_quiet = Me.m_quiet;
  Me.m_quiet = true;

  Me.m_autoconfigure_cmtpath = true;
  configure_cmt_path (0);
  Me.m_autoconfigure_cmtpath = false;

  Me.m_quiet = save_quiet;

  //  configure_current_dir ();

  guess_current_project ();

  log << "configure_current_structuring_style" << log_endl;
  //  configure_current_structuring_style ();
  configure_current_structuring_style (ap);

  log << "configure_current_package" << log_endl;
  configure_current_package ();

  Use& use = Use::current();

  use.set (Me.m_current_package,
           Me.m_current_version,
           Me.m_current_path,
           "",
           "");

  use.style = Me.m_current_style;
  use.structuring_style = Me.m_current_structuring_style;

  use.change_path (Me.m_current_path);

  if (CmtError::has_pending_error ()) 
    {
      Me.m_configure_error = CmtError::get_last_error ();
    }
}

//----------------------------------------------------------
void Cmt::configure_cmt_path (Use* use)
{
  if (!Me.m_autoconfigure_cmtpath) return;

  cmt_string s;

  s = Symbol::get_env_value ("CMTPATH");

  {
    bool q = Me.m_quiet;
    Me.m_quiet = true;  

    Symbol::filter_path_value ("CMTPATH", s);

    Me.m_quiet = q;
  }

  IProjectFactory& factory = ProjectFactory::instance ();
  factory.reset ();

  CmtSystem::get_cmt_paths (factory, s, Me.m_cmt_user_context, Me.m_cmt_home);
}

//----------------------------------------------------------
void Cmt::configure_config_tag ()
{
  Me.m_cmt_config = CmtSystem::get_cmt_config ();
  if (Me.m_cmt_config != "")
    {
      Tag* tag;

      tag = Tag::add (Me.m_cmt_config, PriorityConfig, "CMTCONFIG", 0);
      tag->mark ("CMTCONFIG");
    }
}

//----------------------------------------------------------
void Cmt::configure_current_cmtpath ()
{
  Use& current_use = Use::current ();

  Me.m_current_cmtpath = "";
  Me.m_current_offset = "";

  Me.m_current_cmtpath = Project::find_in_cmt_paths (current_use.path);

  if (Me.m_current_cmtpath != "")
    {
      static const cmt_string empty_string;
      static const cmt_string fs = CmtSystem::file_separator ();

      Me.m_current_offset = current_use.path;

      /**
	 try to remove this current CMTPATH entry from path.  This
	 has a meaning when the specified path already contains an
	 absolute path.
      */
      
      Me.m_current_offset.replace (Me.m_current_cmtpath, empty_string);
      if (Me.m_current_offset[0] == CmtSystem::file_separator ())
	{
	  // Just in case there is a part left after removing the cmtpath entry
	  
	  Me.m_current_offset.replace (fs, empty_string);
	}
    }
}

class CmtMountFilterParser : public FAwk
{
public:

  CmtMountFilterParser ()
  {
    reset ();
  }

  void reset ()
  {
    m_current_dir = CmtSystem::pwd ();

    m_done = false;
    m_prefix = "";
  }

  bool is_done () const
  {
    return (m_done);
  }

  const cmt_string& get_current_dir () const
  {
    return (m_current_dir);
  }

  void set_prefix (const cmt_string& prefix)
  {
    m_prefix = prefix;
  }

  void filter (const cmt_string& line)
  {
    if (m_done) 
      {
	stop ();
	return;
      }

    CmtSystem::cmt_string_vector words;

    CmtSystem::split (line, " \t", words);

    int requested = 2;

    if (m_prefix != "")
      {
	requested++;
      }

    if (words.size () < requested) return;

    int n = 0;

    if (m_prefix != "")
      {
	if (words[n] != m_prefix) return;
	n++;
      }

    cmt_string& path_name = words[n];
    cmt_string& replacement = words[n+1];
    
    if (m_current_dir.find (path_name) != cmt_string::npos)
      {
	m_current_dir.replace (path_name, replacement);
	m_done = true;
	stop ();
      }
  }

private:
  bool m_done;
  cmt_string m_prefix;
  cmt_string m_current_dir;
};

//----------------------------------------------------------
void Cmt::configure_current_dir ()
{
  cmt_string file_name;

  /*
    Building current_dir :

    o we first get the physical value (using getwd)
    o then this value is possibly filtered using the
    cmt_mount_filter file.
  */

  CmtMountFilterParser mount_filter;

  /**
     First try with ${CMTROOT}/mgr/cmt_mount_filter
     with no prefix on lines
  */

  file_name = Me.m_default_path;
  if (file_name != "")
    {
      file_name += CmtSystem::file_separator ();
      file_name += "CMT";
      file_name += CmtSystem::file_separator ();
      file_name += Me.m_cmt_version;
      file_name += CmtSystem::file_separator ();
      file_name += "mgr";
      file_name += CmtSystem::file_separator ();
    }

  file_name += "cmt_mount_filter";

  mount_filter.run (file_name);

  /**
     Now try with .cmtrc
     with "mount_filter" keyword
  */

  mount_filter.set_prefix ("mount_filter");

  mount_filter.run (".cmtrc");

  /**
     Now try with ${HOME}/.cmtrc
     with "mount_filter" keyword
  */

  if (CmtSystem::get_home_directory (file_name))
    {
      file_name += CmtSystem::file_separator ();
      file_name += ".cmtrc";
      mount_filter.run (file_name);
    }

  Me.m_current_dir = mount_filter.get_current_dir ();
  Me.m_current_file_path = mount_filter.get_current_dir ();

  cmt_string t = Me.m_current_file_path;
}

//----------------------------------------------------------
void Cmt::configure_current_package ()
{
  /*
    Build current_package and current_prefix.

    This is only possible if we are within the cmt/mgr branch of a
    standard directory tree (i.e. <package>/<version>/cmt or mgr)
  */

  cmt_string req = "..";
  req += CmtSystem::file_separator ();
  req += "cmt";
  req += CmtSystem::file_separator ();
  req += "requirements";

  if (CmtSystem::test_file (req))
    {
      Me.m_current_style = cmt_style;
    }
  else
    {
      cmt_string req = "..";
      req += CmtSystem::file_separator ();
      req += "mgr";
      req += CmtSystem::file_separator ();
      req += "requirements";

      if (CmtSystem::test_file (req))
	{
	  Me.m_current_style = mgr_style;
	}
      else
	{
	  // This package is probably a standalone one
	  Me.m_current_style = none_style;
	}
    }


  if (Me.m_current_style != none_style)
    {
      //
      //  Here there is a ../cmt or ../mgr branch in front of us
      //  and there is a requirements file there
      //

      cmt_string up_dir;
      cmt_string up_branch;

      CmtSystem::dirname (Me.m_current_dir, up_dir);
      CmtSystem::basename (up_dir, up_branch);

      cmt_string cmt_dir = "..";
      cmt_dir += CmtSystem::file_separator ();
      switch (Me.m_current_style)
	{
	case cmt_style:
	  cmt_dir += "cmt";
	  break;
	case mgr_style:
	  cmt_dir += "mgr";
	  break;
	default:
	  break;
	}
      //      version_file += CmtSystem::file_separator ();
      //      version_file += "version.cmt";

      //      if (CmtSystem::test_file (version_file))
      if (CmtSystem::test_file (cmt_dir
				+ CmtSystem::file_separator ()
				+ Package::get_version_file_name ())
	  )
	{
	  // 
	  // There is an explicit version descriptor. This one takes precedence
	  // and forces the structuring style to no directory
	  //

          Me.m_current_package = up_branch;
          CmtSystem::dirname (up_dir, Me.m_current_path);

	  /*
	  if (Me.m_current_version.read (version_file))
	    {
	      int pos;

	      pos = Me.m_current_version.find ('\n');
	      if (pos != cmt_string::npos) Me.m_current_version.erase (pos);
	      pos = Me.m_current_version.find ('\r');
	      if (pos != cmt_string::npos) Me.m_current_version.erase (pos);
	    }
	  else
	    {
	      Me.m_current_version = "v*";
	      CmtMessage::warning ("Could not read `" + version_file + "'."
				   " Default version `" + Me.m_current_version + "'");
	    }
	  */
	  cmt_string v;
	  //	  if (Package::get_version (v, version_file))
	  if (Package::get_version (v, cmt_dir))
	    {
	      Me.m_current_version = v;
	    }
	  else
	    {
	      Me.m_current_version = "v*";
	      CmtMessage::warning ("Structuring style used `without_version_directory'."
				   " Could not determine version in `" + cmt_dir + "'."
				   " Default version `" + Me.m_current_version + "'");
	    }

	  if (Me.m_debug)
	    {
	      cout << "Cmt::configure_current_package>" << endl
		   << " m_current_package " << Me.m_current_package << endl
		   << " m_current_version " << Me.m_current_version << endl
		   << " m_current_dir " << Me.m_current_dir << endl
		   << " pwd " << CmtSystem::pwd ()
		   << endl;
	    }

          Me.m_current_structuring_style = without_version_directory;
	  //          Me.m_current_style = no_version_style;
	}
      else
	{
	  // Try to use directory structure and
	  // package statement in requirements, if available
	  cmt_string up_up_dir;
	  cmt_string up_up_branch;
	  CmtSystem::dirname (up_dir, up_up_dir);
	  CmtSystem::basename (up_up_dir, up_up_branch);

	  cmt_string n;
	  bool done (false);
	  if (Package::get_name (n, cmt_dir))
	    {
	      if (n == up_branch)
		{
		  Me.m_current_package = up_branch;
		  Me.m_current_path = up_up_dir;
		  Me.m_current_structuring_style = without_version_directory;
		  cmt_string v;
		  if (Package::get_version (v, cmt_dir))
		    {
		      Me.m_current_version = v;
		    }
		  else
		    {
		      // No version descriptor
		      // No version directory. The version is defaulted to v*
		      Me.m_current_version = "v*";
		      CmtMessage::warning ("Structuring style used `without_version_directory'."
					   " Could not determine version in `" + cmt_dir + "'."
					   " Default version `" + Me.m_current_version + "'");
		    }
		  done =true;
		}
	      else if (n == up_up_branch)
		{
		  // The up branch IS a version directory.
		  Me.m_current_version = up_branch;
		  Me.m_current_package = up_up_branch;
		  CmtSystem::dirname (up_up_dir, Me.m_current_path);
		  Me.m_current_structuring_style = with_version_directory;
		  done =true;
		}
	      else
		{
		  CmtMessage::warning ("Package name `" + n + "' in `" + cmt_dir +
				       "' does not correspond to directory"
				       " structure");
		}
	    }

	  if (!done)
	    {
	  // Try to determine the structuring style from:
	  //
	  CmtStructuringStyle structuring_style(default_structuring_style);
	  CmtStructuringStyle style(default_structuring_style);
	  // - the command line options
	  //   or
	  // - the CMTSTRUCTURINGSTYLE environment variable
	  if (structuring_style == default_structuring_style)
	    {
	      structuring_style = get_current_structuring_style ();
	    }
	  // - the project the package belongs to
	  if (structuring_style == default_structuring_style)
	    {
	      Project* p = Project::get_current ();
	      if (p)
		{
		  style = p->get_strategy ("VersionDirectory") ? with_version_directory : without_version_directory ;
		  StrategyDef* def = StrategyMgr::find_strategy ("VersionDirectory");
		  if (def != 0)
		    {
		      if (p->is_specified (def)) structuring_style = style;
		    }
		}
	    }
	  // - the child projects of the project the package belongs to
	  if (structuring_style == default_structuring_style)
	    {
	      structuring_style = style;
	    }
	  // - the default value of the Structure strategy
	  if (structuring_style == default_structuring_style)
	    {
	      structuring_style = StrategyMgr::get_default_strategy ("VersionDirectory") ? with_version_directory : without_version_directory ;
	    }

	  // Make use of the structuring style
	  //
	  if (structuring_style == with_version_directory && CmtSystem::is_version_directory (up_branch))
	    {
	      // The up branch IS a version directory.
	      Me.m_current_version = up_branch;
	      Me.m_current_package = up_up_branch;
	      CmtSystem::dirname (up_up_dir, Me.m_current_path);
	      /*
	      CmtSystem::dirname (up_dir, up_dir);
	      CmtSystem::basename (up_dir, Me.m_current_package);
	      CmtSystem::dirname (up_dir, Me.m_current_path);
	      */
	      Me.m_current_structuring_style = with_version_directory;
	    }
	  else
	    {
	      if (structuring_style == with_version_directory)
		{
		  CmtMessage::warning ("`" + up_branch + "' is not correct version syntax."
				       " Assuming it is package name");
		}
	      Me.m_current_package = up_branch;
	      Me.m_current_path = up_up_dir;
	      //	      CmtSystem::dirname (up_dir, Me.m_current_path);
	      Me.m_current_structuring_style = without_version_directory;
	      cmt_string v;
	      if (Package::get_version (v, cmt_dir))
		{
		  Me.m_current_version = v;
		}
	      else
		{
	      // No version descriptor
	      // No version directory. The version is defaulted to v*
		  Me.m_current_version = "v*";
		  CmtMessage::warning ("Structuring style used `without_version_directory'."
				       " Could not determine version in `" + cmt_dir + "'."
				       " Default version `" + Me.m_current_version + "'");
		}
	      
	      //	      Me.m_current_style = no_version_style;
	    }
	    }
	}
      build_prefix (Me.m_current_package, Me.m_current_prefix);
      build_config (Me.m_current_prefix, Me.m_current_config);
    }
  else
    {
      Me.m_current_package = "cmt_standalone";
      Me.m_current_version = "v0";
      Me.m_current_path = Me.m_current_dir;
      // Do NOT (re)set m_current_structuring_style yet
      // (as requirements may NOT exist, so this is not a package)
      // rather do it in reach_current_package (if/when requirements is read)
      //Me.m_current_structuring_style = without_version_directory;
      build_prefix (Me.m_current_package, Me.m_current_prefix);
      build_config (Me.m_current_prefix, Me.m_current_config);
    }
}

//----------------------------------------------------------
//void Cmt::configure_current_structuring_style ()
void Cmt::configure_current_structuring_style (const ArgParser& ap)
{
  cmt_string s;
  s = CmtSystem::getenv ("CMTSTRUCTURINGSTYLE");
  if (s == "without_version_directory")
    {
      Me.m_current_structuring_style = without_version_directory;
    }
  else if (s == "with_version_directory")
    {
      Me.m_current_structuring_style = with_version_directory;
    } 

  CmtSystem::cmt_string_vector flags;
  Cmt::get_cmt_flags (flags);
  for (int i = 0; i < flags.size (); i++)
    {
      const cmt_string& flag = flags[i];
      if (flag == "-without_version_directory")
	{
	  Me.m_current_structuring_style = without_version_directory;
	}
      else if (flag == "-with_version_directory")
	{
	  Me.m_current_structuring_style = with_version_directory;
	} 
    }

  for (int i = 1; i < ap.argc; i++)
    {
      const cmt_string& arg = ap.argv[i];
      if (arg[0] != '-') break;
      if (arg == "-without_v" ||
	  arg == "-without_ve" ||
	  arg == "-without_ver" ||
	  arg == "-without_vers" ||
	  arg == "-without_versi" ||
	  arg == "-without_versio" ||
	  arg == "-without_version" ||
	  arg == "-without_version_" ||
	  arg == "-without_version_d" ||
	  arg == "-without_version_di" ||
	  arg == "-without_version_dir" ||
	  arg == "-without_version_dire" ||
	  arg == "-without_version_direc" ||
	  arg == "-without_version_direct" ||
	  arg == "-without_version_directo" ||
	  arg == "-without_version_director" ||
	  arg == "-without_version_directory")
	{
	  Me.m_current_structuring_style = without_version_directory;
	  //	  if (!CmtSystem::putenv ("CMTSTRUCTURINGSTYLE", "without_version_directory"))
	  //	    CmtMessage::error ("Cannot set `CMTSTRUCTURINGSTYLE' to"
	  //			       " `without_version_directory' in the environment");
	  if (!Cmt::add_cmt_flag ("-without_version_directory"))
	    CmtMessage::error ("Cannot add flag `-without_version_directory'");
	}
      else if (arg == "-with_v" ||
	       arg == "-with_ve" ||
	       arg == "-with_ver" ||
	       arg == "-with_vers" ||
	       arg == "-with_versi" ||
	       arg == "-with_versio" ||
	       arg == "-with_version" ||
	       arg == "-with_version_" ||
	       arg == "-with_version_d" ||
	       arg == "-with_version_di" ||
	       arg == "-with_version_dir" ||
	       arg == "-with_version_dire" ||
	       arg == "-with_version_direc" ||
	       arg == "-with_version_direct" ||
	       arg == "-with_version_directo" ||
	       arg == "-with_version_director" ||
	       arg == "-with_version_directory")
	{
	  Me.m_current_structuring_style = with_version_directory;
	  //	  if (!CmtSystem::putenv ("CMTSTRUCTURINGSTYLE", "with_version_directory"))
	  //	    CmtMessage::error ("Cannot set `CMTSTRUCTURINGSTYLE' to"
	  //			       " `with_version_directory' in the environment");
	  if (!Cmt::add_cmt_flag ("-with_version_directory"))
	    CmtMessage::error ("Cannot add flag `-with_version_directory'");
	}
    }
}

//----------------------------------------------------------
void Cmt::configure_default_path ()
{
  Me.m_default_path = CmtSystem::get_cmt_root ();
  CmtSystem::get_cmt_version (Me.m_cmt_version);
  Me.m_cmt_root = Me.m_default_path;
  Me.m_cmt_root += CmtSystem::file_separator ();
  Me.m_cmt_root += "CMT";
  Me.m_cmt_root += CmtSystem::file_separator ();
  Me.m_cmt_root += Me.m_cmt_version;
}

//----------------------------------------------------------
void Cmt::configure_home (Use* use)
{
  Me.m_cmt_home = "";

  Symbol* symbol = Symbol::find ("CMTHOME");
  if (symbol != 0)
    {
      Me.m_cmt_home = symbol->build_macro_value ();
      Symbol::expand (Me.m_cmt_home);
    }
  else if (CmtSystem::testenv ("CMTHOME"))
    {
      Me.m_cmt_home = CmtSystem::getenv ("CMTHOME");
    }

  if ((Me.m_cmt_home != "") && !CmtSystem::test_directory (Me.m_cmt_home))
    {
      Me.m_cmt_home = "";
    }

  configure_user_context (0);
}

//----------------------------------------------------------
void Cmt::configure_user_context (Use* use)
{
  Me.m_cmt_user_context = "";

  Symbol* symbol = Symbol::find ("CMTUSERCONTEXT");
  if (symbol != 0)
    {
      Me.m_cmt_user_context = symbol->build_macro_value ();
      Symbol::expand (Me.m_cmt_user_context);
    }
  else if (CmtSystem::testenv ("CMTUSERCONTEXT"))
    {
      Me.m_cmt_user_context = CmtSystem::getenv ("CMTUSERCONTEXT");
    }

  if ((Me.m_cmt_user_context != "") && !CmtSystem::test_directory (Me.m_cmt_user_context))
    {
      Me.m_cmt_user_context = "";
    }

  if (Me.m_debug) cout << "configure_user_context> user_context=" << Me.m_cmt_user_context << endl;

  configure_cmt_path (0);
}

//----------------------------------------------------------
void Cmt::configure_hosttype_tag ()
{
  cmt_string hosttype;

  CmtSystem::get_hosttype (hosttype);

  if (hosttype != "")
    {
      Tag* tag;

      tag = Tag::add (hosttype, PriorityUname, "HOSTTYPE", 0);
      tag->mark ("HOSTTYPE");
    }
}

//----------------------------------------------------------
void Cmt::configure_site_tag (Use* use)
{
  Symbol* symbol = Symbol::find ("CMTSITE");
  if (symbol != 0)
    {
      Me.m_cmt_site = symbol->build_macro_value ();
      Symbol::expand (Me.m_cmt_site);
    }
  else
    {
      Me.m_cmt_site = CmtSystem::get_cmt_site ();
    }

  if (Me.m_cmt_site != "")
    {
      cmt_string s = "CMTSITE";
      cmt_string t = s;

      if (use != 0)
        {
          //s += " in ";
	  t = use->get_package_name ();
        }

      Tag* tag;

      tag = Tag::add (Me.m_cmt_site, PrioritySite, s, use);
      tag->mark (t);
    }
}

//----------------------------------------------------------
void Cmt::restore_all_tags (Use* use)
{
  //cerr << "restore_all_tags" << endl;

  Cmt::configure_tags (use);

  /*
    Then get existing extra tags
  */

  if (CmtSystem::testenv ("CMTEXTRATAGS"))
    {
      cmt_string s = "CMTEXTRATAGS";
      cmt_string t = s;

      if (use != 0)
        {
          //s += " in ";
	  t = use->get_package_name ();
        }

      Tag* tag;
      CmtSystem::cmt_string_vector words;
      
      cmt_string tags = CmtSystem::getenv ("CMTEXTRATAGS");
      
      CmtSystem::split (tags, " \t,", words);

      Me.m_extra_tags = ",";
      
      for (int i = 0; i < words.size (); i++)
        {
          const cmt_string& a = words[i];

          Me.m_extra_tags += a;
          Me.m_extra_tags += ",";
          
          tag = Tag::add (a, PriorityUserTag, s, use);
          
          tag->mark (t);
        }
    }
}

//----------------------------------------------------------
void Cmt::configure_tags (Use* use)
{
  cmt_string config_tag;

  Log;

  log << "current_tag=" << Me.m_current_tag << log_endl;

  Symbol* symbol = Symbol::find ("CMTCONFIG");
  if (symbol != 0)
    {
      bool show_set_hidden = false;

      if (Me.m_action == action_show_set)
        {
          show_set_hidden = true;
          Me.m_action = action_none;
        }

      config_tag = symbol->build_macro_value ();
      Symbol::expand (config_tag);

      if (show_set_hidden)
        {
          show_set_hidden = false;
          Me.m_action = action_show_set;
        }
    }
  else if (CmtSystem::testenv ("CMTCONFIG"))
    {
      config_tag = CmtSystem::getenv ("CMTCONFIG");
    }
  else if (CmtSystem::testenv ("CMTBIN"))
    {
      config_tag = CmtSystem::getenv ("CMTBIN");
    }

  if (config_tag == "")
    {
      CmtSystem::get_uname (config_tag);
    }

  log << "current_tag=" << Me.m_current_tag << log_endl;

  cmt_string s = "CMTCONFIG";
  cmt_string t = s;

  if (use != 0)
    {
      //s += " in ";
      t = use->get_package_name ();
    }
  
  Tag* tag;

  tag = Tag::add (config_tag, PriorityConfig, s, use);
  tag->mark (t);

  //Me.m_current_tag = config_tag;
}

//----------------------------------------------------------
void Cmt::configure_uname_tag ()
{
  cmt_string uname;

  CmtSystem::get_uname (uname);

  if (uname != "")
    {
      Tag* tag;

      tag = Tag::add (uname, PriorityUname, "uname", 0);
      tag->mark ("uname");
    }
}

//----------------------------------------------------------
void Cmt::configure_devenv_tag ()
{
  cmt_string devenv_command;
  Symbol* devenv_command_macro = Symbol::find ("devenv_command");
  if (0 == devenv_command_macro) return;

  devenv_command = devenv_command_macro->resolve_macro_value ();
  if (devenv_command == "") return;
  devenv_command += " 2>&1";

  cmt_string output;
  if (0 != CmtSystem::execute (devenv_command, output)) return;
  cmt_string devenv;
  int pos;
  pos = output.find ("Microsoft");
  if (pos != cmt_string::npos) devenv = "vs";
  else return;

  //
  // Make the output as one single big line.
  //

  output.replace_all ("\n", " ");
  output.replace_all ("\r", " ");

  CmtSystem::cmt_string_vector words;
  CmtSystem::split (output, " \t", words);

  cmt_string version;
  bool need_version (false);
  for (int i = 0; i < words.size (); i++)
    {
      if (need_version && words[i] != "")
	{
	  version = words[i];
	  break;
	}
      if (words[i] == "Version")
	need_version = true;
    }

  if (version == "")
    {
      devenv += "00";
    }
  else
    {
      CmtSystem::cmt_string_vector nbrs;
      CmtSystem::split (version, ".", nbrs);
      if (1 == nbrs.size ())
	devenv += nbrs[0];
      else
	devenv += nbrs[0] + nbrs[1];
    }

  if (devenv != "")
    {
      Tag* tag;

      tag = Tag::add (devenv, PriorityUname, "devenv", 0);
      tag->mark ("devenv");
    }
}

//----------------------------------------------------------
void Cmt::configure_version_tag ()
{
  int v = 0;
  int r = 0;
  int p = 0;

  CmtSystem::is_version_directory (CMTVERSION, v, r, p);

  Tag* tag;

  static char temp[80];

  sprintf (temp, "CMTv%d", v);

  tag = Tag::add (temp, PriorityVersion, "CMTVERSION", 0);
  tag->mark ("CMTVERSION");

  sprintf (temp, "CMTr%d", r);

  tag = Tag::add (temp, PriorityVersion, "CMTVERSION", 0);
  tag->mark ("CMTVERSION");

  sprintf (temp, "CMTp%d", p);

  tag = Tag::add (temp, PriorityVersion, "CMTVERSION", 0);
  tag->mark ("CMTVERSION");

}

//----------------------------------------------------------
//void Cmt::configure_cmt_message ()
void Cmt::configure_cmt_message (const ArgParser& ap)
{
  cmt_string s;

  s = CmtSystem::getenv ("CMTMSGPREFIX");
  if (s != "")
    CmtMessage::set_prefix (s);

  s = CmtSystem::getenv ("CMTFATAL");
  if (s != "")
    {
      CmtMessage::set_level (Fatal);
    }

  s = CmtSystem::getenv ("CMTERROR");
  if (s != "")
    {
      CmtMessage::set_level (Error);
    }

  s = CmtSystem::getenv ("CMTWARNING");
  if (s != "")
    {
      CmtMessage::set_level (Warning);
    }

  s = CmtSystem::getenv ("CMTINFO");
  if (s != "")
    {
      CmtMessage::set_level (Info);
    }

  s = CmtSystem::getenv ("CMTVERBOSE");
  if (s != "")
    {
      CmtMessage::set_level (Verbose);
    }

  s = CmtSystem::getenv ("CMTDEBUG");
  if (s != "")
    {
      CmtMessage::set_level (Debug);
    }

  CmtSystem::cmt_string_vector flags;
  Cmt::get_cmt_flags (flags);
  for (int i = 0; i < flags.size (); i++)
    {
      const cmt_string& flag = flags[i];
      if (flag == "-disable_warnings")
	{
	  Me.m_disable_warnings = true;
	  if (CmtMessage::level () <= Warning)
	    CmtMessage::set_level (Error);
	}
      else if (flag == "-quiet")
	{
	  Me.m_quiet = true;
	  if (CmtMessage::level () <= Error)
	    CmtMessage::set_level (Fatal);
	}
      else if (flag == "-warnings")
	{
	  Me.m_warnings = true;
	  if (CmtMessage::level () != Warning)
	    CmtMessage::set_level (Warning);
	  //	  if (CmtMessage::level () > Warning)
	}
    }

  for (int i = 1; i < ap.argc; i++)
    {
      const cmt_string& arg = ap.argv[i];
      if (arg[0] != '-') break;
      if (arg == "-d" ||
	  arg == "-di" ||
	  arg == "-dis" ||
	  arg == "-disa" ||
	  arg == "-disab" ||
	  arg == "-disabl" ||
	  arg == "-disable" ||
	  arg == "-disable_" ||
	  arg == "-disable_w" ||
	  arg == "-disable_wa" ||
	  arg == "-disable_war" ||
	  arg == "-disable_warn" ||
	  arg == "-disable_warni" ||
	  arg == "-disable_warnin" ||
	  arg == "-disable_warning" ||
	  arg == "-disable_warnings")
	{
	  Me.m_disable_warnings = true;
	  if (CmtMessage::level () <= Warning)
	    {
	      CmtMessage::set_level (Error);
	      //	      if (!CmtSystem::putenv ("CMTERROR", "1"))
	      //		CmtMessage::error ("Cannot set `CMTERROR' in the environment");
	    }
	  if (!Cmt::add_cmt_flag ("-disable_warnings"))
	    CmtMessage::error ("Cannot add flag `-disable_warnings'");
	}
      else if (arg == "-q" ||
	       arg == "-qu" ||
	       arg == "-qui" ||
	       arg == "-quie" ||
	       arg == "-quiet")
	{
	  Me.m_quiet = true;
	  if (CmtMessage::level () <= Error)
	    {
	      CmtMessage::set_level (Fatal);
	      //	      if (!CmtSystem::putenv ("CMTFATAL", "1"))
	      //		CmtMessage::error ("Cannot set `CMTFATAL' in the environment");
	    }
	  if (!Cmt::add_cmt_flag ("-quiet"))
	    CmtMessage::error ("Cannot add flag `-quiet'");
	}
      else if (arg == "-warn" ||
	       arg == "-warni" ||
	       arg == "-warnin" ||
	       arg == "-warning" ||
	       arg == "-warnings")
	{
	  Me.m_warnings = true;
	  //	  if (CmtMessage::level () > Warning)
	  if (CmtMessage::level () != Warning)
	    {
	      CmtMessage::set_level (Warning);
	      //	      if (!CmtSystem::putenv ("CMTWARNING", "1"))
	      //		CmtMessage::error ("Cannot set `CMTWARNING' in the environment");
	    }
	  if (!Cmt::add_cmt_flag ("-warnings"))
	    CmtMessage::error ("Cannot add flag `-warnings'");
	}
    }
}

//----------------------------------------------------------
//
//   Actions
//
//----------------------------------------------------------

class AwkActor : public Awk
{
public:

  void filter (const cmt_string& line)
  {
    cout << line << endl;
  }
};

//----------------------------------------------------------
void Cmt::do_awk (const ArgParser& ap)
{
  if (ap.arguments.size () < 1)
    {
      CmtMessage::error ("cmt awk <file> <pattern>");
      //      cerr << "#CMT> cmt awk <file> <pattern>" << endl;
      return;
    }

  const cmt_string& file = ap.arguments[0];
  const cmt_string& pattern = ap.arguments[1];
  cmt_string text;

  text.read (file);

  static AwkActor a;

  cmt_regexp exp (pattern);

  a.run (text, exp);
}

//----------------------------------------------------------
void Cmt::do_broadcast (const ArgParser& ap)
{
  Use::UsePtrVector& Uses = Use::get_ordered_uses ();

  CmtSystem::cmt_string_vector uses;
  CmtSystem::cmt_string_vector packages;
  CmtSystem::cmt_string_vector versions;
  CmtSystem::cmt_string_vector path_selections;
  CmtSystem::cmt_string_vector selections;
  CmtSystem::cmt_string_vector exclusions;
  cmt_string begin;
  cmt_string command;
  bool is_cmt = false;
  int first = 0;
  int i;
  bool ignore_errors = false;
  bool all_packages = false;

  bool local = true;

  for (i = 0; i < ap.arguments.size (); i++)
    {
      const cmt_string& w = ap.arguments[i];

      //cerr << "broadcast: arg=[" << w << "]" << endl;

      if (command == "")
        {
          if (w.substr (0, 13) == "-all_packages")
            {
              local = false;
              all_packages = true;
            }
          else if (w.substr (0, 7) == "-depth=")
            {
              local = false;

              cmt_string depth_str;
              int depth_value = 0;
                          
              w.substr (7, depth_str);
              if ((sscanf (depth_str.c_str (), "%d", &depth_value) < 1) ||
                  (depth_value < 1))
                {
                  // Syntax error
                  //  We shall restrict to packages found within 
                  // the <depth_value> first elements of CMTPATH.
                  //  If CMTPATH is empty, nothing is selected.
                  // depth=1 is equivalent to local
                }

	      Project::fill_selection (depth_value, path_selections);
            }
          else if (w.substr (0, 9) == "-exclude=")
            {
              cmt_string exclusion;

              w.substr (9, exclusion);

              int size = exclusion.size ();
              
              if (size >= 2)
                {
                  if (((exclusion[0] == '"') && (exclusion[size - 1] == '"')) ||
                      ((exclusion[0] == '\'') && (exclusion[size - 1] == '\'')))
                    {
                      exclusion.erase (size - 1);
                      exclusion.erase (0, 1);
                    }

                  CmtSystem::split (exclusion, " \t", exclusions);
                }
            }
          else if (w.substr (0, 7) == "-global")
            {
              path_selections.clear ();

              local = false;
            }
          else if (w.substr (0, 6) == "-local")
            {
              local = true;
            }
          else if (w.substr (0, 8) == "-select=")
            {
              cmt_string selection;

              w.substr (8, selection);

	      //cerr << "Select=[" << selection << "]" << endl;

              int size = selection.size ();
              
              if (size >= 2)
                {
                  if (((selection[0] == '"') && (selection[size - 1] == '"')) ||
                      ((selection[0] == '\'') && (selection[size - 1] == '\'')))
                    {
                      selection.erase (size - 1);
                      selection.erase (0, 1);
                    }
                }

	      CmtSystem::split (selection, " \t", selections);

	      //cerr << "Selections.size () = " << selections.size () << endl;
            }
          else if (w.substr (0, 7) == "-begin=")
            {
              w.substr (7, begin);
            }
          else
            {
              command = w;
            }
        }
      else
        {
          command += " ";
          command += w;
        }

    }

  if (local)
    {
      Project::fill_selection (1, path_selections);
    }

  if (command[0] == '-')
    {
      ignore_errors = true;
      command.erase (0, 1);
    }

  //if (command.substr (0, 3) == "cmt") is_cmt = true;

  cmt_string curuse = CmtSystem::pwd ();
  if (all_packages)
    {
      PackageSelector selector (uses);
      PathScanner scanner;
      Project::scan_paths (scanner, selector);
    }
  else
    {
      for (i = Uses.size () - 1; i >= 0; i--)
        {
          Use* use = Uses[i];
                  
          if (use->discarded) continue;
          if (use->m_hidden) continue;

          if (!use->located ())
            {
	      CmtMessage::warning ("package " + use->get_package_name ()
				   + " " + use->version + " " + use->path
				   + " not found");
	      /*
              if (!Me.m_quiet)
                {
                  cerr << "#CMT> package " << use->get_package_name () <<
		    " " << use->version << " " << use->path <<
		    " not found" <<
		    endl;
                }
	      */
            }
          else
            {
              if (use->get_package_name () != "CMT")
                {
                  cmt_string& s = uses.add ();

                  use->get_full_path (s);

                  s += CmtSystem::file_separator ();
                  if (use->style == mgr_style) s += "mgr";
                  else s += "cmt";

                  cmt_string& v = versions.add ();
		  v = use->version;

                  cmt_string& p = packages.add ();
		  p = use->get_package_name ();
                }
            }
        }
          
      {
        cmt_string& s = uses.add ();
                  
        Use* use = &(Use::current ());

        if (use->get_package_name ().find ("cmt_standalone") != cmt_string::npos)
          {
            s = CmtSystem::pwd ();
          }
        else
          {
            use->get_full_path (s);

            s += CmtSystem::file_separator ();
                  
            if (use->style == mgr_style) s += "mgr";
            else s += "cmt";
          }

	curuse = s;

	cmt_string& v = versions.add ();
	v = use->version;

	cmt_string& p = packages.add ();
	p = use->get_package_name ();
      }
    }

  bool started = false;

  if (begin == "") started = true;

  set_standard_macros ();
  Cmt::reset_all_sets_done ();
  Symbol::all_set ();
  if (CmtSystem::testenv ("CMTBCAST"))
    CmtSystem::putenv ("CMTBCAST", "");

  for (i = 0; i < uses.size (); i++)
    {
      const cmt_string& s = uses[i];
      const cmt_string& v = versions[i];
      const cmt_string& p = packages[i];
      cmt_string cmtpath;

      bool ok = true;
      bool selected = true;
      bool excluded = false;

      /**
	 Ensure that the current package is not skipped
	 due to symlinks in the paths
       */
      //      if (path_selections.size () > 0)
      if (path_selections.size () > 0 && s != curuse)
        {
          selected = false;

          for (int j = 0; j < path_selections.size (); j++)
            {
              const cmt_string& sel = path_selections[j];
              
              if (s.find (sel) != cmt_string::npos) 
                {
		  cmtpath = sel;
                  selected = true;
                  break;
                }
            }

          ok = selected;
        }

      if (ok)
        {
          if (selections.size () > 0)
            {
              selected = false;
              
              for (int j = 0; j < selections.size (); j++)
                {
                  const cmt_string& sel = selections[j];
                  
                  if (s.find (sel) != cmt_string::npos) 
                    {
                      selected = true;
                      break;
                    }
                }
              
              ok = selected;
            }
        }

      if (ok && !started)
        {
          if (s.find (begin) != cmt_string::npos)
            {
              started = true;
              ok = true;
            }
          else
            {
              ok = false;
            }
        }


      if (ok)
        {
          excluded = false;

          for (int j = 0; j < exclusions.size (); j++)
            {
              const cmt_string& exc = exclusions[j];
              
              if (s.find (exc) != cmt_string::npos) 
                {
                  excluded = true;
                  break;
                }
            }

          if (excluded) ok = false;
        }

      if (!ok) 
        {
          continue;
        }



      if (!CmtSystem::cd (s))
        {
          if (s.find ("cmt_standalone") != cmt_string::npos)
            {
              CmtMessage::warning ("Currently not in a CMT package");
	      //              cerr << "#CMT> Currently not in a CMT package" << endl;
            }
          else
            {
	      char num[32]; sprintf (num, "%d/%d", i+1, uses.size ());
              CmtMessage::error ("Cannot move to the package in " + s
				 + " (" + num + ")");
	      /*
              cerr << "#CMT> Cannot move to the package in " << s << " (" << i+1 << "/" 
                   << uses.size () << ")"<< endl;
	      */
            }

          if (!ignore_errors) break;

          continue;
        }

      if (CmtLock::check () == CmtLock::locked_by_another_user)
        {
	  char num[32]; sprintf (num, "%d/%d", i+1, uses.size ());
	  CmtMessage::warning ("Ignore locked package in " + s
			       + " (" + num + ")");
	  /*
          cerr << "#CMT> Ignore locked package in " << s << " (" << i+1 << "/" 
               << uses.size () << ")" << endl;
	  */
          continue;
        }

      if (cmtpath == "")
        {
	  cmt_string sel = CmtSystem::pwd ();
	  cmtpath = Project::find_in_cmt_paths (sel);
        }

      cmt_string cmd = command;
      static const cmt_string version_template = "<version>";
      cmd.replace_all (version_template, v);

      static const cmt_string package_template = "<package>";
      cmd.replace_all (package_template, p);

      static const cmt_string cmtpath_template = "<package_cmtpath>";
      cmd.replace_all (cmtpath_template, cmtpath);

      static const cmt_string offset_template = "<package_offset>";

      static const cmt_string empty_string;
      static const cmt_string fs = CmtSystem::file_separator ();
      cmt_string offset = s;
      offset.replace (cmtpath, empty_string);
      if (offset[0] == CmtSystem::file_separator ())
	{
	  offset.replace (fs, empty_string);
	}
      CmtSystem::dirname (offset, offset);

      cmt_string n;
      CmtSystem::basename (offset, n);
      if (n == p)
	{
	  CmtSystem::dirname (offset, offset);
	}
      else
	{
	  CmtSystem::dirname (offset, offset);
	  CmtSystem::dirname (offset, offset);
	}

      cmd.replace_all (offset_template, offset);


  if (CmtMessage::active (Error))
    {
      cout << "#--------------------------------------------------------------" << endl;
      cout << "# Now trying [" << cmd << "] in " << s << " (" << i+1 << "/" << uses.size () 
           << ")" << endl;
      cout << "#--------------------------------------------------------------" << endl;
    }

      if (is_cmt)
        {
          //
          //  There is a bug in the recursive use of the parser. Macros are not set correctly.
          //  Thus the recursive optimization is now discarded.
          //
          if (parser (cmd) != 0)
            {
              CmtError::set (CmtError::execution_error, cmd);
              break;
            }
        }
      else
        {
          int status = CmtSystem::execute (cmd);

          //cerr << "do_broadcast> status=" << status << " ignore_errors=" << ignore_errors << endl;

          if ((status != 0) && !ignore_errors)
	    //if ((status != 0) && !ignore_errors)
            {
	      //              if (status != 2) CmtError::set (CmtError::execution_error, cmd);
              CmtError::set (CmtError::execution_error, cmd);
              break;
            }
        }
    }
}

//----------------------------------------------------------
void Cmt::do_build_constituent_makefile (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_constituent_makefile>");
      return;
    }
  set_standard_macros ();

  cmt_string out, name;
  for (int i = 0; i < ap.arguments.size (); i++)
    {
      const cmt_string& arg = ap.arguments[i];
      if (arg.substr (0, 5) == "-out=")
	arg.substr (5, out);
      else
	name = arg;
    }

  const Constituent* constituent = Constituent::find (name);
  if (constituent == 0)
    {
      CmtError::set (CmtError::constituent_not_found, name);
      return;
    }
  bool dependencies (false);
  Generator::build_constituent_makefile (*constituent, dependencies, out);
//   if (ap.arguments.size () > 0) 
//     {
//       set_standard_macros ();
//       Generator::build_constituent_makefile (ap.arguments);
//     }
}

//----------------------------------------------------------
void Cmt::do_build_constituent_config (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_constituent_config>");
      return;
    }
  set_standard_macros ();

  CmtSystem::cmt_string_vector files (2);
  cmt_string out, outdir, name;
  for (int i = 0; i < ap.arguments.size (); i++)
    {
      const cmt_string arg = ap.arguments[i];
      if (arg.substr (0, 5) == "-out=")
	{
	  arg.substr (5, out);
	  CmtSystem::dirname (out, outdir);
	}
      else
	{
	  name = arg;
	}
    }

  //  Generator::build_constituent_makefile (ap.arguments);

  const Constituent* constituent = Constituent::find (name);
  if (constituent == 0)
    {
      CmtError::set (CmtError::constituent_not_found, name);
      return;
    }
  if (!constituent->has_target_tag)
    {
      bool dependencies (false);
      Generator::build_constituent_makefile (*constituent, dependencies, out);
      return;
    }
  //  cerr << "constituent: " << name << endl;

  cmt_string tag;
  {
    Symbol* macro = Symbol::find ("tag");
    if (macro != 0)
      {
	tag = macro->build_macro_value ();
	Symbol::expand (tag);
	if (0 == tag.size ())
	  {
	    CmtError::set(CmtError::configuration_error, "tag empty");
	    return;
	  }
      }
    else
      {
	CmtError::set(CmtError::configuration_error, "tag undefined");
	return;
      }
  }

  //cmt_local_tagfile = $(bin)$(tag).make
  //cmt_final_setup = $(bin)setup.make
  //cmt_local_tagfile_${CONSTITUENT} = $(bin)$(${PACKAGE}_tag)_${CONSTITUENT}.make
  //cmt_final_setup_${CONSTITUENT} = $(bin)setup_${CONSTITUENT}.make
  files[0] = tag + "_" + name;
  files[1] = "setup_" + name;
  for (int i = 0; i < files.size (); i++)
    {
      if (Cmt::build_nmake ())
	files[i] += ".nmake";
      else
	files[i] += ".make";

      if (outdir != "")
	{
	  if (outdir [outdir.size () - 1] != CmtSystem::file_separator ())
	    outdir += CmtSystem::file_separator ();
	  files[i] = outdir + files[i];
	}
      //      cerr << "files[" << i << "]: " << files[i] << endl;
    }

  ofstream t (files[0]);
  if (!t)
    {
      CmtError::set (CmtError::file_access_error, files[0]);
      return;
    }
  t.exceptions (ios::failbit | ios::badbit);
  try
    {
      print_macros (Make, "", t);
      t.close (); // ios_base::failbit
    }
  catch (const ios::failure& e)
    {
      CmtSystem::close_ostream (NULL, files[0] + ": " + cmt_string (e.what ()));
    }

  bool gen_setup (true);
  ostringstream os;
  ofstream s;
  s.open (files[1], ios::in);
  if (s) // file already exists
    {
      //      cerr << files[1] << " already exists" << endl;
      do_show_setup (ap, os);
      ostringstream osn;
      osn << s.rdbuf ();
      if (os.str () == osn.str ())
	{
	  //	  cerr << files[1] << " up-to-date" << endl;
	  gen_setup = false;
	}
    }
  s.clear ();
  s.close ();
  s.clear ();
  if (gen_setup)
    {
      s.open (files[1]);
      if (!s)
	{
	  CmtError::set (CmtError::file_access_error, files[1]);
	  return;
	}
      s.exceptions (ios::failbit | ios::badbit);
      try
	{
	  if (os.str ().size () != 0)
	    {
	      //	      cerr << files[1] << " contents already generated" << endl;
	      s << os.str ();
	    }
	  else
	    {
	      do_show_setup (ap, s);
	    }
	  s.close (); // ios_base::failbit
	}
      catch (const ios::failure& e)
	{
	  CmtSystem::close_ostream (NULL, files[1] + ": " + cmt_string (e.what ()));
	}
    }

  int retval (0);

  bool dependencies (false);
  Generator::build_constituent_makefile (*constituent, dependencies, out);

  if (dependencies)
    retval = Generator::build_dependencies_infile (constituent, outdir/*, usecmt*/);
}

//----------------------------------------------------------
void Cmt::do_build_constituents_makefile (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_constituents_makefile>");
      return;
    }
  set_standard_macros ();

  cmt_string out;
  for (int i = 0; i < ap.arguments.size (); i++)
    {
      const cmt_string& arg = ap.arguments[i];
      if (arg.substr (0, 5) == "-out=")
	{
	  arg.substr (5, out);
	}
    }

  Generator::build_constituents_makefile (Me.m_current_package, out);
  //  Generator::build_constituents_makefile (Me.m_current_package, ap.arguments);
}

//----------------------------------------------------------
void Cmt::do_build_constituents_config (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_constituents_config>");
      return;
    }
  do_check_configuration (ap);
  if (CmtError::get_last_error_code () == CmtError::configuration_error)
    return;

  set_standard_macros ();

  CmtSystem::cmt_string_vector files (2);
  cmt_string out, outdir;
  bool usecmt (true);
  for (int i = 0; i < ap.arguments.size (); i++)
    {
      const cmt_string& arg = ap.arguments[i];
      if (arg.substr (0, 5) == "-out=")
	{
	  arg.substr (5, out);
	  CmtSystem::dirname (out, outdir);
	}
      else if (arg == "-with_cmt")
	usecmt = true;
      else if (arg == "-without_cmt")
	usecmt = false;
    }
  //  cerr << "outdir: " << outdir << endl;

  cmt_string tag;
  {
    Symbol* macro = Symbol::find ("tag");
    if (macro != 0)
      {
	tag = macro->build_macro_value ();
	Symbol::expand (tag);
	if (0 == tag.size ())
	  {
	    CmtError::set(CmtError::configuration_error, "tag empty");
	    return;
	  }
      }
    else
      {
	CmtError::set(CmtError::configuration_error, "tag undefined");
	return;
      }
  }

  //cmt_local_tagfile = $(bin)$(tag).make
  //cmt_final_setup = $(bin)setup.make
  files[0] = tag;
  files[1] = "setup";
  for (int i = 0; i < files.size (); i++)
    {
      if (Cmt::build_nmake ())
	files[i] += ".nmake";
      else
	files[i] += ".make";

      if (outdir != "")
	{
	  if (outdir [outdir.size () - 1] != CmtSystem::file_separator ())
	    outdir += CmtSystem::file_separator ();
	  files[i] = outdir + files[i];
	}
      //      cerr << "files[" << i << "]: " << files[i] << endl;
    }

  //  files[0] = "/dev/full";
  ofstream t (files[0]);
  if (!t)
    {
      CmtError::set (CmtError::file_access_error, files[0]);
      return;
    }
  t.exceptions (ios::failbit | ios::badbit);
  try
    {
      print_macros (Make, "", t);
      t.close (); // ios_base::failbit
    }
  catch (const ios::failure& e)
    {
      CmtSystem::close_ostream (NULL, files[0] + ": " + cmt_string (e.what ()));
    }

  bool gen_setup (true);
  ostringstream os;
  ofstream s;
  s.open (files[1], ios::in);
  if (s) // file already exists
    {
      //      cerr << files[1] << " already exists" << endl;
      do_show_setup (ap, os);
      ostringstream osn;
      osn << s.rdbuf ();
      if (os.str () == osn.str ())
	{
	  //	  cerr << files[1] << " up-to-date" << endl;
	  gen_setup = false;
	}
    }
  s.clear ();
  s.close ();
  s.clear ();
  if (gen_setup)
    {
      s.open (files[1]);
      if (!s)
	{
	  CmtError::set (CmtError::file_access_error, files[1]);
	  return;
	}
      s.exceptions (ios::failbit | ios::badbit);
      try
	{
	  if (os.str ().size () != 0)
	    {
	      //	      cerr << files[1] << " contents already generated" << endl;
	      s << os.str ();
	    }
	  else
	    {
	      do_show_setup (ap, s);
	    }
	  s.close (); // ios_base::failbit
	}
      catch (const ios::failure& e)
	{
	  CmtSystem::close_ostream (NULL, files[1] + ": " + cmt_string (e.what ()));
	}
    }

  int retval (0);

  Generator::build_constituents_makefile (Me.m_current_package, out);
  //  Generator::build_constituents_makefile (Me.m_current_package, ap.arguments);

  retval = Generator::build_library_links_infile (outdir);
  if (0 != retval) return;

  const Constituent::ConstituentVector& constituents =
    Constituent::constituents ();
  bool deps (false);
  for (int n = 0; n < constituents.size (); n++)
    {
      const Constituent& constituent = constituents[n];
      if (constituent.has_target_tag) continue;

      retval = Generator::build_constituent_infile (constituent, outdir, usecmt);
      if (0 != retval) return;

      if (!deps)
	if (constituent.type == Application ||
	    constituent.type == Library ||
	    (constituent.type == Document &&
	     FragmentHandle (constituent.generator).need_dependencies ()))
	  {
	    deps = true;
	  }
    }

  if (deps)
    retval = Generator::build_dependencies_infile (0, outdir, usecmt);
}

//----------------------------------------------------------
void Cmt::do_build_broadcast_config (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_broadcast_config>");
      return;
    }
  set_standard_macros ();

  cmt_string out, outdir, name ("broadcast");
  for (int i = 0; i < ap.arguments.size (); i++)
    {
      const cmt_string& arg = ap.arguments[i];
      if (arg.substr (0, 5) == "-out=")
	{
	  arg.substr (5, out);
	  CmtSystem::dirname (out, outdir);
	  CmtSystem::name (out, name);
	}
    }

  cmt_string tag;
  {
    Symbol* macro = Symbol::find ("tag");
    if (macro != 0)
      {
	tag = macro->build_macro_value ();
	Symbol::expand (tag);
	if (0 == tag.size ())
	  {
	    CmtError::set(CmtError::configuration_error, "tag empty");
	    return;
	  }
      }
    else
      {
	CmtError::set(CmtError::configuration_error, "tag undefined");
	return;
      }
  }
  cmt_string file (tag + "_" + name);
  //  cmt_string file (tag + "_uses");
  if (Cmt::build_nmake ())
    file += ".nmake";
  else
    file += ".make";
  if (outdir != "")
    {
      if (outdir [outdir.size () - 1] != CmtSystem::file_separator ())
	outdir += CmtSystem::file_separator ();
      file = outdir + file;
    }

  ofstream t (file);
  if (!t)
    {
      CmtError::set (CmtError::file_access_error, file);
      return;
    }
  t.exceptions (ios::failbit | ios::badbit);
  try
    {
//       Symbol* symbol = Symbol::find ("use_requirements");
//       if (symbol != 0)
// 	symbol->show_macro (Make, t);
//      const cmt_string pattern = "^use_requirements$|.*_root$|.*_cmtpath$|.*_offset$";
//      const cmt_string pattern = "^use_requirements$|.*_root$";
      const cmt_string pattern = "^use_requirements$|.*_root$|.*_offset$|.*VERSION$";
      print_macros (Make, pattern, t);
      t.close (); // ios_base::failbit
    }
  catch (const ios::failure& e)
    {
      CmtSystem::close_ostream (NULL, file + ": " + cmt_string (e.what ()));
    }

  Generator::build_packages_makefile (Me.m_current_package, out);
  //  Generator::build_uses_makefile (Me.m_current_package, out);
}

//----------------------------------------------------------
void Cmt::do_build_dependencies (const ArgParser& ap,
                                 int argc,
                                 char* argv[])
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_dependencies>");
      return;
    }
  if (ap.arguments.size () > 0)
    {
      set_standard_macros ();

      Generator::build_dependencies (ap.arguments);
    }
}

//----------------------------------------------------------
void Cmt::do_build_library_links (const ArgParser& ap)
{
  cmt_string cmtinstallarea = "";
  cmt_string tag = "";
  cmt_string shlibsuffix;
  cmt_string symlinkcmd;

  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_library_links>");
      return;
    }

  set_standard_macros ();

  Use::UsePtrVector& Uses = Use::get_ordered_uses ();
  Use& current_use = Use::current ();
  int i;

  {
    Symbol* macro = Symbol::find ("shlibsuffix");
    if (macro == 0)
      {
	if (strlen (ap.extra_file.c_str ()) == 0)
	  {
	    CmtError::set(CmtError::configuration_error, "shlibsuffix undefined");
	  }
	else
	  { // we are most likely reading empty library_links.in without CMT
	    if (CmtMessage::active (Verbose))
	      CmtMessage::warning
		(CmtError::get_error_name (CmtError::configuration_error)
		 + ": shlibsuffix undefined");
	  }
	return;
      }
    shlibsuffix = macro->build_macro_value ();
    Symbol::expand (shlibsuffix);
  }

  {
    Symbol* macro = Symbol::find ("library_install_command");
    if (macro != 0)
      {
	symlinkcmd = macro->build_macro_value ();
	Symbol::expand (symlinkcmd);
      }
  }

  if (current_use.get_strategy ("InstallArea"))
    {
      const CmtInstallAreaMgr& ia_mgr = CmtInstallAreaMgr::instance ();
      
      cmt_string s1 = ia_mgr.get_installarea ();

      {
        Symbol* symbol = Symbol::find ("CMTINSTALLAREA");
        if (symbol != 0)
          {
            s1 = symbol->build_macro_value ();
	    Symbol::expand (s1);
          }
      }

      cmtinstallarea = s1;
                  
      cmt_string s2;

      {
        Symbol* macro = Symbol::find ("tag");
        if (macro != 0)
          {
            s2 = macro->build_macro_value ();
	    Symbol::expand (s2);
          }
      }

      tag = s2;

      cmt_string s = s1;
      s += CmtSystem::file_separator ();
      s += s2;
      s += CmtSystem::file_separator ();
      s += "lib";

      CmtSystem::mkdir (s);
    }

  current_use.build_library_links (cmtinstallarea, tag, shlibsuffix, symlinkcmd);

  for (i = 0; i < Uses.size (); i++)
    {
      Use* use = Uses[i];

      if (use == 0) continue;
      if (use->discarded) continue;
      if (use->m_hidden) continue;

      if (use->get_package_name () == "CMT") continue;
      if (use->get_package_name () == current_use.get_package_name ()) continue;

      use->build_library_links (cmtinstallarea, tag, shlibsuffix, symlinkcmd);
    }
}

//----------------------------------------------------------
void Cmt::do_build_make_setup (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_make_setup>");
      return;
    }
  set_standard_macros ();
  Generator::build_make_setup (Me.m_current_package);
}

//----------------------------------------------------------
void Cmt::do_build_msdev (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_msdev>");
      return;
    }

  if (true)
    {
      set_standard_macros ();
      if (ap.arguments.size () > 0) build_msdev_file (ap.arguments[0]);
      else build_msdev_file ("");
    }
}

void Cmt::do_build_CMT_pacman (const ArgParser& ap)
{
  cmt_string pacman_file;

  pacman_file = Me.m_cmt_root;
  pacman_file += CmtSystem::file_separator ();
  pacman_file += "mgr";
  pacman_file += CmtSystem::file_separator ();
  pacman_file += "CMT.pacman";

  cmt_string pacman;
  cmt_string pattern = "<version>";
  cmt_string replacement = CMTVERSION;

  pacman.read (pacman_file);

  pacman.replace_all (pattern, replacement);

  cout << pacman << endl;
}

// Visual Studio.net Support                                                 
//----------------------------------------------------------                 
void Cmt::do_build_vsnet (const ArgParser& ap)     
{                                                                            
  if (CmtLock::check () == CmtLock::locked_by_another_user)                  
    {                                                                        
      CmtError::set (CmtError::conflicting_lock, "build_vsnet>");            
      return;                                                                
    }                                                                        
                                                                             
  if (true)                                                                  
    {                                                                        
      set_standard_macros ();                                                
      if (ap.arguments.size () > 0) build_vsnet_file (ap.arguments[0]);            
      else build_vsnet_file ("");                                            
    }                                                                        
}                                                                            

//----------------------------------------------------------
void Cmt::do_build_os9_makefile (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_os9_makefile>");
      return;
    }

  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();
      build_OS9_makefile (ap.arguments[0]);
    }
}

//----------------------------------------------------------
void Cmt::do_build_prototype (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_prototype>");
      return;
    }

  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();
      Generator::build_prototype (ap.arguments[0]);
    }
}

//----------------------------------------------------------
void Cmt::do_build_readme (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_readme>");
      return;
    }

  set_standard_macros ();
  Generator::build_readme (ap.arguments);
}

//----------------------------------------------------------
void Cmt::do_build_tag_makefile (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_tag_makefile>");
      return;
    }

  print_macros (Make);
}

//----------------------------------------------------------
void Cmt::do_build_temporary_name (const ArgParser& ap)
{
  cmt_string name = CmtSystem::get_temporary_name ();
  cout << name << endl;
}

//----------------------------------------------------------
void Cmt::do_build_triggers (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_tag_makefile>");
      return;
    }

  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();
      TriggerGenerator::run (ap.arguments[0]);
    }
}

//----------------------------------------------------------
void Cmt::do_build_windefs (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "build_windefs>");
      return;
    }

  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();
      //      Generator::build_windefs (ap.arguments[0]);
      Generator::build_windefs (ap.arguments);
    }
}

//----------------------------------------------------------
void Cmt::do_check_configuration (const ArgParser& ap)
{
  cmt_string env;
  Tag* tag;

  set_standard_macros ();

  const Use& use = Use::current ();
  if (use.located ())
    {
      if (action_setup != get_action () &&
	  none_style != use.style &&
	  0 == Project::get_current ())
	  //	  0 == Project::find_in_cmt_paths (use.real_path).size ())
	{
	  bool use_cmtpath_pattern (false);
	  static CmtPathPattern::CmtPathPatternVector& CmtPathPatterns = CmtPathPattern::patterns ();
	  for (int i = 0; i < CmtPathPatterns.size (); i++)
	    {
	      CmtPathPattern& p = CmtPathPatterns[i];
	      if (p.use->get_package ()->is_cmt () || p.is_constant ()) continue;
	      use_cmtpath_pattern = true;
	      break;
	    }
	  if (use_cmtpath_pattern)
	    // non-constant cmtpath_pattern found that
	    // cannot be applied for package outside CMTPATH
	    {
	      if (0 == CmtSystem::getenv ("CMTPEDANTIC").size () &&
		  0 == CmtSystem::getenv ("PEDANTIC").size ())
		CmtMessage::warning
		  (CmtError::get_error_name (CmtError::configuration_error)
		   + ": Package outside CMTPATH: " + use.get_info ());
	      else
		CmtError::set(CmtError::configuration_error,
			      "Package outside CMTPATH: " + use.get_info ());
	    }
	}
    }
  else
    {
      CmtMessage::verbose
	(CmtError::get_error_name (CmtError::configuration_error)
	 + ": Current use not located: " + use.get_info ());
    }

  static CmtSystem::cmt_string_vector tags;

  if (action_build_constituents_config != get_action ())
    CmtSystem::split (Me.m_extra_tags, " \t,", tags);

  for (int i = 0; i < tags.size (); i++)
    {
      const cmt_string& t = tags[i];

      tag = Tag::find (t);
      if (tag == 0) continue;

      if (!Tag::check_tag_used (tag) && !Symbol::check_tag_used (tag)) 
	{
	  CmtMessage::warning ("The tag " + t + " is not used in any tag expression. Please check spelling");
	  //	  cerr << "#CMT> The tag " << t << " is not used in any tag expression. Please check spelling" << endl;
	}
    }

  Symbol::check_all_paths ();

  env = CmtSystem::getenv ("CMTSITE");
  if (env == "") 
    {
      return;
    }

  tag = Tag::find (env);
  if (tag == 0) 
    {
      return;
    }

  if (!Tag::check_tag_used (tag) && !Symbol::check_tag_used (tag) && Cmt::get_warnings ()) 
    {
      CmtMessage::warning ("The CMTSITE value " + env + " is not used in any tag expression. Please check spelling");
      //      cerr << "#CMT> The CMTSITE value " << env << " is not used in any tag expression. Please check spelling" << endl;
    }

}

//----------------------------------------------------------
void Cmt::do_check_files (const ArgParser& ap)
{
  if (ap.arguments.size () >= 2) 
    {
      cmt_string first_file = ap.arguments[0];
      cmt_string second_file = ap.arguments[1];
          
      if (first_file == "") return;
      if (second_file == "") return;
          
      CmtSystem::compare_and_update_files (first_file, second_file);
    }
}

//----------------------------------------------------------
void Cmt::do_check_version (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      cmt_string name = ap.arguments[0];
          
      if (name == "") return;
      int v = 0;
      int r = 0;
      int p = 0;
          
      bool ok = CmtSystem::is_version_directory (name, v, r, p);
          
      if (ok)
        {
          cout << "# " << name << " is version " << v << " release " << r << " patch " << p << endl;
        }
      else
        {
          cout << "# " << name << " is not a version tag" << endl;
        }
    }
}

//----------------------------------------------------------
void Cmt::do_checkout (const ArgParser& ap)
{
  Vcs::checkout (ap.arguments);
  //  Cvs::checkout (ap.arguments);
}

//----------------------------------------------------------
void Cmt::do_cleanup (const ArgParser& ap)
{
  print_clean (ap.mode);
}

//----------------------------------------------------------
void Cmt::do_config (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "config>");
      return;
    }

  //Use::UsePtrVector& Uses = Use::get_ordered_uses ();

  Use& current_use = Use::current ();

  if (Me.m_debug)
    {
      cout << "Cmt::do_config> " << endl;
      cout << "pwd " << CmtSystem::pwd () << endl;
      cout << "current_dir " << Me.m_current_dir << endl;
      cout << "default_path " << Me.m_default_path << endl;
      cout << "cmt config " <<
	Me.m_current_package << " " <<
	Me.m_current_version << " " <<
	Me.m_current_path << endl;
    }

  if (Me.m_current_package == "CMT") return;
  if (Me.m_current_package == "methods") return;

  cmt_string file_name;
  if (strlen (ap.extra_file.c_str ()) == 0)
    file_name = "requirements";
  else
    file_name = ap.extra_file;
  cmt_string cmtflags (get_cmt_flags (file_name));

  if (strlen (ap.extra_file.c_str ()) != 0)
    cmtflags += " -f=" + file_name;
  cmt_string flags (get_cmt_flags ());
  if (flags.size () != 0)
    cmtflags += " " + flags;

  cmt_string branch;

  CmtSystem::basename (Me.m_current_dir, branch);

  if ((branch != "mgr") && (branch != "cmt"))
    {

      //
      // Here we are in a standalone package (ie completely unstructured)
      //

      if (CmtSystem::test_file ("requirements"))
        {
	  if (CmtMessage::active (Error))
	    {
          cout << "------------------------------------------" << endl;
          cout << "Configuring environment for standalone package." << endl;
          cout << "CMT version " << Me.m_cmt_version << "." << endl;
          cout << "System is " << Me.m_cmt_config << endl;
          cout << "------------------------------------------" << endl;
	    }

	  install_scripts (SetupScript, cmtflags);
	  install_scripts (CleanupScript, cmtflags);
          //install_setup_scripts ();
          //install_cleanup_scripts ();

          Generator::build_default_makefile ();
        }
      else
        {
          cout << "==============================================" << endl;
          cout << "cmt config must be operated either upon "
            "an existing package" << endl;
          cout << " (ie. when a requirements file already exists)" << endl;
          cout << "   > cd ..." << endl;
          cout << "   > cmt config" << endl;
          cout << "or to create a new package" << endl;
          cout << "   > cmt config <package> <version> [<path>]" << endl;
          cout << "==============================================" << endl;
        }

      return;
    }

  //  configure_current_package ();

  //  Generator::build_default_makefile ();

  CmtSystem::cmt_string_vector makes;
  cmt_regexp expression ("[.](n?make(sav|cmtsave)?|in)$");
  //  cmt_regexp expression ("[.]n?make(sav)?$");

  CmtSystem::scan_dir (".", expression, makes);
  
  if (makes.size () > 0)
    {
      if (CmtMessage::active (Info))
	cout << "Removing all previous make fragments from " << branch << endl;

      for (int i = 0; i < makes.size (); i++)
        {
          const cmt_string& s = makes[i];
          CmtSystem::cmt_string_vector words;
          CmtSystem::split (s, '.', words);
          if (words.size()>=2)
	    if (CmtSystem::get_makefile_suffix () == "nmake" &&
		(words[1] == "nmake"|| words[1] == "nmakesav" || words[1] == "nmakecmtsave"))
	      CmtSystem::remove_file (s);
	    else if (CmtSystem::get_makefile_suffix () == "make" &&
		     (words[1] == "make" || words[1] == "makesav" || words[1] == "makecmtsave"))
	      CmtSystem::remove_file (s);
        }
    }

  cmt_string bin ("..");
  bin += CmtSystem::file_separator ();
  bin += Me.m_cmt_config;
  //  CmtSystem::cd ("..");

  CmtSystem::scan_dir (bin, expression, makes); 
  //  CmtSystem::scan_dir (Me.m_cmt_config, expression, makes); 
    
  if (makes.size () > 0) 
    {
      if (CmtMessage::active (Info))
	{
	  cout << "Removing all previous make fragments from "
	       << Me.m_cmt_config << endl; 
	}

      for (int i = 0; i < makes.size (); i++) 
        { 
          const cmt_string& s = makes[i];
          CmtSystem::cmt_string_vector words;
          CmtSystem::split (s, '.', words);
          if (words.size()>=2)
	    if (CmtSystem::get_makefile_suffix () == "nmake" &&
		(words[1] == "nmake"|| words[1] == "nmakesav" || words[1] == "nmakecmtsave"))
	      CmtSystem::remove_file (s);
	    else if (CmtSystem::get_makefile_suffix () == "make" &&
		     (words[1] == "make" || words[1] == "makesav" || words[1] == "makecmtsave"))
	      CmtSystem::remove_file (s);
	    else if (words.size() == 2 && words[1] == "in")
	      CmtSystem::remove_file (s);
        }
    }

  //  CmtSystem::cd (branch); 

  /*
  Use& use = Use::current ();

  use.set (Me.m_current_package,
           Me.m_current_version,
           Me.m_current_path,
           "",
           "");

  use.change_path (Me.m_current_path);
  use.style     = Me.m_current_style;
  use.structuring_style = Me.m_current_structuring_style;

  Me.m_quiet = true;

  if (!reach_current_package ())
    {
      CmtMessage::error ("Cannot read the requirements file");
      //      cout << "Cannot read the requirements file" << endl;
      return;
    }
  */
  Me.m_quiet = true;
  install_scripts (SetupScript, cmtflags);
  install_scripts (CleanupScript, cmtflags);
  //install_setup_scripts ();
  //install_cleanup_scripts ();
  install_native_version_file ();

  Generator::build_default_makefile ();

  CmtSystem::cd ("..");

  Branch::BranchVector& branches = Branch::branches ();

  int i;

  for (i = 0; i < branches.size (); i++)
    {
      const Branch& branch = branches[i];
      const cmt_string& branch_name = branch.name ();

      if (!CmtSystem::test_directory (branch_name))
        {
          if (!CmtSystem::mkdir (branch_name))
            {
              CmtMessage::error ("Cannot create the " + branch_name + " branch");
	      //              cout << "Cannot create the " << branch_name <<" branch" << endl;
            }
          else
            {
	      if (CmtMessage::active (Info))
		cout << "Installing the " << branch_name << " directory" << endl;
            }
        }
      else
        {
	  if (CmtMessage::active (Info))
	    cout << branch_name << " directory already installed" << endl;
        }
    }
}


//----------------------------------------------------------
void Cmt::do_relocate (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "relocate>");
      return;
    }

  Use& current_use = Use::current ();

  if (Me.m_debug)
    {
      cout << "Cmt::do_relocate> " << endl;
      cout << "pwd "          << CmtSystem::pwd () << endl;
      cout << "current_dir "  << Me.m_current_dir << endl;
      cout << "default_path " << Me.m_default_path << endl;
      cout << "cmt config "   <<
	Me.m_current_package << " " <<
	Me.m_current_version << " " <<
	Me.m_current_path << endl;
    }

  if (Me.m_current_package == "CMT")     return;
  if (Me.m_current_package == "methods") return;

  cmt_string file_name;
  if (strlen (ap.extra_file.c_str ()) == 0)
    file_name = "requirements";
  else
    file_name = ap.extra_file;
  cmt_string cmtflags (get_cmt_flags (file_name));

  if (strlen (ap.extra_file.c_str ()) != 0)
    cmtflags += " -f=" + file_name;
  cmt_string flags (get_cmt_flags ());
  if (flags.size () != 0)
    cmtflags += " " + flags;

  cmt_string branch;

  CmtSystem::basename (Me.m_current_dir, branch);

  if ((branch != "mgr") && (branch != "cmt"))
    {

      //
      // Here we are in a standalone package (ie completely unstructured)
      //

      if (CmtSystem::test_file ("requirements"))
        {
	  if (CmtMessage::active (Error))
	    {
          cout << "------------------------------------------" << endl;
          cout << "Configuring environment for standalone package." << endl;
          cout << "CMT version " << Me.m_cmt_version << "." << endl;
          cout << "System is "   << Me.m_cmt_config << endl;
          cout << "------------------------------------------" << endl;
	    }
	  install_scripts (SetupScript, cmtflags);
	  install_scripts (CleanupScript, cmtflags);
          //install_setup_scripts ();
          //install_cleanup_scripts ();

          Generator::build_default_makefile ();
        }
      else
        {
          cout << "==============================================" << endl;
          cout << "cmt relocate must be operated either upon "
            "an existing package" << endl;
          cout << " (ie. when a requirements file already exists)" << endl;
          cout << "   > cd ..." << endl;
          cout << "   > cmt relocate" << endl;
          cout << "or to create a new package" << endl;
          cout << "   > cmt relocate <package> <version> [<path>]" << endl;
          cout << "==============================================" << endl;
        }

      return;
    }

  //  configure_current_package ();

  //  Generator::build_default_makefile ();
  
  /*
  CmtSystem::cd ("..");    
  CmtSystem::cd (branch); 

  Use& use = Use::current ();

  use.set (Me.m_current_package,
           Me.m_current_version,
           Me.m_current_path,
           "",
           "");

  use.change_path (Me.m_current_path);
  use.style     = Me.m_current_style;
  use.structuring_style = Me.m_current_structuring_style;

  Me.m_quiet = true;
    
  if (!reach_current_package ())
    {
      CmtMessage::error ("Cannot read the requirements file");
      //      cout << "Cannot read the requirements file" << endl;
      return;
    }
  */
  Me.m_quiet = true;
  install_scripts (SetupScript, cmtflags);
  install_scripts (CleanupScript, cmtflags);
  //install_setup_scripts ();
  //install_cleanup_scripts ();

  Generator::build_default_makefile ();

  CmtSystem::cd ("..");

  Branch::BranchVector& branches = Branch::branches ();

  int i;

  for (i = 0; i < branches.size (); i++)
    {
      const Branch& branch = branches[i];
      const cmt_string& branch_name = branch.name ();

      if (!CmtSystem::test_directory (branch_name))
        {
          if (!CmtSystem::mkdir (branch_name))
            {
              CmtMessage::error ("Cannot create the " + branch_name + " branch");
	      //              cout << "Cannot create the " << branch_name <<" branch" << endl;
            }
          else
            {
	      if (CmtMessage::active (Info))
		cout << "Installing the " << branch_name << " directory" << endl;
            }
        }
      else
        {
	  if (CmtMessage::active (Info))
	    cout << branch_name << " directory already installed" << endl;
        }
    }
}

//----------------------------------------------------------
void Cmt::do_create (const ArgParser& ap)
{
  if (ap.arguments.size () < 2) return;

  const cmt_string& package = ap.arguments[0];
  const cmt_string& version = ap.arguments[1];
  cmt_string offset;
  if (ap.arguments.size () >= 3) offset = ap.arguments[2];

  if (Me.m_debug)
    {
      cout << "do_create>Me.m_current_package=" << Me.m_current_package << endl;
      cout << "do_create>package=" << package << endl;
    }

  //if (Me.m_current_package == "CMT") return;
  //if (Me.m_current_package == "methods") return;

  cmt_string the_path;

  the_path = CmtSystem::pwd ();
  if (0 == the_path.size ())
    {
      CmtError::set (CmtError::system_error, "pwd empty");
      return;
    }

  if (offset != "")
    {
      if (!CmtSystem::absolute_path (offset))
        {
          // offset is really a relative offset
          the_path += CmtSystem::file_separator ();
          the_path += offset;
        }
      else // absolute path
        {
          the_path = offset;
        }
    }

  CmtSystem::compress_path (the_path);

  // Now 'the_path' contains the complete path where the package will be created

  if (CmtMessage::active (Error))
    {
  cout << "------------------------------------------" << endl;
  cout << "Configuring environment for package " << package <<
    " version " << version << "." << endl;
  cout << "CMT version " << Me.m_cmt_version << "." << endl;
  cout << "Root set to " << the_path << "." << endl;
  cout << "System is " << Me.m_cmt_config << endl;
  cout << "------------------------------------------" << endl;
    }

  if (!CmtSystem::test_directory (the_path))
    {
      if (!CmtSystem::mkdir (the_path))
        {
	  CmtError::set (CmtError::system_error,
			 "Cannot create path directory " + the_path);
          //CmtMessage::error ("Cannot create path directory " + the_path);
          return;
        }
      else
        {
	  if (CmtMessage::active (Info))
	    cout << "Installing path directory " << the_path << endl;
        }
    }

  if (!CmtSystem::cd (the_path))
    {
      CmtError::set (CmtError::system_error,
		     "Cannot cd to path directory " + the_path);
      return;
    }

  if (!CmtSystem::test_directory (package))
    {
      if (!CmtSystem::mkdir (package))
        {
	  CmtError::set (CmtError::system_error,
			 "Cannot create package directory " + package);
	  //          CmtMessage::error ("Cannot create the package directory");
          return;
        }
      else
        {
	  if (CmtMessage::active (Info))
	    cout << "Installing package directory" << endl;
        }
    }
  else
    {
      if (CmtMessage::active (Info))
	cout << "Package directory already installed" << endl;
    }

  if (!CmtSystem::cd (package))
    {
      CmtError::set (CmtError::system_error,
		     "Cannot cd to package directory " + package);
      return;
    }
  //  CmtSystem::cd (package);

  Use& current_use = Use::current ();

  bool with_version_dir = current_use.get_strategy ("VersionDirectory");

  CmtStructuringStyle style = get_current_structuring_style ();

  if (style != default_structuring_style)
    {
      if (with_version_dir)
	{
	  if (style == without_version_directory)
	    {
	      with_version_dir = false;
	    }
	}
      else
	{
	  if (style == with_version_directory)
	    {
	      with_version_dir = true;
	    }
	}
    }

  if (with_version_dir)
    {
      if (!CmtSystem::test_directory (version))
        {
          if (!CmtSystem::mkdir (version))
            {
              //CmtMessage::error ("Cannot create the version directory");
	      CmtError::set (CmtError::system_error,
			     "Cannot create version directory " + version);
              return;
            }
          else
            {
	      if (CmtMessage::active (Info))
		cout << "Installing version directory" << endl;
            }
        }
      else
        {
	  if (CmtMessage::active (Info))
	    cout << "Version directory already installed" << endl;
        }

      if (!CmtSystem::cd (version))
	{
	  CmtError::set (CmtError::system_error,
			 "Cannot cd to version directory " + version);
	  return;
	}
      //      CmtSystem::cd (version);
    }
  else
    {
      if (CmtMessage::active (Info))
	cout << "Version directory will not be created due to structuring style" << endl;
    }

  if (!CmtSystem::test_directory ("cmt"))
    {
      if (!CmtSystem::test_directory ("mgr"))
        {
          if (!CmtSystem::mkdir ("cmt"))
            {
	      CmtError::set (CmtError::system_error,
			     "Cannot create cmt directory");
	      //CmtMessage::error ("Cannot create the cmt directory");
              return;
            }
          else
            {
	      Me.m_current_style = cmt_style;
              if (with_version_dir)
                {
		  Me.m_current_structuring_style = with_version_directory;
                }
              else
                {
		  Me.m_current_structuring_style = without_version_directory;
		  //                  Me.m_current_style = no_version_style;
                }

	      if (CmtMessage::active (Info))
		cout << "Installing cmt directory" << endl;
            }
        }
      else
        {
	  Me.m_current_style = mgr_style;
          if (with_version_dir)
            {
	      Me.m_current_structuring_style = with_version_directory;
	      //              Me.m_current_style = mgr_style;
            }
          else
            {
	      Me.m_current_structuring_style = without_version_directory;
	      //              Me.m_current_style = no_version_style;
            }
          
	  if (CmtMessage::active (Info))
	    cout << "Mgr directory already installed" << endl;
        }
    }
  else
    {
      Me.m_current_style = cmt_style;
      if (with_version_dir)
        {
	  Me.m_current_structuring_style = with_version_directory;
	  //          Me.m_current_style = cmt_style;
        }
      else
        {
	  Me.m_current_structuring_style = without_version_directory;
	  //          Me.m_current_style = no_version_style;
        }

      if (CmtMessage::active (Info))
	cout << "Cmt directory already installed" << endl;
    }

  if (!CmtSystem::test_directory ("src"))
    {
      if (!CmtSystem::mkdir ("src"))
        {
	  CmtError::set (CmtError::system_error,
			 "Cannot create src directory");
          //CmtMessage::error ("Cannot create the src directory");
          return;
        }
      else
        {
	  if (CmtMessage::active (Info))
	    cout << "Installing src directory" << endl;
        }
    }
  else
    {
      if (CmtMessage::active (Info))
	cout << "src directory already installed" << endl;
    }

  switch (Me.m_current_style)
    {
    case cmt_style:
      //    case no_version_style:
      if (!CmtSystem::cd ("cmt"))
	{
	  CmtError::set (CmtError::system_error,
			 "Cannot cd to package cmt directory ");
	  return;
	}
      //CmtSystem::cd ("cmt");
      break;
    case mgr_style:
      if (!CmtSystem::cd ("mgr"))
	{
	  CmtError::set (CmtError::system_error,
			 "Cannot cd to package mgr directory ");
	  return;
	}
      //CmtSystem::cd ("mgr");
      break;
    }

  Generator::build_default_makefile ();

  if (!CmtSystem::test_file ("requirements"))
    {
      // create an empty requirement file.
      ofstream f ("requirements");
      if (!f)
	{
	  CmtError::set (CmtError::file_access_error, "requirements");
	  return;
	}
      f.exceptions (ios::failbit | ios::badbit);
      try
	{
          f << "package " << package << endl;
          f << endl;
	  f.close (); // ios_base::failbit
	}
      catch (const ios::failure& e)
	{
	  CmtSystem::close_ostream (NULL, "requirements: " + cmt_string (e.what ()));
	}
    }

  if (!with_version_dir)
    {
      //      ofstream f ("version.cmt");
      ofstream f (Package::get_version_file_name ());
      if (!f)
	{
	  CmtError::set (CmtError::file_access_error,
			 Package::get_version_file_name ());
	  return;
	}
      f.exceptions (ios::failbit | ios::badbit);
      try
	{
          f << version << endl;
	  f.close (); // ios_base::failbit
	}
      catch (const ios::failure& e)
	{
	  CmtSystem::close_ostream (NULL, Package::get_version_file_name () +
				    + ": " + cmt_string (e.what ()));
	}
    }

  Me.m_current_package = package;
  Me.m_current_version = version;
  Me.m_current_path    = the_path;
  Me.m_current_dir     = CmtSystem::pwd ();
  if (0 == Me.m_current_dir.size ())
    {
      CmtError::set (CmtError::system_error, "pwd empty");
      return;
    }

  do_config (ap);
}

//----------------------------------------------------------
void Cmt::do_create_project (const ArgParser& ap)
{
  int argc = ap.arguments.size ();
  int arg = 0;

  if (argc < 1) return;

  cmt_string project;
  cmt_string release;
  cmt_string path;

  project = ap.arguments[arg]; argc--; arg++;

  if (argc > 0)
    {
      release = ap.arguments[arg];

      if (release[0] != '-')
	{
	  argc--; 
	  arg++;
	  if (argc > 0)
	    {
	      path = ap.arguments[arg];
	      if (path[0] != '-')
		{
		  argc--; arg++;
		}
	      else
		{
		  path = "";
		}
	    }
	}
      else
	{
	  release = "";
	}
    }

  if (Project::create (project, release, path))
    {
      while (argc > 0)
	{
	  const cmt_string& argument = ap.arguments[arg]; argc--; arg++;
	  
	  if (argument.substr (0, 5) == "-use=")
	    {
	      cmt_string use;

	      argument.substr (5, use);

	      CmtSystem::cmt_string_vector words;
	      CmtSystem::split (use, ":", words);

	      ofstream f (Project::get_project_file_name (), ios_base::app);
	      if (f)
		{
		  f << "use " << words[0] << " " << words[1] << " " << words[2] << endl;
		  f << endl;
		  f.close ();
		}
	    }
	}
    }
}

//----------------------------------------------------------
void Cmt::do_cvsbranches (const ArgParser& ap)
{
  Cvs::branches (ap.arguments[0]);
}

//----------------------------------------------------------
void Cmt::do_cvssubpackages (const ArgParser& ap)
{
  Cvs::subpackages (ap.arguments[0]);
}

//----------------------------------------------------------
void Cmt::do_cvssubprojects (const ArgParser& ap)
{
  Cvs::subprojects (ap.arguments[0]);
}

//----------------------------------------------------------
void Cmt::do_cvstags (const ArgParser& ap)
{
  Cvs::tags (ap.arguments);
}

//----------------------------------------------------------
void Cmt::do_do (const ArgParser& ap)
{
  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();
      Cmt::reset_all_sets_done ();
      Symbol::all_set ();
      Generator::build_default_makefile ();

      Symbol* symbol = Symbol::find (ap.arguments[0]);

      if (symbol == 0)
	{
	  Me.m_action = action_show_action_names;
	  /*
	    if (!Me.m_quiet)
	    {
	    cerr << "Existing actions:" << endl;
	    print_symbol_names (ap.mode);
	    }
	  */
	  CmtError::set (CmtError::unknown_command, ap.arguments[0]);
	  return;
	}

      /*
	We convert extra arguments into the standard macro cmt_args 
      */

      cmt_string args;

      for (int i = 1; i < ap.arguments.size (); i++)
	{
	  cmt_string s = ap.arguments[i];
	  if (i > 1) args += " ";
	  args += s;
	}

      cmt_string r = "macro cmt_args \"";
      r += args;
      r += "\"";

      Use* current_use = &(Use::current ());
      
      SyntaxParser::parse_requirements_line (r, current_use);

      cmt_string cmd = symbol->build_macro_value ();
      Symbol::expand (cmd);

      CmtMessage::info ("Execute action " + ap.arguments[0] + " => " + cmd);

      int status = CmtSystem::execute (cmd);
      if (status != 0)
	{
	  CmtError::set (CmtError::execution_failed, ap.arguments[0], status);
	}
    }
}

//----------------------------------------------------------
void Cmt::do_expand_model (const ArgParser& ap)
{
  set_standard_macros ();

  if ((ap.arguments[0] == "-strict") && (ap.arguments.size () > 1))
    {
      CmtModel::strict_expand (ap.arguments[1]);
    }
  else if ((ap.arguments[0] == "-test") && (ap.arguments.size () > 2))
    {
      CmtModel::test_regexp (ap.arguments[1], ap.arguments[2]);
    }
  else if (ap.arguments.size () > 0)
    {
      CmtModel::expand (ap.arguments[0]);
    }
}

/**
 *  Handle free filtering of text files containing $(xxx) or ${xxx} patterns
 *
 *  Substitution is performed against CMT macros and environment variables.
 *
 *  Arguments:
 *
 *    cmt filter input-file-name output-file-name
 *
 */
void Cmt::do_filter (const ArgParser& ap)
{
  if (ap.arguments.size () < 2) return;

  cmt_string& input = ap.arguments[0];
  cmt_string& output = ap.arguments[1];

  if (!CmtSystem::test_file (input))
    {
      CmtError::set (CmtError::path_not_found, input);
      //      CmtMessage::error ("File " + input + " not found");
      return;
    }

  cmt_string text;

  text.read (input);

  set_standard_macros ();

  Symbol::expand (text);

  FILE* file = fopen (output, "wb");
  if (file != NULL)
    {
      text.write (file);
      CmtSystem::close_ostream (file, output);
      //      fclose (file);
    }
  else
    {
      CmtError::set (CmtError::file_access_error, output);
      //      CmtMessage::error ("Cannot write filtered file " + output);
    }
}

//----------------------------------------------------------
void Cmt::do_help (const ArgParser& ap)
{
  //cerr << "ap.help_action=" << ap.help_action << " Me.m_action=" << Me.m_action << endl;
  if (Me.m_action == action_none)
    {
      CommandHelp::show_all ();
    }
  else
    {
      CommandHelp::show (Me.m_action);
    }
}

//----------------------------------------------------------
void Cmt::do_lock (const ArgParser& ap)
{
  const cmt_string& package = Me.m_current_package;
  const cmt_string& version = Me.m_current_version;
  const cmt_string& path    = Me.m_current_path;

  //(unsused) Use& use = Use::current();

  CmtMessage::info ("try to lock package " + package + " in " + CmtSystem::pwd ());
  //  cerr << "try to lock package " << package << " in " << CmtSystem::pwd () << endl;

  set_standard_macros ();

  CmtLock::status status = CmtLock::lock ();
}

//----------------------------------------------------------
void Cmt::do_remove (const ArgParser& ap)
{
  const cmt_string& package = Me.m_current_package;
  const cmt_string& version = Me.m_current_version;
  const cmt_string& path    = Me.m_current_path;

  //Use::UsePtrVector& Uses = Use::get_ordered_uses ();

  if (Me.m_current_package == "CMT") return;
  if (Me.m_current_package == "methods") return;

  cmt_string the_path;

  //the_path = Me.m_default_path;
  the_path = CmtSystem::pwd ();

  if (path != "")
    {
      if (!CmtSystem::absolute_path (path))
        {
          // path is just a suffix
          the_path += CmtSystem::file_separator ();
          the_path += path;
        }
      else // absolute path
        {
          the_path = path;
        }
    }

  CmtSystem::compress_path (the_path);

  if (CmtMessage::active (Info))
    {
  cout << "------------------------------------------" << endl;
  cout << "Removing package " << package <<
    " version " << version << "." << endl;
  cout << "CMT version " << Me.m_cmt_version << "." << endl;
  cout << "Root set to " << the_path << "." << endl;
  cout << "System is " << Me.m_cmt_config << endl;
  cout << "------------------------------------------" << endl;
    }

  the_path += CmtSystem::file_separator ();
  the_path += package;

  if (!CmtSystem::cd (the_path))
    {
      CmtMessage::error ("Path " + the_path + " not reachable");
      //      cerr << "Path " << the_path << " not reachable" << endl;
      return;
    }

  if (CmtSystem::test_directory (version))
    {
      if (CmtSystem::remove_directory (version))
        {
	  if (CmtMessage::active (Info))
	    cerr << "Version " << version << " has been removed from " << the_path << endl;
          CmtSystem::cmt_string_vector contents;
          CmtSystem::scan_dir (".", contents);
          if (contents.size () == 0)
            {
              CmtSystem::cd ("..");
              if (CmtSystem::remove_directory (package))
                {
		  if (CmtMessage::active (Info))
		    cerr << "Package " << package << " has no more versions. Thus it has been removed."<< endl;
                }
            }
        }
      else
        {
          CmtMessage::warning ("Impossible to remove version " + version + " from " + the_path);
	  //          cerr << "Impossible to remove version " << version << " from " << the_path << endl;
        }
    }
  else if (CmtSystem::test_directory ("cmt"))
    {
      CmtSystem::cd ("cmt");

      cmt_string v;

      //      v.read ("version.cmt");
      v.read (Package::get_version_file_name ());
      if (v == version)
        {
          CmtSystem::cd ("..");
          if (!CmtSystem::remove_directory ("cmt"))
            {
	      if (CmtMessage::active (Info))
		{
              cerr << "Unstructured version " << version
                   << " has been removed from " << the_path << endl;
		}
            }
          else
            {
              CmtMessage::warning ("Impossible to remove unstructured version " + version + " from " + the_path);
	      //              cerr << "Impossible to remove unstructured version " << version
	      //                   << " from " << the_path << endl;
            }
        }
      else
        {
          CmtMessage::warning ("Version " + version + " not found");
	  //          cerr << "Version " << version << " not found" << endl;
        }
    }
  else
    {
      CmtMessage::warning ("Version " + version + " not found");
      //      cerr << "Version " << version << " not found" << endl;
    }
}

//----------------------------------------------------------
void Cmt::do_remove_library_links (const ArgParser& ap)
{
  if (CmtLock::check () == CmtLock::locked_by_another_user)
    {
      CmtError::set (CmtError::conflicting_lock, "remove_library_links>");
      return;
    }

  set_standard_macros ();

  Use::UsePtrVector& Uses = Use::get_ordered_uses ();
  Use& current_use = Use::current ();
  Use::UsePtrVector uses (Uses);
  uses.push_back (&Use::current ());
  int i;
  cmt_string cmtinstallarea = "";
  cmt_string tag = "";
  cmt_string shlibsuffix;
  cmt_string symunlinkcmd;

  {
    Symbol* macro = Symbol::find ("shlibsuffix");
    if (macro == 0)
      {
	if (strlen (ap.extra_file.c_str ()) == 0)
	  {
	    CmtError::set(CmtError::configuration_error, "shlibsuffix undefined");
	  }
	else
	  { // we are most likely reading empty library_links.in without CMT
	    if (CmtMessage::active (Verbose))
	      CmtMessage::warning
		(CmtError::get_error_name (CmtError::configuration_error)
		 + ": shlibsuffix undefined");
	  }
	return;
      }
    shlibsuffix = macro->build_macro_value ();
    Symbol::expand (shlibsuffix);
  }

  {
    Symbol* macro = Symbol::find ("symunlink");
    if (macro != 0)
      {
	symunlinkcmd = macro->build_macro_value ();
	Symbol::expand (symunlinkcmd);
      }
  }

  if (current_use.get_strategy ("InstallArea"))
    {
      const CmtInstallAreaMgr& ia_mgr = CmtInstallAreaMgr::instance ();
      
      cmt_string s1 = ia_mgr.get_installarea ();

      {
        Symbol* symbol = Symbol::find ("CMTINSTALLAREA");
        if (symbol != 0)
          {
            s1 = symbol->build_macro_value ();
	    Symbol::expand (s1);
          }
      }

      cmtinstallarea = s1;
                  
      cmt_string s2;

      {
        Symbol* macro = Symbol::find ("tag");
        if (macro != 0)
          {
            s2 = macro->build_macro_value ();
	    Symbol::expand (s2);
          }
      }

      tag = s2;
    }

  for (i = 0; i < uses.size (); i++)
    {
      Use* use = uses[i];

      if (use == 0) continue;
      if (use->discarded) continue;
      if (use->m_hidden) continue;

      if (use->get_package_name () == "CMT") continue;
      if (!use->located ())
        {
	  CmtMessage::warning ("package " + use->get_package_name ()
			       + " " + use->version + " " + use->path
			       + " not found");
	  continue;
        }

      use->remove_library_links (cmtinstallarea, tag, shlibsuffix, symunlinkcmd);
    }
}

//----------------------------------------------------------
void Cmt::do_run (const ArgParser& ap)
{
  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();
      Cmt::reset_all_sets_done ();
      Symbol::all_set ();

      cmt_string cmd;

      for (int i = 0; i < ap.arguments.size (); i++)
	{
	  cmd += ap.arguments[i];
	  cmd += " ";
	}

      int status = CmtSystem::execute (cmd);
      if (status != 0)
	{
	  CmtError::set (CmtError::execution_failed, ap.arguments[0], status);
	}
      //      CmtSystem::execute (cmd);
    }
}

//----------------------------------------------------------
void Cmt::do_run_sequence (const ArgParser& ap)
{
  if (ap.arguments.size () == 0)
    CmtMessage::warning ("run_sequence: no sequence specified");
  //cerr << "#CMT> run_sequence: no sequence specified" << endl;

  SequenceRunner runner;

  if (CmtMessage::active (Info))
    cerr << "# cmt run_sequence: sequence " << ap.arguments[0] << endl;

  runner.run (ap.arguments[0]);
}

//----------------------------------------------------------
void Cmt::do_set_version (const ArgParser& ap)
{
  if (ap.arguments.size () == 0)
    CmtMessage::warning ("set version: no version specified");
  //cerr << "#CMT> set version: no version specified" << endl;

  const cmt_string& version = ap.arguments[0];

  int v, r, p;

  if (!CmtSystem::is_version_directory (version, v, r, p))
    {
      CmtMessage::error ("set version " + version + " is not a correct version syntax");
      //      cerr << "#CMT> set version " << version << " is not a correct version syntax" << endl;
      return;
    }

  if ((v == -1) || (r == -1) || (p == -1))
    {
      CmtMessage::error ("set version " + version
			 + " You cannot use wild card to set a version");
      //      cerr << "#CMT> set version " << version
      //	   << " You cannot use wild card to set a version" << endl;
      return;
    }

  // We want to install the version.cmt file

  // We first check we are in a cmt branch
  cmt_string h = CmtSystem::pwd ();
  cmt_string branch;
  CmtSystem::basename (h, branch);

  if (branch != "cmt")
    {
      CmtMessage::error ("set version " + version
			 + " must be applied in a cmt directory");
      //      cerr << "#CMT> set version " << version << " must be applied in a cmt directory" 
      //	   << endl;
      return;
    }

  CmtSystem::dirname (h, h);
  CmtSystem::basename (h, branch);

  if (branch == version)
    {
      CmtMessage::warning ("set version " + version
			   + " is already available as a version directory");
      //      cerr << "#CMT> set version " << version << " is already available as a version directory" 
      //	   << endl;
      return;
    }

  CmtMessage::info ("Writing version file : " + version);
  //  cerr << "Writing version file : " << version << endl;

  //  version.write ("version.cmt");
  version.write (Package::get_version_file_name ());
}

//----------------------------------------------------------
void Cmt::do_set_versions (const ArgParser& ap)
{
  CmtSystem::cmt_string_vector args;

  args = ap.arguments;
  {
    cmt_string& s = args.add ();
    s = "cmt";
  }
  {
    cmt_string& s = args.add ();
    s = "set";
  }
  {
    cmt_string& s = args.add ();
    s = "version";
  }
  {
    cmt_string& s = args.add ();
    s = "<version>";
  }

  Me.m_action = action_broadcast;

  do_broadcast (ap);
}

//----------------------------------------------------------
void Cmt::do_setup (const ArgParser& ap)
{
  Use& current_use = Use::current ();

  do_check_configuration (ap);

  switch (ap.mode)
    {
    case Xml :
      Cmt::print_xml_prolog ("setup");
      cout << "<setup>";
      break;
    case Requirements :
      CmtSystem::cmt_string_vector flags;
      get_cmt_flags (flags);
      cout << "\n# CMTFLAGS: -without_cmt";
      for (int i = 0; i < flags.size (); i++)
	{
	  if (flags[i] == "-without_cmt")
	    cout << " -with_cmt";
	  else if (flags[i] == "-with_cmt")
	    cout << " -without_cmt";
	  else
	    cout << " " << flags[i]; 
	}
      cout << endl;
      break;
    }
  print (ap.mode);
  switch (ap.mode)
    {
    case Xml :
      cout << "</setup>" << endl;
      break;
    }

  //
  //  Try a cleanup of the installation area
  //
  if (current_use.get_strategy ("InstallArea"))
    {
      CmtInstallAreaMgr& ia_mgr = CmtInstallAreaMgr::instance ();

      ia_mgr.setup ();
    }
}

//----------------------------------------------------------
void Cmt::do_show_action (const ArgParser& ap)
{
  do_show_macro (ap);
}

//----------------------------------------------------------
void Cmt::do_show_action_names (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      const cmt_string& pattern = ap.arguments[0];
      print_symbol_names (ap.mode, pattern);
    }
  else
    {
      print_symbol_names (ap.mode);
    }
}

//----------------------------------------------------------
void Cmt::do_show_action_value (const ArgParser& ap)
{
  do_show_macro (ap);
}

//----------------------------------------------------------
void Cmt::do_show_actions (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      const cmt_string& pattern = ap.arguments[0];
      print_macros (ap.mode, pattern);
    }
  else
    {
      print_macros (ap.mode);
    }
}

//----------------------------------------------------------
void Cmt::do_show_alias (const ArgParser& ap)
{
  do_show_macro (ap);
}

//----------------------------------------------------------
void Cmt::do_show_alias_names (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      const cmt_string& pattern = ap.arguments[0];
      print_symbol_names (ap.mode, pattern);
    }
  else
    {
      print_symbol_names (ap.mode);
    }
}

//----------------------------------------------------------
void Cmt::do_show_alias_value (const ArgParser& ap)
{
  do_show_macro (ap);
}

//----------------------------------------------------------
void Cmt::do_show_aliases (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      const cmt_string& pattern = ap.arguments[0];
      print_macros (ap.mode, pattern);
    }
  else
    {
      print_macros (ap.mode);
    }
}

//----------------------------------------------------------
void Cmt::do_show_all_tags (const ArgParser& /*ap*/)
{
  Tag::TagPtrVector tags = Tag::tags ();
  int index;

  set_standard_macros ();

  for (index = 0; index < tags.size (); index++)
    {
      const Tag* tag = tags[index];
      if (tag != 0)
        {
          tag->show_definition (true);
        }
    }
}

//----------------------------------------------------------
void Cmt::do_show_applied_patterns (const ArgParser& /*ap*/)
{
  Pattern::show_all_applied_patterns ();
}

//----------------------------------------------------------
void Cmt::do_show_author (const ArgParser& /*ap*/)
{
  Use& use = Use::current();

  cout << use.author << endl;
  
}
//----------------------------------------------------------
void Cmt::do_show_project_author (const ArgParser& /*ap*/)
{
  cmt_string cmtpath;
  cmt_string offset;

  Use& use = Use::current();    
  use.get_cmtpath_and_offset (cmtpath, offset);

  Project* p = Project::find_by_cmtpath (cmtpath);

  cout << p->get_author () << endl;
}

//----------------------------------------------------------
void Cmt::do_show_branches (const ArgParser& ap)
{
  Branch::print_all (ap.mode);
}

//----------------------------------------------------------
void Cmt::do_show_clients (const ArgParser& ap)
{
  cmt_string package   = "";
  cmt_string version   = "";
  cmt_string path_name = "";

  if (ap.arguments.size () >= 1) package  = ap.arguments[0];
  if (ap.arguments.size () >= 2) version  = ap.arguments[1];
  if (ap.arguments.size () >= 3) path_name = ap.arguments[2];

  PathScanner scanner;
  ClientCollector collector (package, version);

  clear     ();
  //  configure ();
  configure (ap);

  cout << "# ----------- Clients of " << package
       << (version != "" ? " " + version : "")
       << (path_name != "" ? " (" + path_name + ")": "")
    //    " " << version <<
    //    " " << path_name <<
       << endl;

  if (path_name == "")
    {
      Project::scan_paths (scanner, collector);
    }
  else
    {
      scanner.scan_path (path_name, collector);
    }

  cout << "# ----------- " << collector.count () << " clients found." << endl;
}

//----------------------------------------------------------
void Cmt::do_show_cmtpath_patterns (const ArgParser& /*ap*/)
{
  set_standard_macros ();
  CmtPathPattern::show_all ();
}

//----------------------------------------------------------
void Cmt::do_show_constituent (const ArgParser& ap)
{
  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();

      Constituent* c = Constituent::find (ap.arguments[0]);
      if (c != 0)
	{
	  c->show ();
	}
      else
	{
	  cmt_string t (ap.arguments[0]);
	  CmtError::set (CmtError::constituent_not_found, t);
	}
    }
}

//----------------------------------------------------------
void Cmt::do_show_constituent_names (const ArgParser& /*ap*/)
{
  set_standard_macros ();
  Constituent::show_names ();
}

//----------------------------------------------------------
void Cmt::do_show_constituents (const ArgParser& /*ap*/)
{
  set_standard_macros ();
  Constituent::show_all ();
}

//----------------------------------------------------------
void Cmt::do_show_container (const ArgParser& ap)
{
  if (ap.arguments.size () == 0)
    {
      Project::show_container ();
    }
  else
    {
      for (int i = 0; i < ap.arguments.size (); i++)
	{
	  const cmt_string& path_name = ap.arguments[i];
	  if (CmtSystem::test_directory (path_name))
	    {
	      Project::show_container (path_name);
	    }
	  else
	    {
	      CmtMessage::warning ("No such directory: " + path_name);
	      CmtError::set (CmtError::path_not_found, path_name);
	    }
	}
    }
}

//----------------------------------------------------------
void Cmt::do_show_cycles (const ArgParser& /*ap*/)
{
  set_standard_macros ();
  Use& use = Use::current();

  use.show_cycles ();
}

//----------------------------------------------------------
void Cmt::do_show_fragment (const ArgParser& ap)
{
  if (ap.arguments.size () > 0) Fragment::show (ap.arguments[0]);
}

//----------------------------------------------------------
void Cmt::do_show_fragments (const ArgParser& /*ap*/)
{
  Fragment::show_all ();
}

//----------------------------------------------------------
void Cmt::do_show_groups (const ArgParser& /*ap*/)
{
  Constituent::parse_all ();
  //  set_standard_macros ();
  Group::show_all ();
}

//----------------------------------------------------------
void Cmt::do_show_include_dirs (const ArgParser& /*ap*/)
{
  cmt_string temp;

  Use& use = Use::current();

  set_standard_macros ();

  if (use.include_path == "")
    {
      temp += "$(src) ";
    }
  else if (use.include_path != "none")
    {
      temp += use.include_path;
      temp += " ";
    }

  for (int include_number = 0;
       include_number < use.includes.size ();
       include_number++)
    {
      Include& incl = use.includes[include_number];

      if (incl.name == "") continue;

      temp += incl.name;
      temp += " ";
    }

  cout << temp << endl;
}

//----------------------------------------------------------
void Cmt::do_show_language (const ArgParser& ap)
{
  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();
      Language::show (ap.arguments[0]);
    }
}

//----------------------------------------------------------
void Cmt::do_show_languages (const ArgParser& /*ap*/)
{
  set_standard_macros ();
  Language::show_all ();
}

//----------------------------------------------------------
static bool is_upperroot (const cmt_string& name)
{
  int r = name.find_last_of ("ROOT");
  if (r == cmt_string::npos ||
      (r + 4) != name.size () ||
      r == 0)
    return false;
  for (int i = 0; i < r; i++)
    if (islower (name[i])) return false;
  return true;
}

//----------------------------------------------------------
void Cmt::do_show_macro (const ArgParser& ap)
{
  cmt_string target;

  if (ap.arguments.size () > 0) target = ap.arguments[0];

  Symbol* symbol;

  set_standard_macros ();

  symbol = Symbol::find (target);

  if (symbol == 0) 
    {
      cmt_string t = " ";
      t += target;
      t += " is not defined ";

      CmtError::set (CmtError::symbol_not_found, t);

      return;
    }
  else
    {
      cmt_string t = target;
      t += " is ";

      if ((Me.m_action == action_show_macro) ||
          (Me.m_action == action_show_macro_value))
	{
	  if (symbol->type != Symbol::SymbolMacro)
	    {
	      if (symbol->type == Symbol::SymbolAction)
		{
		  t += "action";
		}
	      else if (symbol->type == Symbol::SymbolSet)
		{
		  t += "set";
		}
	      else if (symbol->type == Symbol::SymbolPath)
		{
		  t += "path";
		}
	      else if (symbol->type == Symbol::SymbolAlias)
		{
		  t += "alias";
		}

	      if (!is_upperroot (symbol->name))
		CmtError::set (CmtError::wrong_symbol_type, t);
	    }
	}
      else if ((Me.m_action == action_show_set) ||
               (Me.m_action == action_show_set_value))
        {
	  if ((symbol->type != Symbol::SymbolSet) &&
	      (symbol->type != Symbol::SymbolPath) &&
	      (symbol->type != Symbol::SymbolAction) &&
	      (symbol->type != Symbol::SymbolAlias))
	    {
	      t += "macro";

	      if (!is_upperroot (symbol->name))
		CmtError::set (CmtError::wrong_symbol_type, t);
	    }
        }
      else if (
	       ((Me.m_action == action_show_action ||
		 Me.m_action == action_show_action_value) &&
		symbol->type != Symbol::SymbolAction)
	       ||
	       ((Me.m_action == action_show_alias ||
		 Me.m_action == action_show_alias_value) &&
		symbol->type != Symbol::SymbolAlias)
	       )
	{
	  switch (symbol->type)
	    {
	    case Symbol::SymbolUndefined:
	      t += "undefined";
	      break;
	    case Symbol::SymbolAction:
	      t += "action";
	      break;
	    case Symbol::SymbolAlias:
	      t += "alias";
	      break;
	    case Symbol::SymbolMacro:
	      t += "macro";
	      break;
	    case Symbol::SymbolSetupScript:
	      t += "setup_script";
	      break;
	    case Symbol::SymbolCleanupScript:
	      t += "cleanup_script";
	      break;
	    case Symbol::SymbolSet:
	      t += "set";
	      break;
	    case Symbol::SymbolPath:
	      t += "path";
	      break;
	    default:
	      t += "unknown";
	      break;
	    }
	  
	  CmtError::set (CmtError::wrong_symbol_type, t);
	}
    }

  if (symbol->value_lists.size () < 1) return;

  symbol->show_macro (ap.mode);
}

//----------------------------------------------------------
void Cmt::do_show_macro_names (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      const cmt_string& pattern = ap.arguments[0];
      print_symbol_names (ap.mode, pattern);
    }
  else
    {
      print_symbol_names (ap.mode);
    }
}

//----------------------------------------------------------
void Cmt::do_show_macro_value (const ArgParser& ap)
{
  do_show_macro (ap);
}

//----------------------------------------------------------
void Cmt::do_show_macros (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      const cmt_string& pattern = ap.arguments[0];
      print_macros (ap.mode, pattern);
    }
  else
    {
      print_macros (ap.mode);
    }
}

//----------------------------------------------------------
void Cmt::do_show_manager (const ArgParser& /*ap*/)
{
  Use& use = Use::current();

  cout << use.manager << endl;
}

//----------------------------------------------------------
void Cmt::do_show_packages (const ArgParser& ap)
{
  PathScanner   scanner;
  PackageViewer viewer;

  if (ap.arguments.size () == 0)
    {
      Project::scan_paths (scanner, viewer);
    }
  else
    {
      for (int i = 0; i < ap.arguments.size (); i++)
	{
	  const cmt_string& path_name = ap.arguments[i];
	  if (CmtSystem::test_directory (path_name))
	    {
	      scanner.scan_path (path_name, viewer);
	    }
	  else
	    {
	      CmtMessage::warning ("No such directory: " + path_name);
	      CmtError::set (CmtError::path_not_found, path_name);
	    }
	}
    }
}

//----------------------------------------------------------
void Cmt::do_show_path (const ArgParser& ap, ostream& out)
{
  Project::show_paths (ap.arguments, out);
}

//----------------------------------------------------------
void Cmt::do_show_pattern (const ArgParser& ap)
{
  cmt_string name;
  if (ap.arguments.size () > 0) name = ap.arguments[0];
  Pattern::show (name);
}

//----------------------------------------------------------
void Cmt::do_show_pattern_names (const ArgParser& /*ap*/)
{
  Pattern::show_all_names ();
}

//----------------------------------------------------------
void Cmt::do_show_patterns (const ArgParser& /*ap*/)
{
  Pattern::show_all ();
}

//----------------------------------------------------------
void Cmt::do_show_projects (const ArgParser& ap)
//void Cmt::do_show_projects (const ArgParser& /*ap*/)
{
  Project::show_all (ap.mode);
}

//----------------------------------------------------------
void Cmt::do_show_pwd (const ArgParser& /*ap*/)
{
  cout << Me.m_current_dir << endl;
}

//----------------------------------------------------------
void Cmt::do_show_setup (const ArgParser& ap, ostream& out)
//void Cmt::do_show_setup (const ArgParser& ap)
{
  out << "----------> uses" << endl;
  do_show_uses (ap, out);
  // This is temporary to ensure that Make - which runs "cmt show setup" -
  // does not fail for packages with unresolved uses
  if (CmtError::get_last_error_code () == CmtError::package_not_found)
    CmtError::clear ();

  out << "----------> tags" << endl;
  do_show_tags (ap, out);

  out << "----------> CMTPATH" << endl;
  do_show_path (ap, out);
}

//----------------------------------------------------------
void Cmt::do_show_set (const ArgParser& ap)
{
  do_show_macro (ap);
}

//----------------------------------------------------------
void Cmt::do_show_set_names (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      const cmt_string& pattern = ap.arguments[0];
      print_symbol_names (ap.mode, pattern);
    }
  else
    {
      print_symbol_names (ap.mode);
    }
}

//----------------------------------------------------------
void Cmt::do_show_set_value (const ArgParser& ap)
{
  do_show_macro (ap);
}

//----------------------------------------------------------
void Cmt::do_show_sets (const ArgParser& ap)
{
  if (ap.arguments.size () > 0)
    {
      const cmt_string& pattern = ap.arguments[0];
      print_macros (ap.mode, pattern);
    }
  else
    {
      print_macros (ap.mode);
    }
}

//----------------------------------------------------------
void Cmt::do_show_strategies (const ArgParser& /*ap*/)
{
  Use& current_use = Use::current ();

  Project::show_specified_strategies_for_all ();

  Project* p = Project::get_current ();

  /*
    if (p != 0) p->show ();
    else cout << "No current project" << endl;
  */

  cout << "Build strategy     : ";

  if (current_use.get_strategy ("BuildPrototypes"))
    {
      cout << "prototypes";
    }
  else
    {
      cout << "no_prototypes";
    }
  
  if (current_use.get_strategy ("InstallArea"))
    {
      cout << " with_installarea";
    }
  else
    {
      cout << " without_installarea";
    }
  
  cout << endl;

  cout << "Setup strategy     : ";
  
  if (current_use.get_strategy ("SetupConfig"))
    {
      cout << "config";
    }
  else
    {
      cout << "no_config";
    }
  
  if (current_use.get_strategy ("SetupRoot"))
    {
      cout << " root";
    }
  else
    {
      cout << " no_root";
    }
  
  if (current_use.get_strategy ("SetupCleanup"))
    {
      cout << " cleanup";
    }
  else
    {
      cout << " no_cleanup";
    }

  if (current_use.get_strategy ("SetupScripts"))
    {
      cout << " scripts";
    }
  else
    {
      cout << " no_scripts";
    }

  cout << endl;
  
  cout << "Structure strategy : ";
  
  if (current_use.get_strategy ("VersionDirectory"))
    {
      cout << "with_version_directory";
    }
  else
    {
      cout << "without_version_directory";
    }
  
  cout << endl;

  if (Me.m_current_structuring_style != default_structuring_style)
    {
      cout << "Structuring style  : ";

      switch (Me.m_current_structuring_style)
	{
	case without_version_directory:
	  cout << "without_version_directory";
	  break;
	case with_version_directory:
	  cout << "with_version_directory";
	  break;
	}

      cout << endl;
    }
}

//----------------------------------------------------------
void Cmt::do_show_tags (const ArgParser& /*ap*/, ostream& out)
{
  Tag::TagPtrVector tags = Tag::tags ();
  int index;

  set_standard_macros ();

  for (index = 0; index < tags.size (); index++)
    {
      const Tag* tag = tags[index];
      if (tag != 0)
        {
          tag->show (Me.m_quiet, out);
        }
    }
}

//----------------------------------------------------------
void Cmt::do_show_use_paths (const ArgParser& ap)
{
  const cmt_string& to_name = ap.arguments[0];

  Use* current = &(Use::current());

  if (!current->get_all_clients (to_name))
    CmtError::set (CmtError::package_not_found, to_name);
}

//----------------------------------------------------------
void Cmt::do_show_uses (const ArgParser& ap, ostream& out)
//void Cmt::do_show_uses (const ArgParser& /*ap*/, ostream& out)
{
  Use::show_all (false, out, ap.mode);
  //  Use::show_all (false, out);
}

//----------------------------------------------------------
void Cmt::do_show_version (const ArgParser& /*ap*/)
{
  cout << Me.m_current_version << endl;
}

//----------------------------------------------------------
void Cmt::do_show_versions (const ArgParser& ap)
{
  cmt_string package_name;

  if (ap.arguments.size () > 0) package_name = ap.arguments[0];

  PathScanner scanner;

  Project::scan_paths_for_package (scanner, package_name);
}

//----------------------------------------------------------
void Cmt::do_show_system (const ArgParser& /*ap*/)
{
  cout << CmtSystem::get_cmt_config () << endl;
}

//----------------------------------------------------------
void Cmt::do_unlock (const ArgParser& /*ap*/)
{
  const cmt_string& package = Me.m_current_package;
  const cmt_string& version = Me.m_current_version;
  const cmt_string& path    = Me.m_current_path;

  // (unused??) Use& use = Use::current();

  CmtMessage::info ("try to unlock package " + package + " in " + CmtSystem::pwd ());
  //  cerr << "try to unlock package " << package << " in " << CmtSystem::pwd () << endl;

  set_standard_macros ();

  CmtLock::status status = CmtLock::unlock ();
}

//----------------------------------------------------------
void Cmt::do_version (const ArgParser& /*ap*/)
{
  cout << CMTVERSION << endl;
}



//----------------------------------------------------------
ActionType Cmt::get_action ()
{
  return (Me.m_action);
}

/*
  const CmtSystem::cmt_string_vector& Cmt::get_cmt_path ()
  {
  return (Me.m_cmt_path);
  }

  const CmtSystem::cmt_string_vector& Cmt::get_cmt_path_pwds ()
  {
  return (Me.m_cmt_path_pwds);
  }

  const CmtSystem::cmt_string_vector& Cmt::get_cmt_path_sources ()
  {
  return (Me.m_cmt_path_sources);
  }
*/

const cmt_string& Cmt::get_cmt_home ()
{
  return (Me.m_cmt_home);
}

const cmt_string& Cmt::get_cmt_user_context ()
{
  return (Me.m_cmt_user_context);
}

const cmt_string& Cmt::get_cmt_version ()
{
  return (Me.m_cmt_version);
}

const cmt_string& Cmt::get_current_dir ()
{
  return (Me.m_current_dir);
}

const cmt_string Cmt::get_current_dir_real ()
{
  cmt_string current_dir_real;
  if (CmtSystem::realpath_ (Me.m_current_dir, current_dir_real))
    return current_dir_real;
  return (Me.m_current_dir);
}

const cmt_string& Cmt::get_current_package ()
{
  return (Me.m_current_package);
}

const cmt_string& Cmt::get_current_path ()
{
  return (Me.m_current_path);
}

const cmt_string& Cmt::get_current_cmtpath ()
{
  return (Me.m_current_cmtpath);
}

const cmt_string& Cmt::get_current_offset ()
{
  return (Me.m_current_offset);
}

AccessMode Cmt::get_current_access ()
{
  return (Me.m_current_access);
}

CmtStructuringStyle Cmt::get_current_structuring_style ()
{
  return (Me.m_current_structuring_style);
}

CmtDirStyle Cmt::get_current_style ()
{
  return (Me.m_current_style);
}

const cmt_string& Cmt::get_current_version ()
{
  return (Me.m_current_version);
}

const cmt_string& Cmt::get_current_target ()
{
  return (Me.m_current_target);
}

bool Cmt::get_debug ()
{
  return (Me.m_debug);
}

bool Cmt::get_quiet ()
{
  return (Me.m_quiet);
}

bool Cmt::get_disable_warnings ()
{
  return (Me.m_disable_warnings);
}

bool Cmt::get_warnings ()
{
  return (Me.m_warnings);
}

bool Cmt::get_recursive ()
{
  return (Me.m_recursive);
}

CmtScopeFilteringMode Cmt::get_scope_filtering_mode ()
{
  if (Me.m_scope_filtering_mode == default_filtering_mode)
    {
      return (block_private_uses);
    }
  else
    {
      return (Me.m_scope_filtering_mode);
    }
}

//----------------------------------------------------------
bool Cmt::get_all_sets_done ()
{
  return (Me.m_all_sets_done);
}

//----------------------------------------------------------
void Cmt::get_cmt_flags (CmtSystem::cmt_string_vector& flags)
{
  CmtSystem::split (CmtSystem::getenv ("CMTFLAGS"), " \t", flags);
}

//----------------------------------------------------------
cmt_string Cmt::get_cmt_flags ()
{
  return CmtSystem::getenv ("CMTFLAGS");
}

//----------------------------------------------------------
class CmtFlagsReader : public FAwk
{
public:

  CmtFlagsReader ()
  { }
  
  CmtFlagsReader (const cmt_string& pattern)
    : m_pattern (pattern)
  { m_condition = ok; }
  
  const cmt_string& get_pattern () const
  {
    return (m_pattern);
  }
  
  const cmt_string& get_cmt_flags () const
  {
    return (m_cmt_flags);
  }
  
  void filter (const cmt_string& line)
  {
    int p (line.find (m_pattern));
    if (p == cmt_string::npos) return;
    if (m_cmt_flags.size () != 0)
      m_cmt_flags += " " + line.substr (p + m_pattern.size ());
    else
      m_cmt_flags = line.substr (p + m_pattern.size ());
    //stop ();
  }
  
private:
  const cmt_string m_pattern;
  cmt_string m_cmt_flags;
};

//----------------------------------------------------------
cmt_string Cmt::get_cmt_flags (const cmt_string& file_name)
{
  cmt_string result;
  CmtFlagsReader reader ("CMTFLAGS:");
  Awk::condition c = reader.run (file_name, reader.get_pattern ());
  if (Awk::failed != c)
    result = reader.get_cmt_flags ();
  else
    CmtError::set (CmtError::file_access_error, file_name);
  return result;
}

//----------------------------------------------------------
bool Cmt::set_cmt_flags (const cmt_string& cmtflags)
{
  return CmtSystem::putenv ("CMTFLAGS", cmtflags) ?
    true :
    (CmtMessage::error ("Cannot set `CMTFLAGS' to `" + cmtflags +
			"' in the environment"),
     false) ;
}

//----------------------------------------------------------
bool Cmt::add_cmt_flag (const cmt_string& flag)
{
  CmtSystem::cmt_string_vector flags;
  get_cmt_flags (flags);
  cmt_string cmtflags;
  for (int i = 0; i < flags.size (); i++)
    {
      if (flags[i] == flag) continue;
      if (cmtflags == "")
	cmtflags = flags[i]; 
      else
	cmtflags += " " + flags[i]; 
    }

  if (cmtflags == "")
    cmtflags = flag; 
  else
    cmtflags += " " + flag; 

  return set_cmt_flags (cmtflags);
}

/**---------------------------------------------------------
   guess_current_project

   if current directory is in one of the CMTPATHs, do nothing.

   Otherwise, we want to guess the current project

   move up in directories until cmt/project.cmt is found

   for (;;)
   {
   if test -f ./cmt/project.cmt
   ok:
   this directory should become the first entry of the CMTPATH
   break

   if (at top) break;

   move up
   }
*/
void Cmt::guess_current_project ()
{
  Log;

  log << "guess_current_project" << log_endl;

  cmt_string here = CmtSystem::pwd ();

  Use& use = Use::current();
  cmt_string current_path (Me.m_current_dir);
  if (use.located ())
    {
      current_path = use.real_path;
      CmtMessage::verbose ("Using current use real_path `" + current_path + "'");
    }

  if (Project::find_in_cmt_paths (current_path) == "")
    //  if (Project::find_in_cmt_paths (Me.m_current_dir) == "")
    {
      if (!CmtSystem::cd (current_path))
	{
	  CmtError::set (CmtError::file_access_error, current_path);
	  CmtError::print ();
	  return;
	}
      cmt_string project_file = "cmt";
      project_file += CmtSystem::file_separator ();
      project_file += Project::get_project_file_name ();

      cmt_string pwd;

      for (;;)
	{
	  pwd = CmtSystem::pwd ();
	  if (CmtSystem::test_file (project_file))
	    {
	      //this directory should become the first entry of the CMTPATH

	      IProjectFactory& factory = ProjectFactory::instance ();
	      factory.create_project ("", pwd, "CurrentProject", 0);

	      break;
	    }

	  log << "pwd=" << CmtSystem::pwd () << log_endl;
	  
	  if (!CmtSystem::cd (".."))
	    {
	      log << "Cannot cd up..." << log_endl;
	      break;
	    }

	  if (CmtSystem::pwd () == pwd)
	    {
	      log << "Looks the same pwd..." << log_endl;
	      break;
	    }
	}

      CmtSystem::cd (Me.m_current_dir);
    }

  //cmt_string buffer = "path CMTPATH \n";
  cmt_string buffer;
  Project::fill_cmtpaths (buffer);
  //cerr << "buffer = " << buffer << endl;
  //  Use& use = Use::current();

  bool save_quiet = Me.m_quiet;
  Me.m_quiet = true;

  SyntaxParser::parse_requirements_text (buffer, "", &use);

  Me.m_quiet = save_quiet;

  Me.m_autoconfigure_cmtpath = true;

  CmtSystem::cd (here);
}

//----------------------------------------------------------
const cmt_string& Cmt::filter_dir (const cmt_string& dir)
{
  static cmt_string newdir;

  CmtSystem::compress_path (dir, newdir);

  return (newdir);
}

//----------------------------------------------------------
static void dos_script_prefix (FILE* f, 
			       const cmt_string& cmt_root, 
			       const cmt_string& package, 
			       const cmt_string& mangled_package, 
			       const cmt_string& version, 
			       const cmt_string& path, 
			       const cmt_string& action, 
			       const cmt_string& option = "")
{
  cmt_string no_device = path;

  if (CmtSystem::absolute_path (path)) 
    {
      if (path[1] == ':')
	{
	  no_device = path.substr (2);
	}
    }

  if (package == "cmt_standalone")
    {
      no_device = "";
    }
  else
    {
      no_device = "..\\..\\..";
      if (Cmt::get_current_structuring_style () == without_version_directory)
	//      if (Cmt::get_current_style () == no_version_style)
	{
	  no_device = "..\\..";
	}
    }


  fprintf (f, "@echo off\n");
  fprintf (f, "if NOT DEFINED CMTROOT set CMTROOT=%s& set PATH=%%CMTROOT%%\\%%CMTBIN%%;%%PATH%%& set CMTBIN=VisualC& if not defined CMTCONFIG set CMTCONFIG=%%CMTBIN%%\n", cmt_root.c_str ());
  fprintf (f, "\n");
  fprintf (f, "set cmt%stempfile=\"%%TEMP%%\\cmt%stempfile.bat\"\n", mangled_package.c_str (), mangled_package.c_str ());
  fprintf (f, "%%CMTROOT%%\\%%CMTBIN%%\\cmt.exe %s -bat "
	   " -pack=%s -version=%s -path=\"%%~d0%%~p0%s\" "
	   " %s "
	   "%%1 %%2 %%3 %%4 %%5 %%6 %%7 %%8 %%9 >%%cmt%stempfile%%\n",
	   action.c_str (),
	   package.c_str (),
	   version.c_str (),
	   no_device.c_str (),
	   option.c_str (), mangled_package.c_str ());
  fprintf (f, "if exist %%cmt%stempfile%% call %%cmt%stempfile%%\n", mangled_package.c_str (), mangled_package.c_str ());
  fprintf (f, "if exist %%cmt%stempfile%% del %%cmt%stempfile%%\n", mangled_package.c_str (), mangled_package.c_str ());
  fprintf (f, "set cmt%stempfile=\n", mangled_package.c_str ());
}

//----------------------------------------------------------
void Cmt::install_cleanup_scripts ()
{
#ifdef WIN32
  static const int modes = 1;
  static const cmt_string suffix[1]   = {"bat"};
  static const PrintMode  mode[1]     = {Bat};
#else
  static const int modes = 2;
  static const cmt_string suffix[2]   = {"csh", "sh"};
  static const PrintMode  mode[2]     = {Csh, Sh};
#endif

  Use& current_use = Use::current ();

  if (!current_use.get_strategy ("SetupScripts"))
    {
      for (int i = 0; i < modes; i++)
	{
          cmt_string old_file_name = "cleanup";
          old_file_name += ".";
          old_file_name += suffix[i];
	  if (CmtSystem::test_file (old_file_name))
	    {
	      if (CmtMessage::active (Error))
		cerr << "Removing cleanup script " + old_file_name << endl;
	      CmtSystem::remove_file (old_file_name);
	    }
	}
      return;
    }

  if (CmtMessage::active (Error))
    cerr << "Creating cleanup scripts." << endl;

  cmt_string temp;
  int i;

  cmt_string version = Me.m_current_version;
  if (version == "v*") version = "";
  cmt_string mangled_package = CmtSystem::mangle (Me.m_current_package);

  for (i = 0; i < modes; i++)
    {
      cmt_string file_name = "cleanup";
      file_name += ".";
      file_name += suffix[i];
      file_name += ".";
      file_name += "new";

      FILE* f = fopen (file_name.c_str (), "wb");
      if (f != NULL)
        {
          if (mode[i] == Csh)
            {
              fprintf (f, "if ( $?CMTROOT == 0 ) then\n");
              fprintf (f, "  setenv CMTROOT %s\n", Me.m_cmt_root.c_str ());
              fprintf (f, "endif\n");
              fprintf (f, "source ${CMTROOT}/mgr/setup.csh\n");
              fprintf (f, "set cmt%stempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n", mangled_package.c_str ());
              fprintf (f, "if $status != 0 then\n  set cmt%stempfile=/tmp/cmt.$$\nendif\n", mangled_package.c_str ());
              fprintf (f, "${CMTROOT}/mgr/cmt cleanup -%s "
                       "-pack=%s -version=%s -path=%s $* >${cmt%stempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (), mangled_package.c_str ());
	      fprintf (f,
		       "if ( $status != 0 ) then\n"
		       "  echo \"${CMTROOT}/mgr/cmt cleanup -%s "
                       "-pack=%s -version=%s -path=%s $* >${cmt%stempfile}\"\n"
		       "  set cmtcleanupstatus=2\n"
		       "  /bin/rm -f ${cmt%stempfile}\n"
		       "  unset cmt%stempfile\n"
		       "  exit $cmtcleanupstatus\n"
		       "endif\n"
		       "set cmtcleanupstatus=0\n"
		       "source ${cmt%stempfile}\n"
		       "if ( $status != 0 ) then\n"
		       "  set cmtcleanupstatus=2\n"
		       "endif\n"
		       "/bin/rm -f ${cmt%stempfile}\n"
		       "unset cmt%stempfile\n"
		       "exit $cmtcleanupstatus\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str ());
            }
          else if (mode[i] == Sh)
            {
              fprintf (f, "if test \"${CMTROOT}\" = \"\"; then\n");
              fprintf (f, "  CMTROOT=%s; export CMTROOT\n", Me.m_cmt_root.c_str ());
              fprintf (f, "fi\n");
              fprintf (f, ". ${CMTROOT}/mgr/setup.sh\n");
              fprintf (f, "cmt%stempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n", mangled_package.c_str ());
              fprintf (f, "if test ! $? = 0 ; then cmt%stempfile=/tmp/cmt.$$; fi\n", mangled_package.c_str ());
              fprintf (f, "${CMTROOT}/mgr/cmt cleanup -%s "
                       "-pack=%s -version=%s -path=%s $* >${cmt%stempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (), mangled_package.c_str ());
              fprintf (f,
		       "if test $? != 0 ; then\n"
		       "  echo >&2 \"${CMTROOT}/mgr/cmt cleanup -%s "
                       "-pack=%s -version=%s -path=%s $* >${cmt%stempfile}\"\n"
		       "  cmtcleanupstatus=2\n"
		       "  /bin/rm -f ${cmt%stempfile}\n"
		       "  unset cmt%stempfile\n"
		       "  return $cmtcleanupstatus\n"
		       "fi\n"
		       "cmtcleanupstatus=0\n"
		       ". ${cmt%stempfile}\n"
		       "if test $? != 0 ; then\n"
		       "  cmtcleanupstatus=2\n"
		       "fi\n"
		       "/bin/rm -f ${cmt%stempfile}\n"
		       "unset cmt%stempfile\n"
		       "return $cmtcleanupstatus\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str ());
            }
          else if (mode[i] == Bat)
            {
	      dos_script_prefix (f, Me.m_cmt_root, 
				 Me.m_current_package, mangled_package, version, Me.m_current_path,
				 "cleanup");
            }

          fprintf (f, "\n");

          CmtSystem::close_ostream (f, file_name);
	  //          fclose (f);

          cmt_string old_file_name = "cleanup";
          old_file_name += ".";
          old_file_name += suffix[i];

          CmtSystem::compare_and_update_files (file_name, old_file_name);
        }
      else
	{
	  CmtError::set (CmtError::file_access_error, file_name);
	}
    }
}

//----------------------------------------------------------
void Cmt::install_setup_scripts ()
{
#ifdef WIN32
  static const int modes = 1;
  static const cmt_string suffix[1]   = {"bat"};
  static const PrintMode  mode[1]     = {Bat};
#else
  static const int modes = 2;
  static const cmt_string suffix[2]   = {"csh", "sh"};
  static const PrintMode  mode[2]     = {Csh, Sh};
#endif

  Use& current_use = Use::current ();

  if (!current_use.get_strategy ("SetupScripts"))
    {
      for (int i = 0; i < modes; i++)
	{
          cmt_string old_file_name = "setup";
          old_file_name += ".";
          old_file_name += suffix[i];
	  if (CmtSystem::test_file (old_file_name))
	    {
	      if (CmtMessage::active (Error))
		cerr << "Removing setup script " + old_file_name << endl;
	      CmtSystem::remove_file (old_file_name);
	    }
	}
      return;
    }

  if (CmtMessage::active (Error))
    cerr << "Creating setup scripts." << endl;
  
  cmt_string no_cleanup_opt;

  if (current_use.get_strategy ("SetupCleanup"))
    {
      no_cleanup_opt = " -no_cleanup";
    }

  cmt_string temp;
  int i;

  cmt_string version = Me.m_current_version;
  if (version == "v*") version = "";
  cmt_string mangled_package = CmtSystem::mangle (Me.m_current_package);

  for (i = 0; i < modes; i++)
    {
      cmt_string file_name = "setup";
      file_name += ".";
      file_name += suffix[i];
      file_name += ".";
      file_name += "new";

      FILE* f = fopen (file_name.c_str (), "wb");
      if (f != NULL)
        {
          if (mode[i] == Csh)
            {
              fprintf (f, "# echo \"Setting %s %s in %s\"\n",
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str ());
              fprintf (f, "\n");

              fprintf (f, "if ( $?CMTROOT == 0 ) then\n");
              fprintf (f, "  setenv CMTROOT %s\n", Me.m_cmt_root.c_str ());
              fprintf (f, "endif\n");
              fprintf (f, "source ${CMTROOT}/mgr/setup.csh\n");
              fprintf (f, "set cmt%stempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n", mangled_package.c_str ());
              fprintf (f, "if $status != 0 then\n  set cmt%stempfile=/tmp/cmt.$$\nendif\n", mangled_package.c_str ());
              fprintf (f, "${CMTROOT}/mgr/cmt setup -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${cmt%stempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str (), mangled_package.c_str ());
	      fprintf (f,
		       "if ( $status != 0 ) then\n"
		       "  echo \"${CMTROOT}/mgr/cmt setup -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${cmt%stempfile}\"\n"
		       "  set cmtsetupstatus=2\n"
		       "  /bin/rm -f ${cmt%stempfile}\n"
		       "  unset cmt%stempfile\n"
		       "  exit $cmtsetupstatus\n"
		       "endif\n"
		       "set cmtsetupstatus=0\n"
		       "source ${cmt%stempfile}\n"
		       "if ( $status != 0 ) then\n"
		       "  set cmtsetupstatus=2\n"
		       "endif\n"
		       "/bin/rm -f ${cmt%stempfile}\n"
		       "unset cmt%stempfile\n"
		       "exit $cmtsetupstatus\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str ());
            }
          else if (mode[i] == Sh)
            {
              fprintf (f, "# echo \"Setting %s %s in %s\"\n",
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str ());
              fprintf (f, "\n");

              fprintf (f, "if test \"${CMTROOT}\" = \"\"; then\n");
              fprintf (f, "  CMTROOT=%s; export CMTROOT\n", Me.m_cmt_root.c_str ());
              fprintf (f, "fi\n");
              fprintf (f, ". ${CMTROOT}/mgr/setup.sh\n");
              fprintf (f, "cmt%stempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n", mangled_package.c_str ());
              fprintf (f, "if test ! $? = 0 ; then cmt%stempfile=/tmp/cmt.$$; fi\n", mangled_package.c_str ());
              fprintf (f, "${CMTROOT}/mgr/cmt setup -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${cmt%stempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str (), mangled_package.c_str ());
              fprintf (f,
		       "if test $? != 0 ; then\n"
		       "  echo >&2 \"${CMTROOT}/mgr/cmt setup -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${cmt%stempfile}\"\n"
		       "  cmtsetupstatus=2\n"
		       "  /bin/rm -f ${cmt%stempfile}\n"
		       "  unset cmt%stempfile\n"
		       "  return $cmtsetupstatus\n"
		       "fi\n"
		       "cmtsetupstatus=0\n"
		       ". ${cmt%stempfile}\n"
		       "if test $? != 0 ; then\n"
		       "  cmtsetupstatus=2\n"
		       "fi\n"
		       "/bin/rm -f ${cmt%stempfile}\n"
		       "unset cmt%stempfile\n"
		       "return $cmtsetupstatus\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str (), mangled_package.c_str ());
            }
          else if (mode[i] == Bat)
            {
              fprintf (f, "rem Setting %s %s in %%~d0%%~p0\n",
                       Me.m_current_package.c_str (),
                       version.c_str ());
	      dos_script_prefix (f, Me.m_cmt_root, 
				 Me.m_current_package, mangled_package, version, Me.m_current_path,
				 "setup", no_cleanup_opt);
            }

          fprintf (f, "\n");

          CmtSystem::close_ostream (f, file_name);
	  //          fclose (f);

          cmt_string old_file_name = "setup";
          old_file_name += ".";
          old_file_name += suffix[i];

          CmtSystem::compare_and_update_files (file_name, old_file_name);
        }
      else
	{
	  CmtError::set (CmtError::file_access_error, file_name);
	}
    }
}

//----------------------------------------------------------
void Cmt::install_scripts (ScriptType type, const cmt_string& flags)
{
#ifdef WIN32
  static const int modes = 1;
  static const cmt_string suffix[1]   = {"bat"};
  static const PrintMode  mode[1]     = {Bat};
#else
  static const int modes = 2;
  static const cmt_string suffix[2]   = {"csh", "sh"};
  static const PrintMode  mode[2]     = {Csh, Sh};
#endif

  Use& current_use = Use::current ();
  const cmt_string action = (SetupScript == type ? "setup" : "cleanup");
  if (!current_use.get_strategy ("SetupScripts"))
    {
      for (int i = 0; i < modes; i++)
	{
          cmt_string old_file_name (action);
          //cmt_string old_file_name = "setup";
          old_file_name += ".";
          old_file_name += suffix[i];
	  if (CmtSystem::test_file (old_file_name))
	    {
	      if (CmtMessage::active (Error))
		cerr << "Removing " + action + " script " + old_file_name << endl;
	      //cerr << "Removing setup script " + old_file_name << endl;
	      CmtSystem::remove_file (old_file_name);
	    }
	}
      return;
    }

  if (CmtMessage::active (Error))
    cerr << "Creating " + action + " scripts." << endl;
  //cerr << "Creating setup scripts." << endl;
  
  cmt_string no_cleanup_opt;

  if (SetupScript == type)
    if (current_use.get_strategy ("SetupCleanup"))
      {
	no_cleanup_opt = " -no_cleanup";
      }

  no_cleanup_opt = flags + no_cleanup_opt;

  cmt_string version = Me.m_current_version;
  if (version == "v*") version = "";
  cmt_string mangled_package = CmtSystem::mangle (Me.m_current_package);

  for (int i = 0; i < modes; i++)
    {
      cmt_string file_name = action;
      //cmt_string file_name = "setup";
      file_name += ".";
      file_name += suffix[i];
      file_name += ".";
      file_name += "new";

      FILE* f = fopen (file_name.c_str (), "wb");
      if (f != NULL)
        {
          if (mode[i] == Csh)
            {
              //fprintf (f, "# echo \"Setting %s %s in %s\"\n",
              fprintf (f, "# echo \"%s %s %s in %s\"\n",
		       action.c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str ());
              fprintf (f, "\n");

              fprintf (f, "if ( $?CMTROOT == 0 ) then\n");
              fprintf (f, "  setenv CMTROOT %s\n", Me.m_cmt_root.c_str ());
              fprintf (f, "endif\n");
              fprintf (f, "source ${CMTROOT}/mgr/setup.csh\n");
              fprintf (f, "set cmt%stempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n", mangled_package.c_str ());
              fprintf (f, "if $status != 0 then\n  set cmt%stempfile=/tmp/cmt.$$\nendif\n", mangled_package.c_str ());
              //fprintf (f, "${CMTROOT}/mgr/cmt setup -%s "
              fprintf (f, "${CMTROOT}/mgr/cmt %s -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${cmt%stempfile}\n",
		       action.c_str (),
		       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str (),
		       mangled_package.c_str ());
	      fprintf (f,
		       "if ( $status != 0 ) then\n"
		       "  echo \"${CMTROOT}/mgr/cmt %s -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${cmt%stempfile}\"\n"
		       "  set cmt%sstatus=2\n"
		       "  /bin/rm -f ${cmt%stempfile}\n"
		       "  unset cmt%stempfile\n"
		       "  exit $cmt%sstatus\n"
		       "endif\n"
		       "set cmt%sstatus=0\n"
		       "source ${cmt%stempfile}\n"
		       "if ( $status != 0 ) then\n"
		       "  set cmt%sstatus=2\n"
		       "endif\n"
		       "/bin/rm -f ${cmt%stempfile}\n"
		       "unset cmt%stempfile\n"
		       "exit $cmt%sstatus\n",
		       action.c_str (),
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str (), mangled_package.c_str (),
		       action.c_str (),
		       mangled_package.c_str (),
		       mangled_package.c_str (),
		       action.c_str (),
		       action.c_str (),
		       mangled_package.c_str (),
		       action.c_str (),
		       mangled_package.c_str (),
		       mangled_package.c_str (),
		       action.c_str ());
            }
          else if (mode[i] == Sh)
            {
              //fprintf (f, "# echo \"Setting %s %s in %s\"\n",
              fprintf (f, "# echo \"%s %s %s in %s\"\n",
		       action.c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str ());
              fprintf (f, "\n");

              fprintf (f, "if test \"${CMTROOT}\" = \"\"; then\n");
              fprintf (f, "  CMTROOT=%s; export CMTROOT\n", Me.m_cmt_root.c_str ());
              fprintf (f, "fi\n");
              fprintf (f, ". ${CMTROOT}/mgr/setup.sh\n");
              fprintf (f, "cmt%stempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n", mangled_package.c_str ());
              fprintf (f, "if test ! $? = 0 ; then cmt%stempfile=/tmp/cmt.$$; fi\n", mangled_package.c_str ());
              //fprintf (f, "${CMTROOT}/mgr/cmt setup -%s "
              fprintf (f, "${CMTROOT}/mgr/cmt %s -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${cmt%stempfile}\n",
		       action.c_str (),
		       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str (),
		       mangled_package.c_str ());
              fprintf (f,
		       "if test $? != 0 ; then\n"
		       "  echo >&2 \"${CMTROOT}/mgr/cmt %s -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${cmt%stempfile}\"\n"
		       "  cmt%sstatus=2\n"
		       "  /bin/rm -f ${cmt%stempfile}\n"
		       "  unset cmt%stempfile\n"
		       "  return $cmt%sstatus\n"
		       "fi\n"
		       "cmt%sstatus=0\n"
		       ". ${cmt%stempfile}\n"
		       "if test $? != 0 ; then\n"
		       "  cmt%sstatus=2\n"
		       "fi\n"
		       "/bin/rm -f ${cmt%stempfile}\n"
		       "unset cmt%stempfile\n"
		       "return $cmt%sstatus\n",
		       action.c_str (),
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str (), mangled_package.c_str (),
		       action.c_str (),
		       mangled_package.c_str (),
		       mangled_package.c_str (),
		       action.c_str (),
		       action.c_str (),
		       mangled_package.c_str (),
		       action.c_str (),
		       mangled_package.c_str (),
		       mangled_package.c_str (),
		       action.c_str ());
            }
          else if (mode[i] == Bat)
            {
              //fprintf (f, "rem Setting %s %s in %%~d0%%~p0\n",
              fprintf (f, "rem %s %s %s in %%~d0%%~p0\n",
		       action.c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str ());
	      dos_script_prefix (f, Me.m_cmt_root, 
				 Me.m_current_package, mangled_package, version, Me.m_current_path,
				 action, no_cleanup_opt);
	      //"setup", no_cleanup_opt);
            }

          fprintf (f, "\n");

          CmtSystem::close_ostream (f, file_name);
	  //          fclose (f);

          cmt_string old_file_name = action;
          //cmt_string old_file_name = "setup";
          old_file_name += ".";
          old_file_name += suffix[i];

          CmtSystem::compare_and_update_files (file_name, old_file_name);
        }
      else
	{
	  CmtError::set (CmtError::file_access_error, file_name);
	}
    }
}

//----------------------------------------------------------
void Cmt::install_native_version_file ()
{    
  Use& current_use        = Use::current ();
  cmt_string package_name = current_use.get_package_name();
  cmt_string macro_name   = package_name + "_native_version";
  Symbol* macro           = Symbol::find (macro_name);
  if (macro != 0)
    {
      cmt_string value = macro->resolve_macro_value ();
      if (value != "")
	{
	  if (CmtMessage::active (Info))
	    cerr << "Creating native_version file." << endl;    

	  cmt_string file_name ("new.native_version.cmt");
	  FILE* f = fopen (file_name.c_str (), "wb");
	  if (f != NULL)
	    {
	      fprintf (f, "%s\n", value.c_str ());
	      CmtSystem::close_ostream (f, file_name);
	      //          fclose (f);
	      
	      CmtSystem::compare_and_update_files ("new.native_version.cmt", "native_version.cmt");
	    }      
	  else
	    {
	      CmtError::set (CmtError::file_access_error, file_name);
	    }
	} 
    }    
}

/**
 *    load is only called from the Windows GUI which pretends to access directly
 *   the internal data model.
 *    This is considered to be rather unsafe, and should be replaced by query functions.
 */
//bool Cmt::load (const cmt_string& path,
bool Cmt::load (const ArgParser& ap,
		const cmt_string& path,
                const cmt_string& package,
                const cmt_string& version,
                const cmt_string& tag_name)
{
  clear ();
  //  configure ();
  configure (ap);

  Me.m_action  = action_load;
  Me.m_recursive = true;

  if (((package != "") && (version != "")) || (Me.m_current_package == ""))
    {
      //
      //  Here we want to connect to a new package, or to the current package
      //  but with another tag.
      //
      //   the 'package' argument may include a directory offset. Thus 'path'
      //  is only expected to hold the base directory.
      //
      cmt_string offset;
      cmt_string package_name;
      
      CmtSystem::dirname (package, offset);
      CmtSystem::basename (package, package_name);
      
      if (offset != "")
        {
          Me.m_current_path = path;
          Me.m_current_path += CmtSystem::file_separator ();
          Me.m_current_path += offset;
        }
      else
        {
          Me.m_current_path = path;
        }
      
      Me.m_current_package = package_name;
      Me.m_current_version = version;
    }

  if (tag_name != "")
    {
      Tag* tag;

      Tag::unmark_all ();
      configure_version_tag ();
      configure_site_tag (0);
      configure_uname_tag ();
      configure_hosttype_tag ();

      Me.m_current_tag = tag_name;

      //if (!Me.m_quiet) cerr << "load1> current_tag=" << Me.m_current_tag << endl;

      tag = Tag::add (tag_name, PriorityTag, "load", 0);
      tag->mark ("load");
    }

  /*
    Set to developer mode if positioned into the package
    (which is detected since we were able to retreive the
    Version, Package and Path)
  */

  if ((Me.m_current_path == "") ||
      (Me.m_current_package == "") ||
      (Me.m_current_version == ""))
    {
      Me.m_current_access = UserMode;
    }
  else
    {
      Me.m_current_access = DeveloperMode;
    }

  use_cmt ();

  cmt_string dir;

  /*
    Try to access the package.
  */

  if (Me.m_current_path != "")
    {
      dir = Me.m_current_path;
    }
  else
    {
      dir = Me.m_default_path;
    }

  if (!CmtSystem::cd (Me.m_current_path))
    {
      CmtMessage::error ("Cannot reach the directory " + Me.m_current_path);
      /*
      if (!Me.m_quiet)
        {
          cerr << "#CMT> Cannot reach the directory " <<
            Me.m_current_path << endl;
        }
      */
      CmtError::set (CmtError::package_not_found, "Load> Cannot reach the path directory");
      CmtSystem::cd (Me.m_current_dir);

      return (false);
    }

  dir += CmtSystem::file_separator ();
  dir += Me.m_current_package;

  if (!CmtSystem::cd (Me.m_current_package))
    {
      CmtMessage::error ("Cannot reach the package " + Me.m_current_package);
      /*
      if (!Me.m_quiet)
        {
          cerr << "#CMT::load> Cannot reach the package " <<
            Me.m_current_package << endl;
        }
      */
      CmtError::set (CmtError::package_not_found, "Load> Cannot reach the package directory");
      CmtSystem::cd (Me.m_current_dir);

      return (false);
    }

  dir += CmtSystem::file_separator ();
  dir += Me.m_current_version;

  Me.m_current_style = none_style;
  Me.m_current_structuring_style = without_version_directory;

  if (!CmtSystem::cd (Me.m_current_version))
    {
      if (!CmtSystem::test_directory ("cmt"))
        {
	  CmtMessage::error ("Cannot reach the version " + Me.m_current_version);
	  /*
          if (!Me.m_quiet)
            {
              cerr << "#CMT> Cannot reach the version " <<
                Me.m_current_version << endl;
            }
	  */
          CmtError::set (CmtError::package_not_found, "Load> Cannot reach the version directory");
          CmtSystem::cd (Me.m_current_dir);

          return (false);
        }
      else
        {
	  Me.m_current_style = cmt_style;
          Me.m_current_structuring_style = without_version_directory;
	  //          Me.m_current_style = no_version_style;
        }
    }

  if (CmtSystem::cd ("cmt"))
    {
      dir += CmtSystem::file_separator ();
      dir += "cmt";
      if (Me.m_current_style == none_style)
	{
	  Me.m_current_style = cmt_style;
          Me.m_current_structuring_style = with_version_directory;
	}
    }
  else
    {
      /*
        if (!Me.m_quiet)
        {
        cerr << "Cannot reach the cmt branch" << endl;
        }
      */

      if (CmtSystem::cd ("mgr"))
        {
          dir += CmtSystem::file_separator ();
          dir += "mgr";
          if (Me.m_current_style == none_style)
	    {
	      Me.m_current_style = mgr_style;
	      Me.m_current_structuring_style = with_version_directory;
	    }
        }
      else
        {
	  CmtMessage::error ("Cannot reach the mgr branch");
	  /*
          if (!Me.m_quiet)
            {
              cerr << "#CMT> Cannot reach the mgr branch" << endl;
            }
	  */

          CmtError::set (CmtError::package_not_found,
                         "Load> Cannot reach the mgr/cmt directory");
          CmtSystem::cd (Me.m_current_dir);

          return (false);
        }
    }

  /*
    Check Tag is always set up
  */

  if (Me.m_current_tag == "")
    {
      char* env;

      env = getenv (Me.m_current_config.c_str ());
      if (env != 0)
        {
          Tag* tag;

          tag = Tag::add (env, PriorityConfig, "load", 0);
          tag->mark ("load");
          Me.m_current_tag = env;

          //if (!Me.m_quiet) cerr << "load2> current_tag=" << Me.m_current_tag << endl;

        }
      else
        {
          Me.m_current_tag = Me.m_cmt_config;

          //if (!Me.m_quiet) cerr << "load3> current_tag=" << Me.m_current_tag << endl;

        }
    }

  if (Me.m_debug)
    {
      cout << "pwd = " << CmtSystem::pwd () << endl;
    }

  configure_current_dir ();
  build_prefix (Me.m_current_package, Me.m_current_prefix);
  build_config (Me.m_current_prefix, Me.m_current_config);

  Use* use = &(Use::current());
  use->path    = Me.m_current_path;
  use->set_package_name (Me.m_current_package);
  use->version = Me.m_current_version;
  use->prefix  = Me.m_current_prefix;
  use->done    = false;
  use->style   = Me.m_current_style;
  use->structuring_style  = Me.m_current_structuring_style;

  /*
    Work on the requirements file.
  */

  dir += CmtSystem::file_separator ();
  dir += "requirements";
  SyntaxParser::parse_requirements (dir, use);

  if (CmtError::has_pending_error ()) return (false);

  /**
   * See reach_current_package for an explanation of this call
   */
  Pattern::apply_all_globals ();

  /*
    Select all possible tags
  */

  Tag::restore_tree ();

  return (true);
}

//----------------------------------------------------------
bool Cmt::need_prototypes ()
{
  Use& current_use = Use::current ();

  if (current_use.get_strategy ("BuildPrototypes")) return (true);
  else return (false);
}

//----------------------------------------------------------
void Cmt::parse_arguments (ArgParser& ap)
{
  /*
    Decoding arguments.

    While decoding all arguments, no requirements analysis should
    occur. Every new option, or parameter should be saved and
    used later at actual analysis time.
  */

  Me.m_action = action_none;

  restore_all_tags (0);

#ifdef WIN32
  Me.m_build_nmake = true;
#endif

  ap.parse ();
}

//----------------------------------------------------------
int Cmt::parser (const cmt_string& command_line)
{
  CmtSystem::cmt_string_vector v;

  CmtSystem::split (command_line, " \t", v);

  int argc = v.size ();

  char** argv = (char**) malloc ((argc + 1) * sizeof (char*));

  int i;
  for (i = 0; i < argc; i++)
    {
      argv[i] = (char*) v[i].c_str ();
    }
  argv[argc] = 0;

  int status = parser (argc, argv);

  free (argv);

  return (status);
}

//----------------------------------------------------------
int Cmt::parser (int argc, char* argv[])
{
  ArgParser ap (Me);
  
  ap.argc = argc;
  ap.argv = argv;

  if (argc <= 1)
    {
      do_help (ap);
      return 2;
      //      exit (0);
    }

  // save CMTFLAGS
  cmt_string cmtflags (get_cmt_flags ());

  clear ();

  //  configure ();
  configure (ap);

  CmtError::clear ();

  /*
    Set private if positioned inside the package
    (which is detected since we were able to retreive the
    Version, Package and Path)
  */

  if ((Me.m_current_path.size () == 0) ||
      (Me.m_current_package.size () == 0) ||
      (Me.m_current_version.size () == 0))
    {
      Me.m_current_access = UserMode;
    }
  else
    {
      Me.m_current_access = DeveloperMode;
    }
  
  parse_arguments (ap);
  
  if (ap.help_action == action_help)
    {
      int code (0);
      if (CmtError::has_pending_error ())
	{
	  code = CmtError::get_last_error_code ();
	  CmtError::print ();
	}
      do_help (ap);
      return code;
    }

  if (Me.m_debug)
    {
      cout << "After parse_argument> pack=" << Me.m_current_package
           << " Me.m_current_tag=" << Me.m_current_tag
           << " cwd=" << CmtSystem::pwd () 
	   << " mode=" << Me.m_current_access
           << endl;
    }

  if (Me.m_configure_error != "")
    {
      CmtMessage::error (Me.m_configure_error);
      //      if (!Me.m_quiet) cerr << "#CMT> Error: " << Me.m_configure_error << endl;
      return (CmtError::execution_error);
    }

  if (CmtError::has_pending_error ())
    {
      int code = CmtError::get_last_error_code ();
      CmtError::print ();
      //      if (!Me.m_quiet) CmtError::print ();
      clear ();

      return (code);
    }

  /*
    Now actual requirements analysis can take place.

    Extra lines or files are analysed first.
  */

  //  if (strlen (ap.extra_file.c_str ()) > 0) SyntaxParser::parse_requirements (ap.extra_file, (Use*) 0);
  //  if (strlen (ap.extra_line.c_str ()) > 0) SyntaxParser::parse_requirements_line (ap.extra_line, (Use*) 0);

  //
  //  For some of the actions, the CMT package must be automatically
  //  included
  //

  if (Me.m_debug) cout << "parser1> current_tag=" << Me.m_current_tag << endl;

//   if (ap.help_action == action_help)
//     {
//       do_help (ap);
//       int code (0);
//       if (CmtError::has_pending_error ())
// 	{
// 	  code = CmtError::get_last_error_code ();
// 	  CmtError::print ();
// 	}
//       return code;
//       //return (0);
//     }

  switch (Me.m_action)
    {
      // case action_none :
    case action_awk :
    case action_broadcast :
    case action_build_constituent_makefile :
    case action_build_constituent_config :
    case action_build_constituents_makefile :
    case action_build_constituents_config :
    case action_build_broadcast_config :
    case action_build_dependencies :
    case action_build_library_links :
    case action_build_make_setup :
    case action_build_msdev :
    case action_build_CMT_pacman :
    case action_build_vsnet :     
    case action_build_os9_makefile :
      // case action_build_prototype :
    case action_build_readme :
    case action_build_tag_makefile :
      // case action_build_temporary_name :
    case action_build_triggers :
    case action_build_windefs :
    case action_check_configuration :
      // case action_check_files :
      // case action_check_version :
    case action_checkout :
    case action_cleanup :
    case action_config :
    case action_create :
      // case action_create_project :
    case action_cvsbranches :
    case action_cvssubpackages :
    case action_cvssubprojects :
    case action_cvstags :
    case action_do :
    case action_expand_model :
    case action_filter :
      // case action_help :
    case action_load :
    case action_lock :
    case action_relocate:
    case action_remove :
    case action_remove_library_links :
    case action_run :
    case action_run_sequence :
    case action_set_version :
    case action_set_versions :
    case action_setup :
    case action_show_action :
    case action_show_action_names :
    case action_show_action_value :
    case action_show_actions :
    case action_show_alias :
    case action_show_alias_names :
    case action_show_alias_value :
    case action_show_aliases :
    case action_show_all_tags :
    case action_show_applied_patterns :
      // case action_show_author :
      // case action_show_branches :
      // case action_show_clients :
    case action_show_cmtpath_patterns :
    case action_show_constituent :
    case action_show_constituent_names :
    case action_show_constituents :
    case action_show_container :
    case action_show_cycles :
    case action_show_fragment :
    case action_show_fragments :
    case action_show_groups :
    case action_show_include_dirs :
    case action_show_language :
    case action_show_languages :
    case action_show_macro :
    case action_show_macro_names :
    case action_show_macro_value :
    case action_show_macros :
      // case action_show_manager :
    case action_show_packages :
    case action_show_path :
    case action_show_pattern :
    case action_show_pattern_names :
    case action_show_patterns :
    case action_show_projects :
      // case action_show_pwd :
    case action_show_setup :
    case action_show_set :
    case action_show_set_names :
    case action_show_set_value :
    case action_show_sets :
    case action_show_strategies :
    case action_show_tags :
    case action_show_use_paths :
    case action_show_uses :
    case action_show_version :
      // case action_show_versions :
      // case action_system :
    case action_unlock :
    case action_version :
      if (Me.m_use_cmt)
	{
      use_cmt ();
	}
      //
      // Now parse the requirements file stored in ${CMTHOME}
      //
      
      use_home_requirements ();

      configure_devenv_tag ();

      break;
    default:
      break;
    }

  if (Me.m_debug) cout << "parser2> current_tag=" << Me.m_current_tag << endl;

  //
  // Setting up recursive actions
  //

  switch (Me.m_action)
    {
      // case action_none :
    case action_awk :
    case action_broadcast :
    case action_build_constituent_makefile :
    case action_build_constituent_config :
    case action_build_constituents_makefile :
    case action_build_constituents_config :
    case action_build_broadcast_config :
    case action_build_dependencies :
    case action_build_library_links :
    case action_build_make_setup :
    case action_build_msdev :
    case action_build_CMT_pacman :
    case action_build_vsnet :     
    case action_build_os9_makefile :
      // case action_build_prototype :
    case action_build_readme :
    case action_build_tag_makefile :
      // case action_build_temporary_name :
    case action_build_triggers :
    case action_build_windefs :
    case action_check_configuration :
      // case action_check_files :
      // case action_check_version :
      // case action_checkout :
    case action_cleanup :
    case action_config :
      // case action_create :
      // case action_create_project :
      // case action_cvsbranches :
      // case action_cvssubpackages :
      // case action_cvssubprojects :
      // case action_cvstags :
    case action_do :
    case action_expand_model :
    case action_filter :
      // case action_help :
    case action_load :
      // case action_lock :
      // case action_remove :
    case action_relocate:
    case action_remove_library_links :
    case action_run :
    case action_run_sequence :
      // case action_set_version :
    case action_set_versions :
    case action_setup :
    case action_show_action :
    case action_show_action_names :
    case action_show_action_value :
    case action_show_actions :
    case action_show_alias :
    case action_show_alias_names :
    case action_show_alias_value :
    case action_show_aliases :
    case action_show_all_tags :
    case action_show_applied_patterns :
      // case action_show_author :
      // case action_show_branches :
      // case action_show_clients :
    case action_show_cmtpath_patterns :
    case action_show_constituent :
    case action_show_constituent_names :
    case action_show_constituents :
    case action_show_container :
    case action_show_cycles :
    case action_show_fragment :
    case action_show_fragments :
    case action_show_groups :
    case action_show_include_dirs :
    case action_show_language :
    case action_show_languages :
    case action_show_macro :
    case action_show_macro_names :
    case action_show_macro_value :
    case action_show_macros :
      // case action_show_manager :
    case action_show_packages :
    case action_show_path :
    case action_show_pattern :
    case action_show_pattern_names :
    case action_show_patterns :
    case action_show_projects :
      // case action_show_pwd :
    case action_show_setup :
    case action_show_set :
    case action_show_set_names :
    case action_show_set_value :
    case action_show_sets :
    case action_show_strategies :
    case action_show_tags :
    case action_show_use_paths :
    case action_show_uses :
      // case action_show_version :
      // case action_show_versions :
      // case action_system :
      // case action_unlock :
      // case action_version :
      Me.m_recursive = true;
      break;
    default:
      Me.m_recursive = false;
      break;
    }

  //
  //  Actions for which the context of the package is checked,
  //  and the requirements file is analysed.
  //

  switch (Me.m_action)
    {
    case action_none :
    case action_awk :
    case action_broadcast :
    case action_build_constituent_makefile :
    case action_build_constituent_config :
    case action_build_constituents_makefile :
    case action_build_constituents_config :
    case action_build_broadcast_config :
    case action_build_dependencies :
    case action_build_library_links :
    case action_build_make_setup :
    case action_build_msdev :
    case action_build_CMT_pacman :
    case action_build_vsnet :     
    case action_build_os9_makefile :
      // case action_build_prototype :
    case action_build_readme :
    case action_build_tag_makefile :
      // case action_build_temporary_name :
    case action_build_triggers :
    case action_build_windefs :
    case action_check_configuration :
      // case action_check_files :
      // case action_check_version :
      // case action_checkout :
    case action_cleanup :
    case action_config :
      // case action_create :
      // case action_create_project :
      // case action_cvsbranches :
      // case action_cvssubpackages :
      // case action_cvssubprojects :
      // case action_cvstags :
    case action_do :
    case action_expand_model :
    case action_filter :
      // case action_help :
    case action_load :
    case action_lock :
      // case action_remove :
    case action_relocate :
    case action_remove_library_links :
    case action_run :
      // case action_run_sequence :
      // case action_set_version :
    case action_set_versions :
    case action_setup :
    case action_show_action :
    case action_show_action_names :
    case action_show_action_value :
    case action_show_actions :
    case action_show_alias :
    case action_show_alias_names :
    case action_show_alias_value :
    case action_show_aliases :
    case action_show_all_tags :
    case action_show_applied_patterns :
    case action_show_author :
    case action_show_branches :
      // case action_show_clients :
    case action_show_cmtpath_patterns :
    case action_show_constituent :
    case action_show_constituent_names :
    case action_show_constituents :
    case action_show_container :
    case action_show_cycles :
    case action_show_fragment :
    case action_show_fragments :
    case action_show_groups :
    case action_show_include_dirs :
    case action_show_language :
    case action_show_languages :
    case action_show_macro :
    case action_show_macro_names :
    case action_show_macro_value :
    case action_show_macros :
    case action_show_manager :
    case action_show_packages :
    case action_show_path :
    case action_show_pattern :
    case action_show_pattern_names :
    case action_show_patterns :
    case action_show_projects :
    case action_show_project_author :
    case action_show_pwd :
    case action_show_setup :
    case action_show_set :
    case action_show_set_names :
    case action_show_set_value :
    case action_show_sets :
    case action_show_strategies :
    case action_show_tags :
    case action_show_use_paths :
    case action_show_uses :
    case action_show_version :
      // case action_show_versions :
      // case action_system :
    case action_unlock :
      // case action_version :
      {
	bool w = Me.m_warnings;
	Me.m_warnings = false;
	if (strlen (ap.extra_file.c_str ()) == 0)
	  reach_current_package ();
	else
	  use_extra_file (ap.extra_file);
	use_user_context_requirements ();
	if (strlen (ap.extra_line.c_str ()) > 0)
	  SyntaxParser::parse_requirements_text (ap.extra_line, "extra statement(s)", (Use*) 0);
	Me.m_warnings = w;
	//if (strlen (ap.extra_line.c_str ()) > 0) SyntaxParser::parse_requirements_line (ap.extra_line, &(Use::current ()));
      }
      break;
    default:
      break;
    }

  //
  // Set auto_imports
  //

  Use::UsePtrVector uses;
  Use* use (0);
  use = Use::find (CmtSystem::get_home_package ());
  if (use != 0 && !use->discarded && !use->m_hidden && use->located ())
    uses.push_back (use);
  uses.push_back (&(Use::current()));
  use = Use::find (CmtSystem::get_user_context_package ());
  if (use != 0 && !use->discarded && !use->m_hidden && use->located ())
    uses.push_back (use);

  cmt_map <Use*, bool> visited;
  for (int i = 0; i < uses.size (); i++)
    //for (int i = uses.size () - 1; i >= 0; i--)
    {
      Use* use = uses[i];
      use->set_auto_imports (use->auto_imports, use->auto_imports, visited);
    }

  if (Me.m_debug) cout << "parser3> current_tag=" << Me.m_current_tag << endl;

  //
  // Perform some actions even if there is an error
  //

  if (CmtError::has_pending_error ())
    {
      int code = CmtError::get_last_error_code ();
      if (!Me.m_quiet) CmtError::print ();

      switch (Me.m_action)
        {
          // case action_none :
          // case action_awk :
          // case action_broadcast :
        case action_build_constituent_makefile :
	case action_build_constituent_config :
        case action_build_constituents_makefile :
        case action_build_constituents_config :
	case action_build_broadcast_config :
        case action_build_dependencies :
        case action_build_library_links :
        case action_build_make_setup :
        case action_build_msdev :
	case action_build_CMT_pacman :
        case action_build_vsnet :     
        case action_build_os9_makefile :
        case action_build_prototype :
        case action_build_readme :
        case action_build_tag_makefile :
          // case action_build_temporary_name :
        case action_build_triggers :
        case action_build_windefs :
        case action_check_configuration :
          // case action_check_files :
          // case action_check_version :
          // case action_checkout :
        case action_cleanup :
          // case action_config :
          // case action_create :
          // case action_create_project :
          // case action_cvsbranches :
          // case action_cvssubpackages :
          // case action_cvssubprojects :
          // case action_cvstags :
          // case action_do :
          // case action_expand_model :
          // case action_filter :
          // case action_help :
        case action_load :
        case action_lock :
        case action_relocate :
        case action_remove :
        case action_remove_library_links :
          // case action_run :
        case action_run_sequence :
	  // case action_set_version :
          // case action_set_versions :
        case action_setup :
          // case action_show_action :
          // case action_show_action_names :
          // case action_show_action_value :
          // case action_show_actions :
	  // case action_show_alias :
	  // case action_show_alias_names :
	  // case action_show_alias_value :
	  // case action_show_aliases :
          // case action_show_all_tags :
          // case action_show_applied_patterns :
          // case action_show_author :
          // case action_show_branches :
          // case action_show_clients :
          // case action_show_cmtpath_patterns :
          // case action_show_constituent :
          // case action_show_container :
          // case action_show_constituent_names :
          // case action_show_constituents :
	  // case action_show_cycles :
          // case action_show_fragment :
          // case action_show_fragments :
          // case action_show_groups :
          // case action_show_include_dirs :
          // case action_show_language :
          // case action_show_languages :
          // case action_show_macro :
          // case action_show_macro_names :
          // case action_show_macro_value :
          // case action_show_macros :
          // case action_show_manager :
          // case action_show_packages :
          // case action_show_path :
          // case action_show_pattern :
          // case action_show_pattern_names :
          // case action_show_patterns :
          // case action_show_projects :
          // case action_show_pwd :
          // case action_show_setup :
          // case action_show_set :
          // case action_show_set_names :
          // case action_show_set_value :
          // case action_show_sets :
          // case action_show_strategies :
          // case action_show_tags :
          // case action_show_use_paths :
          // case action_show_uses :
          // case action_show_version :
          // case action_show_versions :
          // case action_system :
        case action_unlock :
          // case action_version :
          clear ();
          return (code);
        default:
          CmtError::clear ();
          break;
        }
    }

  //
  // Perform actions
  //

  if (!Me.m_simulation)
    {
      switch (Me.m_action)
	{
	case action_none :
	  //CmtError::set (CmtError::syntax_error, "ParseArguments> ");
	  break;
	case action_awk :
	  do_awk (ap);
	  break;
	case action_broadcast :
	  do_broadcast (ap);
	  break;
	case action_build_constituent_makefile :
	  do_build_constituent_makefile (ap);
	  break;
	case action_build_constituent_config :
	  do_build_constituent_config (ap);
	  break;
	case action_build_constituents_makefile :
	  do_build_constituents_makefile (ap);
	  break;
	case action_build_constituents_config :
	  do_build_constituents_config (ap);
	  break;
	case action_build_broadcast_config :
	  do_build_broadcast_config (ap);
	  break;
	case action_build_dependencies :
	  do_build_dependencies (ap, argc, argv);
	  break;
	case action_build_library_links :
	  do_build_library_links (ap);
	  break;
	case action_build_make_setup :
	  do_build_make_setup (ap);
	  break;
	case action_build_msdev :
	  do_build_msdev (ap);
	  break;
	case action_build_CMT_pacman :
	  do_build_CMT_pacman (ap);
	  break;
	case action_build_vsnet :     
	  do_build_vsnet (ap);
	  break;
	case action_build_os9_makefile :
	  do_build_os9_makefile (ap);
	  break;
	case action_build_prototype :
	  do_build_prototype (ap);
	  break;
	case action_build_readme :
	  do_build_readme (ap);
	  break;
	case action_build_tag_makefile :
	  do_build_tag_makefile (ap);
	  break;
	case action_build_temporary_name :
	  do_build_temporary_name (ap);
	  break;
	case action_build_triggers :
	  do_build_triggers (ap);
	  break;
	case action_build_windefs :
	  do_build_windefs (ap);
	  break;
	case action_check_configuration :
	  do_check_configuration (ap);
	  break;
	case action_check_files :
	  do_check_files (ap);
	  break;
	case action_check_version :
	  do_check_version (ap);
	  break;
	case action_checkout :
	  do_checkout (ap);
	  break;
	case action_cleanup :
	  do_cleanup (ap);
	  break;
	case action_config :
	  do_config (ap);
	  break;
	case action_create :
	  do_create (ap);
	  break;
	case action_create_project :
	  do_create_project (ap);
	  break;
	case action_cvsbranches :
	  do_cvsbranches (ap);
	  break;
	case action_cvssubpackages :
	  do_cvssubpackages (ap);
	  break;
	case action_cvssubprojects :
	  do_cvssubprojects (ap);
	  break;
	case action_cvstags :
	  do_cvstags (ap);
	  break;
	case action_do :
	  do_do (ap);
	  break;
	case action_expand_model :
	  do_expand_model (ap);
	  break;
	case action_filter :
	  do_filter (ap);
	  break;
	case action_help :
	  do_help (ap);
	  break;
	case action_load :
	  CmtMessage::error ("action not implemented");
	  //	  cerr << "#CMT> action not implemented" << endl;
	  break;
	case action_lock :
	  do_lock (ap);
	  break;
	case action_relocate :
	  do_relocate (ap);
	  break;
	case action_remove :
	  do_remove (ap);
	  break;
	case action_remove_library_links :
	  do_remove_library_links (ap);
	  break;
	case action_run :
	  do_run (ap);
	  break;
	case action_run_sequence :
	  do_run_sequence (ap);
	  break;
	case action_set_version :
	  do_set_version (ap);
	  break;
	case action_set_versions :
	  do_set_versions (ap);
	  break;
	case action_setup :
	  do_setup (ap);
	  break;
	case action_show_action :
	  do_show_action (ap);
	  break;
	case action_show_action_names :
	  do_show_action_names (ap);
	  break;
	case action_show_action_value :
	  do_show_action_value (ap);
	  break;
	case action_show_actions :
	  do_show_actions (ap);
	  break;
	case action_show_alias :
	  do_show_alias (ap);
	  break;
	case action_show_alias_names :
	  do_show_alias_names (ap);
	  break;
	case action_show_alias_value :
	  do_show_alias_value (ap);
	  break;
	case action_show_aliases :
	  do_show_aliases (ap);
	  break;
	case action_show_all_tags :
	  do_show_all_tags (ap);
	  break;
	case action_show_applied_patterns :
	  do_show_applied_patterns (ap);
	  break;
	case action_show_author :
	  do_show_author (ap);
	  break;
	case action_show_branches :
	  do_show_branches (ap);
	  break;
        case action_show_container :
	  do_show_container (ap);
	  break;
	case action_show_clients :
	  do_show_clients (ap);
	  break;
	case action_show_cmtpath_patterns :
	  do_show_cmtpath_patterns (ap);
	  break;
	case action_show_constituent :
	  do_show_constituent (ap);
	  break;
	case action_show_constituent_names :
	  do_show_constituent_names (ap);
	  break;
	case action_show_constituents :
	  do_show_constituents (ap);
	  break;
	case action_show_cycles :
	  do_show_cycles (ap);
	  break;
	case action_show_fragment :
	  do_show_fragment (ap);
	  break;
	case action_show_fragments :
	  do_show_fragments (ap);
	  break;
	case action_show_groups :
	  do_show_groups (ap);
	  break;
	case action_show_include_dirs :
	  do_show_include_dirs (ap);
	  break;
	case action_show_language :
	  do_show_language (ap);
	  break;
	case action_show_languages :
	  do_show_languages (ap);
	  break;
	case action_show_macro :
	  do_show_macro (ap);
	  break;
	case action_show_macro_names :
	  do_show_macro_names (ap);
	  break;
	case action_show_macro_value :
	  do_show_macro_value (ap);
	  break;
	case action_show_macros :
	  do_show_macros (ap);
	  break;
	case action_show_manager :
	  do_show_manager (ap);
	  break;
	case action_show_packages :
	  do_show_packages (ap);
	  break;
	case action_show_path :
	  do_show_path (ap);
	  break;
	case action_show_pattern :
	  do_show_pattern (ap);
	  break;
	case action_show_pattern_names :
	  do_show_pattern_names (ap);
	  break;
	case action_show_patterns :
	  do_show_patterns (ap);
	  break;
	case action_show_projects :
	  do_show_projects (ap);
	  break;
	case action_show_project_author :
	  do_show_project_author (ap);
	  break;
	case action_show_pwd :
	  do_show_pwd (ap);
	  break;
	case action_show_setup :
	  do_show_setup (ap);
	  break;
	case action_show_set :
	  do_show_set (ap);
	  break;
	case action_show_set_names :
	  do_show_set_names (ap);
	  break;
	case action_show_set_value :
	  do_show_set_value (ap);
	  break;
	case action_show_sets :
	  do_show_sets (ap);
	  break;
	case action_show_strategies :
	  do_show_strategies (ap);
	  break;
	case action_show_tags :
	  do_show_tags (ap);
	  break;
	case action_show_use_paths :
	  do_show_use_paths (ap);
	  break;
	case action_show_uses :
	  do_show_uses (ap);
	  break;
	case action_show_version :
	  do_show_version (ap);
	  break;
	case action_show_versions :
	  do_show_versions (ap);
	  break;
	case action_system :
	  do_show_system (ap);
	  break;
	case action_unlock :
	  do_unlock (ap);
	  break;
	case action_version :
	  do_version (ap);
	  break;
	default:
	  CmtError::set (CmtError::syntax_error, "ParseArguments>");
	  break;
	}
    }

  // restore CMTFLAGS
  set_cmt_flags (cmtflags);

  if (CmtError::has_pending_error ())
    {
      int code = CmtError::get_last_error_code ();      
      if (code == CmtError::execution_failed)
	{
          code = CmtError::get_last_execution_error();
	}   
      
      CmtError::print ();
      //      if (!Me.m_quiet) CmtError::print ();
      clear ();
      return (code);
    }
  else
    {
      clear ();
      return (0);
    }
}


/**
 * Format as one single line a set of 'setenv' statements
 * joined with semi-colons to form one shell command.
 */
void Cmt::print (PrintMode mode)
{
  Use::UsePtrVector& Uses = Use::get_ordered_uses ();
  Use& current_use = Use::current ();

  cmt_string tag;

  set_standard_macros ();

  //cerr << "# current_tag=" << Me.m_current_tag << endl;
  //cerr << "# current_config=" << Me.m_current_config << endl;

  if (Me.m_current_tag == "")
    {
      if (mode == Bat) tag = "%CMTCONFIG%";
      else tag = "${CMTCONFIG}";
    }
  else
    {
      tag = Me.m_current_tag;
    }

  //
  //  Now check if all extra tags are still valid. Some of them
  //  may be discarded du to some conflict with highest priority
  //  tags, or with exclude statements
  //

  {
    CmtSystem::cmt_string_vector words;
      
    cmt_string tags;

    tags = Me.m_extra_tags;
      
    CmtSystem::split (tags, " \t,", words);

    Me.m_extra_tags = ",";
      
    for (int i = 0; i < words.size (); i++)
      {
        Tag* tag;
        const cmt_string& a = words[i];

        tag = Tag::find (a);

        if ((tag != 0) && (tag->is_selected ()))
          {
            Me.m_extra_tags += a;
            Me.m_extra_tags += ",";
          }
      }
  }

  if (mode == Requirements)
    {
      //do_show_tags (ap, cout);
      Tag::TagPtrVector tags = Tag::tags ();
      for (int index = 0; index < tags.size (); index++)
	{
	  const Tag* tag = tags[index];
	  if (tag != 0)
	    {
	      tag->show (true, cout, "apply_tag ");
	    }
	}
    }

  if (Me.m_debug)
    {
      cout << "Before all print contexts" << endl;
    }

  if (Uses.size () > 0)
    {
      int number;

      for (number = 0; number < Uses.size (); number++)
        {
          Use& use = *(Uses[number]);

          if (use.discarded) continue;
          if (use.m_hidden) continue;
          
          print_context (use, mode, tag);
        }
    }

  print_context (Use::current (), mode, tag);

  if (Me.m_debug)
    {
      cout << "After all print contexts" << endl;
    }

  Symbol::all_print (mode);
  // Script::all_print (mode);

  if (Me.m_debug)
    {
      cout << "After all print" << endl;
    }

  switch (mode)
    {
    case Xml :
      break;
    default :
  cout << endl;
      break;
    }
}


/**
 * Format as one single line a set of 'unsetenv' statements
 * joined with semi-colons to form one shell command.
 */
void Cmt::print_clean (PrintMode mode)
{
  Use::UsePtrVector& Uses = Use::get_ordered_uses ();

  set_standard_macros ();

  //Script::all_print_clean (mode);
  Symbol::all_print_clean (mode);

  cmt_string prefix;
  if (0 != CmtSystem::mangle (Me.m_current_prefix, prefix))
    CmtMessage::verbose ("Replace " + Me.m_current_prefix + " with " + prefix);

  switch (mode)
    {
    case Csh :
      if (Me.m_current_package != "CMT")
        {
          cout << "unsetenv " << prefix << "ROOT" << endl;
          cout << "unsetenv " << prefix << "CONFIG" << endl;
        }
      break;
    case Sh :
      if (Me.m_current_package != "CMT")
        {
          cout << "[ -z ${" << prefix << "ROOT+CMT} ] || unset " << prefix << "ROOT" << endl;
          cout << "[ -z ${" << prefix << "CONFIG+CMT} ] || unset " << prefix << "CONFIG" << endl;
	  //          cout << "unset " << prefix << "ROOT" << endl;
	  //          cout << "unset " << prefix << "CONFIG" << endl;
        }
      break;
    case Bat :
      if (Me.m_current_package != "CMT")
        {
          cout << "set " << prefix << "ROOT=" << endl;
          cout << "set " << prefix << "CONFIG=" << endl;
        }
      break;
    }

  if (Uses.size () > 0)
    {
      int number;

      for (number = 0; number < Uses.size (); number++)
        {
          Use* use = Uses[number];

          if (use->discarded) continue;
          if (use->m_hidden) continue;

	  Package* p = use->get_package ();
	  if (p->is_cmt ()) continue;


	  if (0 != CmtSystem::mangle (use->prefix, prefix))
	    CmtMessage::verbose ("Replace " + use->prefix + " with " + prefix);

          switch (mode)
            {
            case Csh :
              cout << "unsetenv " << prefix << "ROOT" << endl;
              cout << "unsetenv " << prefix << "CONFIG" << endl;
              break;
            case Sh :
	      cout << "[ -z ${" << prefix << "ROOT+CMT} ] || unset " << prefix << "ROOT" << endl;
	      cout << "[ -z ${" << prefix << "CONFIG+CMT} ] || unset " << prefix << "CONFIG" << endl;
	  //              cout << "unset " << prefix << "ROOT" << endl;
	  //              cout << "unset " << prefix << "CONFIG" << endl;
              break;
            case Bat :
              cout << "set " << prefix << "ROOT=" << endl;
              cout << "set " << prefix << "CONFIG=" << endl;
              break;
            }
        }
    }

  switch (mode)
    {
    case Csh :
      cout << "unsetenv CMTEXTRATAGS" << endl;
      break;
    case Sh :
      cout << "[ -z ${CMTEXTRATAGS+CMT} ] || unset CMTEXTRATAGS" << endl;
	      //      cout << "unset CMTEXTRATAGS" << endl;
      break;
    case Bat :
      cout << "set CMTEXTRATAGS=" << endl;
      break;
    }

  cout << endl;
}

//----------------------------------------------------------
void Cmt::print_context (Use& use, PrintMode mode, const cmt_string& tag)
{
  if (use.get_package_name () == "cmt_standalone") return;

  cmt_string fs = CmtSystem::file_separator ();

  use.real_path.replace_all (CmtSystem::file_separator (), fs);

  cmt_string system = CmtSystem::get_cmt_config ();

  bool do_config = use.get_strategy ("SetupConfig");
  bool do_root   = use.get_strategy ("SetupRoot");
    
  cmt_string prefix (use.prefix);
  switch (mode)
    {
    case Requirements :
      break;
    default:
      if (do_config || do_root)
	{
	  if (0 != CmtSystem::mangle (use.prefix, prefix))
	    CmtMessage::verbose ("Replace " + use.prefix + " with " + prefix);
	}
      break;
    }
  
  switch (mode)
    {
    case Csh :
      if (do_root)
	{
	  cout << "setenv " << prefix << "ROOT \"" <<
	    use.get_full_path () << "\"" << endl;
	}

      if (use.get_package_name () == "CMT")
        {
          cout << "setenv CMTCONFIG " << system << endl;
        }
      else
        {
	  if (do_config)
	    {
	      cout << "setenv " << prefix << "CONFIG \"" << tag << "\"" << endl;
	    }
	}
        
      break;
    case Sh :
      if (do_root)
	{
	  cout << prefix << "ROOT=\"" <<
	    use.get_full_path () << "\"; export " <<
	    prefix << "ROOT" << endl;
        }

      if (use.get_package_name () == "CMT")
        {
          cout << "CMTCONFIG=" << system << "; export CMTCONFIG" << endl;
        }
      else
        {
	  if (do_config)
	    {
	      cout << prefix << "CONFIG=\"" <<
		tag << "\"; export " <<
		prefix << "CONFIG" << endl;
	    }
	}
        
      break;
    case Bat :
      if (do_root)
	{
	  cout << "set " << prefix << "ROOT=" <<
	    CmtSystem::quote (use.get_full_path (), " \t") << endl;
	}

      if (use.get_package_name () == "CMT")
        {
          cout << "set CMTCONFIG=" << system << endl;
        }
      else
        {
	  if (do_config)
	    {
	      cout << "set " << prefix << "CONFIG=" << CmtSystem::quote (tag, " \t") << endl;
	    }
	}
        
      break;
    case Xml :
      if (do_root)
	{
	  cout << "<variable><name>" << prefix << "ROOT</name>"
	       << "<value>" << use.get_full_path () << "</value></variable>";
	}

      if (use.get_package_name () == "CMT")
        {
	  cout << "<variable><name>CMTCONFIG</name>"
	       << "<value>" << system << "</value></variable>";
        }
      else
        {
	  if (do_config)
	    {
	      cout << "<variable><name>" << prefix << "CONFIG</name>"
		   << "<value>" << tag << "</value></variable>";
	    }
	}
        
      break;
    case Requirements :
      if (do_root &&
	  use.get_package_name () != "CMT")
	{
	  cout << "set " << use.prefix << "ROOT " <<
	    CmtSystem::quote (use.get_full_path (), " \t") << endl;

	  cmt_string name (use.prefix + "ROOT");
	  Symbol* symbol = Symbol::find (name);
	  if (symbol != 0) 
	    {
	      symbol->printed = true;
	    }
	  if (symbol == 0 || symbol->type != Symbol::SymbolMacro)
	    {
	      CmtMessage::warning
		(CmtError::get_error_name (CmtError::symbol_not_found)
		 + ": macro " + name);
	    }
        }

      if (use.get_package_name () == "CMT")
        {
	  cout << "set CMTCONFIG " << system << endl;
        }
      else
        {
	  if (do_config)
	    {
	      cout << "set " << use.prefix << "CONFIG " << CmtSystem::quote (tag, " \t") << endl;
	    }
	}
        
      break;
    }
}

/**
 *  Format a set of make macro definitions (one per line)
 * Each macro value is provided enclosed in single quotes
 *
 *  Take the macro values from the macro statements found
 * in recursively read requirements files.
 */
void Cmt::print_symbol_names (PrintMode mode, const cmt_string& pattern)
{
  int number;

  set_standard_macros ();

  cmt_regexp expression (pattern);

  bool has_pattern = (pattern != "");

  for (number = 0; number < Symbol::symbol_number (); number++)
    {
      Symbol& symbol = Symbol::symbol (number);

      if (has_pattern)
	{
	  if (!expression.match (symbol.name)) continue;
	}

      if (Me.m_action == action_show_macro_names)
        {
          // Only keep macros.
          if ((symbol.type == Symbol::SymbolSet) ||
              (symbol.type == Symbol::SymbolAlias) ||
              (symbol.type == Symbol::SymbolPath) ||
              (symbol.type == Symbol::SymbolAction)) continue;
        }
      else if (Me.m_action == action_show_set_names)
        {
          // Exclude macros, actions.
          if ((symbol.type == Symbol::SymbolMacro) ||
              (symbol.type == Symbol::SymbolAction)) continue;
        }
      else if (Me.m_action == action_show_action_names)
        {
          // Only keep actions.
          if (symbol.type != Symbol::SymbolAction) continue;
        }
      else if (Me.m_action == action_show_alias_names)
        {
          // Only keep aliases.
          if (symbol.type != Symbol::SymbolAlias) continue;
        }

      cout << symbol.name << endl;
    }
}

/**
 *  Format a set of make macro definitions (one per line)
 * Each macro value is provided enclosed in single quotes
 *
 *  Take the macro values from the macro statements found
 * in recursively read requirements files.
 */
void Cmt::print_macros (PrintMode mode, const cmt_string& pattern, ostream& out)
//void Cmt::print_macros (PrintMode mode, const cmt_string& pattern)
{
  int number;

  set_standard_macros ();

  cmt_regexp expression (pattern);

  bool has_pattern = (pattern != "");

  for (number = 0; number < Symbol::symbol_number (); number++)
    {
      Symbol& symbol = Symbol::symbol (number);

      if (has_pattern)
	{
	  if (!expression.match (symbol.name)) continue;
	}

      if (Me.m_action == action_show_macros)
        {
          // Only keep macros.
          if ((symbol.type == Symbol::SymbolSet) ||
              (symbol.type == Symbol::SymbolAlias) ||
              (symbol.type == Symbol::SymbolPath) ||
              (symbol.type == Symbol::SymbolAction)) continue;
        }
      else if (Me.m_action == action_show_sets)
        {
          // Exclude macros.
          if ((symbol.type == Symbol::SymbolMacro) ||
              (symbol.type == Symbol::SymbolAction)) continue;
        }
      else if ((Me.m_action == action_build_tag_makefile) ||
	       (Me.m_action == action_build_constituents_config) ||
	       (Me.m_action == action_build_constituent_config))
        {
          // Exclude scripts and actions
          if ((symbol.type == Symbol::SymbolSetupScript) ||
              (symbol.type == Symbol::SymbolCleanupScript) ||
              (symbol.type == Symbol::SymbolAction)) continue;
        }
      else if (Me.m_action == action_show_actions)
        {
          if (symbol.type != Symbol::SymbolAction) continue;
        }
      else if (Me.m_action == action_show_aliases)
        {
          if (symbol.type != Symbol::SymbolAlias) continue;
        }

      if (symbol.value_lists.size () < 1) continue;

      symbol.show_macro (mode, out);
      //      symbol.show_macro (mode);
    }
}

//----------------------------------------------------------
void Cmt::print_tabs (int tabs)
{
  while (tabs > 0)
    {
      cout << "  ";
      tabs--;
    }
}

//----------------------------------------------------------
void Cmt::print_xml_prolog (const cmt_string& root, ostream& out)
{
  out << "<?xml version=\"1.0\" standalone=\"no\"?>" << endl;
  cmt_string dtd_file (Me.m_cmt_root);
  dtd_file += CmtSystem::file_separator ();
  dtd_file += "mgr";
  dtd_file += CmtSystem::file_separator ();
  dtd_file += "CMT.dtd";
  out << "<!DOCTYPE " + root + " SYSTEM \"" + dtd_file + "\">" << endl;
}

//----------------------------------------------------------
int Cmt::reach_current_package ()
{
  Use& use = Use::current ();
  cmt_string dir;

  if (Me.m_debug)
    {
      cout << "Cmt::reach_current_package> pwd = " 
	   << CmtSystem::pwd () 
	   << " path=" << Me.m_current_path
	   << " package=" << Me.m_current_package
	   << endl;
    }

  /*
    Try to access the package.
  */

  if (Me.m_current_package == "cmt_standalone")
    {
      if ((Me.m_current_path != "") && (Me.m_current_path != CmtSystem::pwd ()))
        {
          if (!CmtSystem::cd (Me.m_current_path))
            {
              CmtError::set (CmtError::package_not_found,
                             "ReachCurrentPackage> Cannot reach the path directory");
              return (0);
            }
        }

      if (!CmtSystem::test_file ("requirements"))
        {
          return (0);
        }

      Me.m_current_structuring_style = without_version_directory;
    }
  else if (Me.m_current_package != "")
    {
      if (!use.move_to () && !use.move_to ("", true))
	//      if (!use.move_to ())
        {
          CmtError::set (CmtError::package_not_found,
                         "ReachCurrentPackage> Cannot reach the path directory");
          return (0);
        }

      Me.m_current_path = use.real_path;
    }
  else
    {
      //
      // The cmt command has been given without explicit search for 
      // a package. Thus it is expected that we are in the context of a
      // true package.
      //
      //  This means that there should be a requirements file visible.
      //
      //  If this is not true, we'll make a try into ../cmt and then
      // a last try into ../mgr
      //

      if (!CmtSystem::test_file ("requirements"))
        {
          if (CmtSystem::cd ("../cmt") && 
              CmtSystem::test_file ("requirements"))
            {
              Me.m_current_style = cmt_style;
            }
          else if (CmtSystem::cd ("../mgr") && 
                   CmtSystem::test_file ("requirements"))
            {
              Me.m_current_style = mgr_style;
            }
          else
            {
	      CmtMessage::error ("Cannot reach the mgr branch");
	      /*
              if (!Me.m_quiet)
                {
                  cerr << "#CMT> Cannot reach the mgr branch" << endl;
                }
	      */
              
              CmtError::set (CmtError::package_not_found,
                             "ReachCurrentPackage> Cannot reach the mgr/cmt directory");
              return (0);
            }
        }
      else
	Me.m_current_style = none_style;

      dir = CmtSystem::pwd ();

      CmtSystem::dirname (dir, Me.m_current_path);
      CmtSystem::basename (Me.m_current_path, Me.m_current_version);

      if (CmtSystem::is_version_directory (Me.m_current_version))
        {
          CmtSystem::dirname (Me.m_current_path, Me.m_current_path);
          CmtSystem::basename (Me.m_current_path, Me.m_current_package);
          CmtSystem::dirname (Me.m_current_path, Me.m_current_path);
	  Me.m_current_structuring_style = with_version_directory;
        }
      else
        {
          Me.m_current_package = Me.m_current_version;
          Me.m_current_version = "";
          CmtSystem::dirname (Me.m_current_path, Me.m_current_path);
          Me.m_current_structuring_style = without_version_directory;
	  //          Me.m_current_style = no_version_style;
        }

      use.set_package_name (Me.m_current_package);
      use.version = Me.m_current_version;
      use.path    = Me.m_current_path;
      use.style   = Me.m_current_style;
      use.structuring_style = Me.m_current_structuring_style;
    }

  configure_current_dir ();
  build_prefix (Me.m_current_package, Me.m_current_prefix);
  build_config (Me.m_current_prefix, Me.m_current_config);

  /*
    Check Tag is always set up
  */

  if (Me.m_debug) cout << "reach_current_package0> current_tag=" << Me.m_current_tag << endl;

  if (Me.m_current_tag == "")
    {
      cmt_string env;

      env = CmtSystem::getenv (Me.m_current_config);
      if (env != "")
        {
          Tag* tag;

          tag = Tag::add (env, PriorityConfig, "reach current package", 0);
          tag->mark (use.get_package_name ());
	  //Me.m_current_tag = env;

          //if (!Me.m_quiet) cerr << "reach_current_package1> current_tag=" << Me.m_current_tag << endl;

        }
    }

  if (Me.m_debug)
    {
      cout << "pwd = " << CmtSystem::pwd () << endl;
    }

  /*
    Work on the requirements file.
  */

  if (dir != "") dir += CmtSystem::file_separator ();
  dir += "requirements";
  SyntaxParser::parse_requirements (dir, &use);

  if (Me.m_debug) cout << "reach_current_package2> current_tag=" << Me.m_current_tag << endl;

  /**
   *   It would be useful to change this mechanism. Instead of
   *  applying all global patterns at once to all use contexts, it
   *  would be much better to apply it at the end of each
   *  requirements file parsing, and only in the context the
   *  appropriate Use.
   *
   *   This would avoid the current flaw which is that when a global
   *  pattern specifies a "private" definition, it is actually
   *  applied in the scope context of the Current Use and not in
   *  each individual Use. Therefore the private is lost.
   *
   *   However, this induces problems since some pattern definitions
   *  are done AFTER the use statements, which will NOT receive the
   *  pattern aplications.
   *
   *   Therefore it is decided to leave this "bad" mechanism until
   *  everybody is aware of this constraint.
   *
   * 
   */
  Pattern::apply_all_globals ();

  /*
    Select all possible tags
  */

  Tag::restore_tree ();

  return (1);
}

//----------------------------------------------------------
int Cmt::use_extra_file (const cmt_string& file)
{
  if (!CmtSystem::test_file (file))
    {
      CmtError::set (CmtError::path_not_found, file);
      return 0;
    }

  // (almost) Cmt::reach_current_package ()
  Use& use = Use::current ();
  /*
    Try to access the package.
  */

  if (Me.m_current_package == "cmt_standalone")
    {
      if ((Me.m_current_path != "") && (Me.m_current_path != CmtSystem::pwd ()))
        {
          if (!CmtSystem::cd (Me.m_current_path))
            {
              CmtError::set (CmtError::package_not_found,
                             "ReachCurrentPackage> Cannot reach the path directory");
              return (0);
            }
        }
      /*
      if (!CmtSystem::test_file ("requirements"))
        {
          return (0);
        }
      */
      Me.m_current_structuring_style = without_version_directory;
    }
  else if (Me.m_current_package != "")
    {
      if (!use.move_to () && !use.move_to ("", true))
	//      if (!use.move_to ())
        {
          CmtError::set (CmtError::package_not_found,
                         "ReachCurrentPackage> Cannot reach the path directory");
	  //          return -1;
	  return (0);
        }

      Me.m_current_path = use.real_path;
    }
  else
    {
      //
      // The cmt command has been given without explicit search for 
      // a package. Thus it is expected that we are in the context of a
      // true package.
      //
      //  This means that there should be a requirements file visible.
      //
      //  If this is not true, we'll make a try into ../cmt and then
      // a last try into ../mgr
      //

      //...
    }

  configure_current_dir ();
  build_prefix (Me.m_current_package, Me.m_current_prefix);
  build_config (Me.m_current_prefix, Me.m_current_config);

  /*
    Check Tag is always set up
  */

  if (Me.m_debug) cout << "use_extra_file0> current_tag=" << Me.m_current_tag << endl;

  if (Me.m_current_tag == "")
    {
      cmt_string env;

      env = CmtSystem::getenv (Me.m_current_config);
      if (env != "")
        {
          Tag* tag;

          tag = Tag::add (env, PriorityConfig, "reach current package", 0);
          tag->mark (use.get_package_name ());
	  //Me.m_current_tag = env;

          //if (!Me.m_quiet) cerr << "use_extra_file1> current_tag=" << Me.m_current_tag << endl;

        }
    }

  if (Me.m_debug)
    {
      cout << "pwd = " << CmtSystem::pwd () << endl;
    }

  /*
    Work on the requirements file.
  */

  SyntaxParser::parse_requirements (file, &use);

  if (Me.m_debug) cout << "use_extra_file2> current_tag=" << Me.m_current_tag << endl;

  /**
   *   It would be useful to change this mechanism. Instead of
   *  applying all global patterns at once to all use contexts, it
   *  would be much better to apply it at the end of each
   *  requirements file parsing, and only in the context the
   *  appropriate Use.
   *
   *   This would avoid the current flaw which is that when a global
   *  pattern specifies a "private" definition, it is actually
   *  applied in the scope context of the Current Use and not in
   *  each individual Use. Therefore the private is lost.
   *
   *   However, this induces problems since some pattern definitions
   *  are done AFTER the use statements, which will NOT receive the
   *  pattern aplications.
   *
   *   Therefore it is decided to leave this "bad" mechanism until
   *  everybody is aware of this constraint.
   *
   * 
   */
  Pattern::apply_all_globals ();

  /*
    Select all possible tags
  */

  Tag::restore_tree ();

  return (1);
}

//----------------------------------------------------------
static cmt_string get_best_form (const CmtSystem::cmt_string_vector& pwd,
                                 const cmt_string& path)
{
  static cmt_string fs = CmtSystem::file_separator ();
  cmt_string result;

  /*
  //if (CmtSystem::getenv ("CMTTESTPREFIX") != "")
  {
  */

  //
  //  If there is a common prefix between
  //  use->real_path and pwd
  //  we have 
  //  use->real_path = /<prefix>/aaa
  //  pwd            = /<prefix>/bbb
  //
  //  Then use->real_path may be expressed as:
  //  ../..../../aaa
  //   where ../..../../ moves up to /<prefix>
  //
  //   Then we try to find the shortest between
  //
  //     /<prefix> and ../..../..
  //
  cmt_string a = path;
  
  CmtSystem::cmt_string_vector va;
  
  va.clear ();
  
  CmtSystem::split (a, fs, va);
  
  int m = va.size ();
  if (pwd.size () < m) m = pwd.size ();
  
  int i;
  
  for (i = 0; i < m; i++)
    {
      const cmt_string& fa = va[i];
      const cmt_string& fb = pwd[i];
      
      if (fa != fb) break;
    }
  
  cmt_string ups = "";
  
  if (i > 0)
    {
      // We have the prefix.
      // if we count what remains from pwd, then 
      // we have the number of ../ required to 
      // move to /<prefix>
      int j;
      
      for (j = i; j < pwd.size (); j++)
        {
          if (j > i) ups += fs;
          ups += "..";
        }

      for (j = i; j < va.size (); j++)
        {
          ups += fs;
          ups += va[j];
        }
    }
  
  //
  // Here ups contains the ../..../../aaa form
  // for the use->real_path or is empty when there
  // were no common prefix.
  //
  
  //if (ups != "")
  if ((ups != "") &&
      (ups.size () < path.size ()))
    {
      result = ups;
    }
  else
    {
      result = path;
    }

  return (result);
}

/**
 *   This completely local class holds primitive actions for building
 *   standard macros.
 */
class StandardMacroBuilder
{
public:

  /**
   *  CMTVERSION
   */
  void fill_for_CMTVERSION ()
  {
    buffer = "macro CMTVERSION \"";
    buffer += CMTVERSION;
    buffer += "\"";
    apply ();
  }

  StandardMacroBuilder (const cmt_string& tag,
                        const cmt_string& package,
                        const cmt_string& version,
                        const cmt_string& prefix,
                        CmtDirStyle style)
  {
    fs = CmtSystem::file_separator ();
    buffer = "";
    //pwd = CmtSystem::pwd ();
    //CmtSystem::split (pwd, fs, vb);
    current_use = &(Use::current ());
    current_tag = tag;
    current_package = package;
    current_version = version;
    current_prefix = prefix;
    current_style = style;
  }

  void apply ()
  {
    SyntaxParser::parse_requirements_line (buffer, current_use);
    buffer = "";
  }

  /**
   *   tag
   */
  void fill_for_tag ()
  {
    static bool tag_debug = CmtSystem::testenv ("TAGDEBUG");

    if (!Symbol::is_selected ("tag"))
      {
        if (tag_debug) cerr << "set_standard_macro2.1> current_tag=" << current_tag << endl;

        if (current_tag == "")
          {
            buffer = "macro tag \"$(CMTCONFIG)\"";
          }
        else
          {
            buffer = "macro tag \"";
            buffer += current_tag;
            buffer += "\"";
          }
        
        if (tag_debug) cerr << " define tag: " << buffer << endl;
        
        apply ();
      }
  }

  /**
   *   PACKAGE_ROOT
   */
  void fill_for_package ()
  {
    buffer = "macro package \"";
    buffer += current_package;
    buffer += "\"";
    apply ();

    buffer = "macro version \"";
    buffer += current_version;
    buffer += "\"";
    apply ();

    if (!Symbol::is_selected ("PACKAGE_ROOT"))
      {
        buffer = "macro PACKAGE_ROOT \"$(";
        buffer += current_prefix;
	buffer += "ROOT";
        buffer += ")\"";

        apply ();
      }
  }

  /**
   *   srcdir
   *   src       =$(srcdir)/
   *   inc
   *   mgrdir
   *   mgr       =../$(mgrdir)/
   *   bin
   *   javabin
   *   doc
   *   version
   *   package
   *
   *   <package>_project
   *   <package>_cmtpath
   *   <package>_offset
   *   package_cmtpath
   *   package_offset
   *   project
   *
   */
  void fill_for_branches ()
  {
    /**
     *    Basic macros  (src, mgr, ...)
     */
    
    if (current_style == none_style)
      {
        if (!Symbol::is_selected ("srcdir"))
          {
	    buffer = "macro srcdir \".";
	    buffer += "\"";
	    apply ();
          }

        if (!Symbol::is_selected ("src"))
          {
	    buffer = "macro src \".";
	    buffer += fs;
	    buffer += "\"";
	    apply ();
          }

        if (!Symbol::is_selected ("inc"))
          {
	    buffer = "macro inc \".";
	    buffer += fs;
	    buffer += "\"";
	    apply ();
          }

        if (!Symbol::is_selected ("doc"))
          {
	    buffer = "macro doc \".";
	    buffer += fs;
	    buffer += "\"";
	    apply ();
          }

        if (!Symbol::is_selected ("bin"))
          {
	    buffer = "macro bin \".";
	    buffer += fs;
	    buffer += "\"";
	    apply ();
	  }

        if (!Symbol::is_selected ("javabin"))
          {
	    buffer = "macro javabin \".";
	    buffer += fs;
	    buffer += "\"";
	    apply ();
          }

        if (!Symbol::is_selected ("mgr"))
          {
	    buffer = "macro mgr \".";
	    buffer += fs;
	    buffer += "\"";
	    apply ();
          }

        if (!Symbol::is_selected ("BIN"))
          {
	    /*
	    buffer = "macro BIN \"";
	    buffer += pwd;
	    buffer += fs;
	    buffer += "\"";
	    apply ();
	    */
	    cmt_string temp = "$(bin)";
	    Symbol::expand (temp);
	    int len (temp.size());
	    cmt_string atemp;
	    if (CmtSystem::absolute_path (temp))
	      {
		CmtSystem::compress_path (temp, atemp);
	      }
	    else
	      {
		atemp = "$(PACKAGE_ROOT)";
		Symbol::expand (atemp);
		atemp += fs + temp;
		//atemp = pwd + fs + temp;
		CmtSystem::compress_path (atemp);
	      }
	    buffer = "macro BIN \"";
	    buffer += atemp;
	    buffer += "\"";
	    apply ();
	    if (0 != len && fs != temp[len - 1])
	      {
		buffer = "macro_append bin \"";
		buffer += fs;
		buffer += "\"";
		apply ();

		buffer = "macro_append BIN \"";
		buffer += fs;
		buffer += "\"";
		apply ();
	      }
	  }
      }
    else
      {
        if (!Symbol::is_selected ("srcdir"))
          {
            buffer = "macro srcdir \"..";
            buffer += fs;
            buffer += "src";
            buffer += "\"";
            apply ();
          }
        
        if (!Symbol::is_selected ("src"))
          {
            buffer = "macro src \"..";
            buffer += fs;
            buffer += "src";
            buffer += fs;
            buffer += "\"";
            apply ();
          }
        
        if (!Symbol::is_selected ("inc"))
          {
            buffer = "macro inc \"..";
            buffer += fs;
            buffer += "src";
            buffer += fs;
            buffer += "\"";
            apply ();
          }
        
        if (!Symbol::is_selected ("doc"))
          {
            buffer = "macro doc \"..";
            buffer += fs;
            buffer += "doc";
            buffer += fs;
            buffer += "\"";
            apply ();
          }
        
        if (!Symbol::is_selected ("bin"))
          {
            cmt_string package_tag = current_package;
            package_tag += "_tag";

            buffer = "macro bin \"..";
            buffer += fs;
            buffer += "$(";
            buffer += package_tag;
            buffer += ")";
            buffer += fs;
            buffer += "\"";
            apply ();
          }

        if (!Symbol::is_selected ("javabin"))
          {
            buffer = "macro javabin \"..";
            buffer += fs;
            buffer += "classes";
            buffer += fs;
            buffer += "\"";
            apply ();
          }
        
        if (current_style == mgr_style)
          {
            buffer = "macro mgrdir \"mgr\"";
            apply ();

            buffer = "macro mgr \"..";
            buffer += fs;
            buffer += "mgr";
            buffer += fs;
            buffer += "\"";
            apply ();
          }
        else
          {
            buffer = "macro mgrdir \"cmt\"";
            apply ();

            buffer = "macro mgr \"..";
            buffer += fs;
            buffer += "cmt";
            buffer += fs;
            buffer += "\"";
            apply ();
          }

        if (!Symbol::is_selected ("BIN"))
          {
	    /*
	    cmt_string pardir;
	    CmtSystem::dirname (pwd, pardir);
	    //            buffer = "macro BIN \"$(PACKAGE_ROOT)";
            buffer = "macro BIN \"";
            buffer += pardir;
            buffer += fs;
            buffer += "$(";
            buffer += package_tag;
            buffer += ")";
            buffer += fs;
            buffer += "\"";
            apply ();
	    */
	    cmt_string temp = "$(bin)";
	    Symbol::expand (temp);
	    int len (temp.size());
	    cmt_string atemp;
	    if (CmtSystem::absolute_path (temp))
	      {
		CmtSystem::compress_path (temp, atemp);
	      }
	    else
	      {
		atemp = "$(PACKAGE_ROOT)";
		atemp += fs + "$(mgrdir)";
		Symbol::expand (atemp);
		atemp += fs + temp;
		//atemp = pwd + fs + temp;
		CmtSystem::compress_path (atemp);
	      }
	    buffer = "macro BIN \"";
	    buffer += atemp;
	    buffer += "\"";
	    apply ();
	    if (0 != len && fs != temp[len - 1])
	      {
		buffer = "macro_append bin \"";
		buffer += fs;
		buffer += "\"";
		apply ();

		buffer = "macro_append BIN \"";
		buffer += fs;
		buffer += "\"";
		apply ();
	      }
	  }

	Cmt::configure_current_cmtpath ();
      }
  }

  /**
   *   project
   */
  void fill_for_project ()
  {
    if (current_style == none_style) return;

    cmt_string project_name;
    Project* project = Project::get_current ();
    if (project != 0)
      {
	project_name = project->get_name ();
      }

    buffer = "macro project \"";
    buffer += project_name;
    buffer += "\"";
    apply ();
  }

  /**
   *   use_requirements
   */
  void fill_for_use_requirements ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_requirements"))
      {
        buffer  = "macro use_requirements \"";
        buffer += "requirements ";
        
        for (int number = 0; number < Uses.size (); number++)
          {
            Use* use = Uses[number];
            
            if (use->discarded) continue;
            if (use->m_hidden) continue;
            
            if (use->located ())
              {
                buffer += "$(";
                buffer += use->get_package_name ();
                buffer += "_root)";
//                 buffer += use->prefix;
//                 buffer += "ROOT)";
                
                if (use->style == cmt_style)
		  {
		    buffer += fs;
		    buffer += "cmt";
		  }
                else if (use->style == mgr_style)
		  {
		    buffer += fs;
		    buffer += "mgr";
		  }
		//                else buffer += "cmt";
                
                buffer += fs;
                buffer += "requirements ";
              }
          }
        
        buffer += "\"";
        
        apply ();
      }
  }

  /**
   *   use_includes
   */
  void fill_for_use_includes ()
  {
    Include::parse_all (&(Use::current()));

    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_includes"))
      {
        buffer = "macro_append use_includes \' ";
        
        for (int number = 0; number < Uses.size (); number++)
          {
            Use* use = Uses[number];
            
            if (use->discarded) continue;
            if (use->m_hidden) continue;

	    Package* p = use->get_package ();
	    if (p->is_cmt ()) continue;

            if (Cmt::get_debug ())
              {
                cout << "fill use_includes for " << use->get_package_name () 
                     << " discarded=" << use->discarded
                     << " auto_imports=" << use->auto_imports << endl;
              }
            
            if (use->auto_imports == Off) continue;
            
	    Include::parse_all (use);

            use->fill_includes_macro (buffer);
          }
        
        buffer += "\'";
        
        apply ();
      }
  }

  /**
   *   use_fincludes
   */
  void fill_for_use_fincludes ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_fincludes"))
      {
        buffer = "macro_append use_fincludes \" $(use_includes)\"";
        apply ();
      }
  }

  /**
   *   use_stamps
   */
  void fill_for_use_stamps ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_stamps"))
      {
	/*
        buffer = "macro use_stamps \"";
        (Use::current()).fill_macro (buffer, "stamps");
        
        for (int number = 0; number < Uses.size (); number++)
          {
            Use* use = Uses[number];
            
            if (use->discarded) continue;
            if (use->m_hidden) continue;

	    Package* p = use->get_package ();
	    if (p->is_cmt ()) continue;
            
            use->fill_macro (buffer, "stamps");
          }
        
        buffer += "\"";
	*/
        Use::fill_macro_all (buffer, "stamps");
        apply ();
      }
  }

  /**
   *   use_cflags
   */
  void fill_for_use_cflags ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_cflags"))
      {
        Use::fill_macro_all (buffer, "cflags");
        apply ();
      }
  }

  /**
   *   use_pp_cflags
   */
  void fill_for_use_pp_cflags ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_pp_cflags"))
      {
        Use::fill_macro_all (buffer, "pp_cflags");
        apply ();
      }
  }

  /**
   *   use_cppflags
   */
  void fill_for_use_cppflags ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_cppflags"))
      {
        Use::fill_macro_all (buffer, "cppflags");
        apply ();
      }
  }

  /**
   *   use_pp_cppflags
   */
  void fill_for_use_pp_cppflags ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_pp_cppflags"))
      {
        Use::fill_macro_all (buffer, "pp_cppflags");
        apply ();
      }
  }

  /**
   *   use_fflags
   */
  void fill_for_use_fflags ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_fflags"))
      {
        Use::fill_macro_all (buffer, "fflags");
        apply ();
      }
  }

  /**
   *   use_pp_fflags
   */
  void fill_for_use_pp_fflags ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_pp_fflags"))
      {
        Use::fill_macro_all (buffer, "pp_fflags");
        apply ();
      }
  }

  /**
   *   use_linkopts
   */
  void fill_for_use_linkopts ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_linkopts"))
      {
        Use::fill_macro_all (buffer, "linkopts");
        apply ();
      }
  }

  /**
   *   use_libraries
   */
  void fill_for_use_libraries ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("use_libraries"))
      {
        buffer  = "macro use_libraries \"";

        for (int number = 0; number < Uses.size (); number++)
          {
            Use* use = Uses[number];
            
            if (use->discarded) continue;
            if (use->m_hidden) continue;
            
	    Package* p = use->get_package ();
	    if (p->is_cmt ()) continue;

            use->fill_macro (buffer, "libraries");
          }
        
        buffer += "\"";

        apply ();
      }
  }

  /**
   *   includes
   */
  void fill_for_includes ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("includes"))
      {
        buffer = "macro_append includes \' ";

        Use& use = Use::current();

        if (use.include_path == "")
          {
            buffer += "$(ppcmd)\"$(srcdir)\" ";
          }
        else if (use.include_path != "none")
          {
            buffer += "$(ppcmd)\"";
            buffer += use.include_path;
            buffer += "\" ";
          }

        for (int include_number = 0;
             include_number < use.includes.size ();
             include_number++)
          {
            Include& incl = use.includes[include_number];

            if (incl.name == "") continue;

            buffer += "$(ppcmd)\"";
            buffer += incl.name;
            buffer += "\" ";
          }
        
        buffer += "$(use_includes)\'";
        
        apply ();
      }
  }

  /**
   *   fincludes
   */
  void fill_for_fincludes ()
  {
    Use::UsePtrVector& Uses = Use::get_ordered_uses ();

    if (Uses.size () == 0) return;

    if (!Symbol::is_selected ("fincludes"))
      {
        buffer = "macro_append fincludes \" $(includes)\"";
        apply ();
      }
  }

  /**
   *  Macros specific to constituents.
   *  This includes the compiler flags
   *  and fills in these macros from uses packages. This takes care
   *  of -no_auto_imports and -import= directives
   *
   *    <constituent>_use_linkopts
   *    <prefix>_<constituent>_cflags
   *    <prefix>_<constituent>_pp_cflags
   *    <prefix>_<constituent>_cppflags
   *    <prefix>_<constituent>_pp_cppflags
   *    <prefix>_<constituent>_fflags
   *    <prefix>_<constituent>_pp_fflags
   *    <constituent>linkopts
   *    <constituent>_GUID
   *    <constituent>_stamps
   *
   */
  void fill_for_all_constituents ()
  {
    /// First, finish the parsing of constituent parameters.
    if (Cmt::get_debug ())
      {
	cout << "fill_for_all_constituents>" << endl;
      }

    Constituent::parse_all ();

    Use::UsePtrVector& Uses = Use::get_ordered_uses ();
    
    const Constituent::ConstituentVector& constituents =
      Constituent::constituents ();

  
    // Prepare the auto_imports states in a vector
    cmt_vector<bool> base_auto_imports_states;

    base_auto_imports_states.resize (Uses.size ());

    int number;
    
    for (number = 0; number < Uses.size (); number++)
      {
	Use* use = Uses[number];
	base_auto_imports_states[number] = (use->auto_imports != Off);
      }
    
    // Now scan all constituents
	
    for (number = 0; number < constituents.size (); number++)
      {
	const Constituent& constituent = constituents[number];
	
	//==== GLAST addition for vs.net ==========
	buffer = "macro ";
	buffer += constituent.name;
	buffer += "_GUID \"{88BF15AB-5A2D-4bea-B64F-02752C2A1F4F}\" ";
	apply ();
	
	if (Cmt::get_debug ())
	  {
	    cout << "Checking " << constituent.name  << " against imports requests" << endl;
	  }
	Use::UsePtrVector imports;
	int i;
	
	/**
	 *  Problem for imports in constituents.
	 *
	 *     1) use_xxx has holes due to the corresponding 
	 *         -no_auto_imports options attached to some
	 *        use statements (including the transitive ones)
	 *
	 *     2) the -import=yyy options provided to a given constituent
	 *        should restore the appropriate holes as well as
	 *        all transitive ones.
	 *
	 *     3) for use_linkopts, missing pieces must be filled at
	 *        the right position. (for others, order is not relevant
	 *        while transitive access is required for all)
	 *
	 */
	
	if (constituent.type == Document)
	  { 
	    continue;
	  }
	
	if (constituent.imports.size () == 0) 
	  {
	    buffer = "macro_append ";
	    buffer += constituent.name;
	    buffer += "_use_linkopts ";
	    buffer += " \" ";
	    
	    current_use->fill_macro (buffer, "linkopts");
	    
	    for (i = 0; i < Uses.size (); i++)
	      {
		if (base_auto_imports_states[i])
		  {
		    Use* u = Uses[i];
		    
		    if (u->discarded) continue;
		    if (u->m_hidden) continue;
		    
		    Package* p = u->get_package ();
		    if (p->is_cmt ()) continue;
                    
		    u->fill_macro (buffer, "linkopts");
		  }
	      }
	    buffer += "\"";
	    apply ();
	    
	    /*
	      buffer = "macro_append ";
	      buffer += constituent.name;
	      buffer += "_use_linkopts ";
	      
	      buffer += " \" $(use_linkopts)\"";
	      apply ();
	    */
	    
	    continue;
	  }
	
	// From here on, the constituent HAS import options. 
	
	/**
	 * Create a private copy of the state vector. This private copy
	 * will be updated according to -import=xxx modifiers for the
	 * current constituent.
	 */
	cmt_vector<bool> auto_imports_states (base_auto_imports_states);
	Use::UsePtrVector uses;

	for (i = 0; i < constituent.imports.size (); i++)
	  {
	    const cmt_string& import = constituent.imports[i];
            
	    //
	    // Resolve the imported uses
	    //
	    
	    int use_index = Use::find_index (import, "", "");
	    
	    if (use_index >= 0)
	      {
		Use* u = Uses[use_index];
		
		if (u->discarded) continue;
		if (u->m_hidden) continue;
                
		if (Cmt::get_debug ())
		  {
		    cout << constituent.name  << " has import request " << import
			 << " i=" << use_index << " package=" 
			 << u->get_package()->get_name()
			 << " auto_imports=" << u->auto_imports
			 << " (Off=" << Off
			 << " On=" << On << ")"
			 << endl;
		  }
		
		Package* p = u->get_package ();
		if (p->is_cmt ()) continue;
		
		uses.push_back (u);
		//u->set_auto_imports_state (auto_imports_states, visited);
		//if (u->auto_imports != Off) continue;
		//Use::set_auto_imports_state (use_index, auto_imports_states);
	      }
	    else
	      {
		if ((!constituent.has_target_tag &&
		     Me.m_action == action_build_constituents_config)
		    ||
		    (constituent.has_target_tag &&
		     Me.m_action == action_build_constituent_config))
		  CmtMessage::warning
		    (CmtError::get_error_name (CmtError::configuration_error)
		     + ": package " + import
		     + " cannot be imported (requested for "
		     + (constituent.type == Application ?
			"application " : "library ")
		     + constituent.name +")");
		
		if (Cmt::get_debug ())
		  {
		    cout << "import [" << i << "] "
			 << ("package " + import +
			     " cannot be imported (requested for " +
			     (constituent.type == Application ?
			      "application " : "library ") +
			     constituent.name +")")  << endl;
		  }
	      }
	  }

	/*
	cmt_map <Use*, bool> visited;
	static bool yes (true);
	visited.add (&(Use::current()), yes);
	Use::set_auto_imports_state (uses, auto_imports_states, visited);
	*/	
	Use::set_auto_imports_state (uses, auto_imports_states);

	/**
	 *   Find all newly exposed packages and precompute this list inside
	 *   a vector.
	 */
	for (i = 0; i < base_auto_imports_states.size (); i++)
	  {
	    //	    if (base_auto_imports_states[i]== On && auto_imports_states[i] == Off) continue;
	    if (base_auto_imports_states[i] || !auto_imports_states[i]) continue;
	    //if (base_auto_imports_states[i] == On || auto_imports_states[i] == Off) continue;
	    /**
	     *  Consider the package (i) for import only if it is:
	     *   o not imported yet (i.e., base_auto_imports_states[i] != true)
	     *   o requested for import according to -import=xxx modifiers for
	     *     the current constituent (i.e., auto_imports_states[i] != false)
	     */
	    Use* u = Uses[i];
	    
	    if (u->discarded) continue;
	    if (u->m_hidden)  continue;
	    
	    Package* p = u->get_package ();
	    if (p->is_cmt ()) continue;

	    imports.push_back (u);
	  }
        
	if (Cmt::get_debug ())
	  {
	    if (imports.size () == 0)
	      {
		cout << constituent.name  << " needs no imports" << endl;
	      }
	    else
	      {
		cout << constituent.name  << " has imports" << endl;
		for (int i = 0; i < imports.size (); i++)
		  {
		    cout << constituent.name  << " has import "
			 << imports[i]->get_package_name () << endl;
		  }
	      }
	  }

	/**
	 *  Only for linkopts we take care of the order. This means
	 *  that ${CONSTITUENT}_use_linkopts should be used in place of use_linkopts.
	 *
	 *  (see the application fragments)
	 *  that ${CONSTITUENT}_use_linkopts will be used in place of use_linkopts.
	 */
	buffer = "macro_append ";
	buffer += constituent.name;
	buffer += "_use_linkopts ";
	buffer += " \" ";
	
	current_use->fill_macro (buffer, "linkopts");
	
	for (i = 0; i < Uses.size (); i++)
	  {
	    if (auto_imports_states[i])
	      {
		Use* u = Uses[i];
		
		if (u->discarded) continue;
		if (u->m_hidden) continue;
		
		Package* p = u->get_package ();
		if (p->is_cmt ()) continue;
		
		u->fill_macro (buffer, "linkopts");
	      }
	  }
	buffer += "\"";
	apply ();
	
	if (imports.size () == 0) continue;
	
	cmt_string prefix;
	
	//
	// Documents are not considered 
	//
	switch (constituent.type)
	  {
	  case Application:
	    prefix = "app_";
	    break;
	  case Library:
	    prefix = "lib_";
	    break;
	  }
	
	buffer = "macro_append ";
	buffer += prefix;
	buffer += constituent.name;
	buffer += "_cflags ";
	buffer += " \' ";
	for (i = 0; i < imports.size (); i++)
	  {
	    Use* u = imports[i];
	    
	    u->fill_includes_macro (buffer);
	    u->fill_macro (buffer, "cflags");
	  }
	buffer += "\'";
	apply ();
	
	buffer = "macro_append ";
	buffer += prefix;
	buffer += constituent.name;
	buffer += "_pp_cflags ";
	buffer += " \" ";
	for (i = 0; i < imports.size (); i++)
	  {
	    Use* u = imports[i];
	    
	    u->fill_macro (buffer, "pp_cflags");
	  }
	buffer += "\"";
	apply ();
	
	buffer = "macro_append ";
	buffer += prefix;
	buffer += constituent.name;
	buffer += "_cppflags ";
	buffer += " \' ";
	for (i = 0; i < imports.size (); i++)
	  {
	    Use* u = imports[i];
	    
	    u->fill_includes_macro (buffer);
	    u->fill_macro (buffer, "cppflags");
	  }
	buffer += "\'";
	apply ();
	
	buffer = "macro_append ";
	buffer += prefix;
	buffer += constituent.name;
	buffer += "_pp_cppflags ";
	buffer += " \" ";
	for (i = 0; i < imports.size (); i++)
	  {
	    Use* u = imports[i];
	    
	    u->fill_macro (buffer, "pp_cppflags");
	  }
	buffer += "\"";
	apply ();
	
	buffer = "macro_append ";
	buffer += prefix;
	buffer += constituent.name;
	buffer += "_fflags ";
	buffer += " \' ";
	for (i = 0; i < imports.size (); i++)
	  {
	    Use* u = imports[i];
	    
	    u->fill_includes_macro (buffer);
	    u->fill_macro (buffer, "fflags");
	  }
	buffer += "\'";
	apply ();
	
	buffer = "macro_append ";
	buffer += prefix;
	buffer += constituent.name;
	buffer += "_pp_fflags ";
	buffer += " \" ";
	for (i = 0; i < imports.size (); i++)
	  {
	    Use* u = imports[i];
	    
	    u->fill_macro (buffer, "pp_fflags");
	  }
	buffer += "\"";
	apply ();

	buffer = "macro_append ";
	buffer += constituent.name;
	buffer += "_stamps ";
	buffer += " \" ";
	for (i = 0; i < imports.size (); i++)
	  {
	    Use* u = imports[i];
	    
	    u->fill_macro (buffer, "stamps");
	  }
	buffer += "\"";
	apply ();

	/**
	 *  Setting ${CONSTITUENT}linkopts is a temporary solution
	 *  until the backward compatibility solution for a proper 
	 *  replacement of use_linkopts by ${CONSTITUENT}_use_linkopts
	 *  is acheived.
	 *
	 */
	/**
	buffer = "macro_append ";
	buffer += constituent.name;
	buffer += "linkopts ";
	buffer += " \" ";
	for (i = 0; i < imports.size (); i++)
	  {
	    Use* u = imports[i];
	    
	    u->fill_macro (buffer, "linkopts");
	  }
	buffer += "\"";
	apply ();
	*/
      }
  }
  
  /**
   *   Macros implied or required to manage constituents.
   */
  void fill_for_constituent_macros ()
  {
    int number;
    cmt_string temp;

    const Constituent::ConstituentVector& constituents = Constituent::constituents ();
  
    if (!Symbol::is_selected ("constituents"))
      {
	temp = "macro_append constituents \" ";
	
	for (number = 0; number < constituents.size (); number++)
	  {
	    const Constituent& constituent = constituents[number];
	    
	    if (constituent.group == 0)
	      {
		temp += constituent.name;
		temp += " ";
	      }
	  }
	
	temp += "\"";
	
	SyntaxParser::parse_requirements_line (temp, current_use);
      }
    
    SyntaxParser::parse_requirements_line ("macro_append all_constituents \" $(constituents)\"", 
					   current_use);
    
    if (!Symbol::is_selected ("constituentsclean"))
      {
	temp = "macro_append constituentsclean \" ";
	
	for (number = constituents.size () - 1; number >= 0 ; number--)
	  {
	    const Constituent& constituent = constituents[number];
	    
	    if (constituent.group == 0)
	      {
		temp += constituent.name;
		temp += "clean ";
	      }
	  }
	
	temp += "\"";
	
	SyntaxParser::parse_requirements_line (temp, current_use);
      }
    
    SyntaxParser::parse_requirements_line ("macro_append all_constituentsclean \" $(constituentsclean)\"", 
					   current_use);
    
    const Group::GroupVector& groups = Group::groups ();
    
    for (number = 0; number < groups.size (); number++)
      {
	const Group& group = groups[number];
	
	temp = "macro_append ";
	temp += group.name ();
	temp += "_constituents \" ";
	
	int i;
	
	for (i = 0; i < constituents.size (); i++)
	  {
	    const Constituent& constituent = constituents[i];
	    
	    if ((constituent.group != 0) && 
		(group.name () == constituent.group->name ()))
	      {
		temp += constituent.name;
		temp += " ";
	      }
	  }
	
	temp += "\"";
	
	SyntaxParser::parse_requirements_line (temp, current_use);
	
	temp = "macro_append ";
	temp += group.name ();
	temp += "_constituentsclean \" ";
	
	for (i = constituents.size () - 1; i >= 0 ; i--)
	  {
	    const Constituent& constituent = constituents[i];
	    
	    if ((constituent.group != 0) && 
		(group.name () == constituent.group->name ()))
	      {
		temp += constituent.name;
		temp += "clean ";
	      }
	  }
	
	temp += "\"";
	
	SyntaxParser::parse_requirements_line (temp, current_use);
      }
  }

  /**
   *  Definitions for installation area mechanisms. Apply all cmtpath patterns
   */
  void fill_for_install_area ()
  {
    CmtPathPattern::apply_all ();

    const Use& current_use = Use::current ();

    if (current_use.get_strategy ("InstallArea"))
      {
	CmtInstallAreaMgr& ia_mgr = CmtInstallAreaMgr::instance ();
	
	ia_mgr.setup ();
      }
  }

  /**
   * Macros to be defined once current_package is known
   * and even before reading its requirements file.
   */
  void fill_for_current_package ()
  {
    fill_for_tag ();
    fill_for_package ();
  }

private:
  cmt_string fs;
  cmt_string buffer;
  //CmtSystem::cmt_string_vector vb;
  //cmt_string pwd;
  Use* current_use;
  cmt_string current_tag; 
  cmt_string current_package; 
  cmt_string current_version; 
  cmt_string current_prefix; 
  CmtDirStyle current_style;
};

//----------------------------------------------------------
void Cmt::set_current_access (AccessMode mode)
{
  Me.m_current_access = mode;
}

//----------------------------------------------------------
void Cmt::set_recursive (bool mode)
{
  Me.m_recursive = mode;
}

//----------------------------------------------------------
void Cmt::set_scope_filtering_mode (CmtScopeFilteringMode mode)
{
  Me.m_scope_filtering_mode = mode;
}

//----------------------------------------------------------
void Cmt::set_standard_macros ()
{
  if (Me.m_standard_macros_done) return;

  Me.m_standard_macros_done = true;

  //  Use::UsePtrVector& Uses = Use::get_ordered_uses ();
  Use& current_use = Use::current ();

  cmt_string fs = CmtSystem::file_separator ();

  cmt_string pwd = CmtSystem::pwd ();

  /**
   * This is a check for package names
   */
  if (CmtMessage::active (Verbose))
    {
      Use::UsePtrVector uses (Use::get_ordered_uses ());
      uses.push_back (&current_use);
      for (int i = uses.size () - 1; i >= 0; i--)
	{
	  Use* use = uses[i];
	  if (use->discarded) continue;
	  if (use->m_hidden) continue;
	  if (!use->located ()) continue;
	  for (int j = i - 1; j >= 0; j--)
	    {
	      Use* use2 = uses[j];
	      if (use2->discarded) continue;
	      if (use2->m_hidden) continue;
	      if (!use2->located ()) continue;
	      if (use->prefix == use2->prefix)
		{
		  CmtMessage::warning (use->prefix + "ROOT, "
				       + use->prefix + "VERSION ill-defined: "
				       + use->get_package_name () + " and "
				       + use2->get_package_name ()
				       + " package name conflict");
		}
	    }
	}
    }
  /**
   * This is already done in
   void Cmt::configure_current_package ()

  if (CmtSystem::test_file ("../cmt/requirements")) Me.m_current_style = cmt_style;
  else if (CmtSystem::test_file ("../mgr/requirements")) Me.m_current_style = mgr_style;
  else Me.m_current_style = none_style;

  {
    cmt_string v;
    CmtSystem::dirname (pwd, v);
    CmtSystem::basename (v, v);
    if (!CmtSystem::is_version_directory (v))
      {
        Me.m_current_style = no_version_style;
      }
  }
  */

  // Prepare computation of the best form for relative path from current directory
  // to package directories.
  CmtSystem::cmt_string_vector vb;
  CmtSystem::split (pwd, fs, vb);


  /**
   *    TAG management
   */

  static bool tag_debug = CmtSystem::testenv ("TAGDEBUG");

  if (tag_debug) cerr << "set_standard_macro0> current_tag=" << Me.m_current_tag << endl;

  if (Me.m_current_tag != "")
    {
      // this is when some -tag= argument was used.
      if (tag_debug) cerr << "set_standard_macro0.1> current_tag=" << Me.m_current_tag << endl;
    }
  else if (Symbol::is_selected ("CMTCONFIG"))
    {
      // This is when CMTCONFIG has been set from some requirements file
      Symbol* macro = Symbol::find ("CMTCONFIG");
      if (macro != 0)
        {
          Me.m_current_tag = macro->build_macro_value ();
          if (tag_debug) cerr << "set_standard_macro1> current_tag=" << Me.m_current_tag << endl;
        }
    }
  else
    {
      // this is when no -tag= argument was used.
      if (tag_debug) cerr << "set_standard_macro(before2)> current_tag=" << Me.m_current_tag << endl;
      if (current_use.get_package_name () == "CMT")
        {
          Me.m_current_tag = CmtSystem::getenv ("CMTBIN");
        }
      else
        {
          Me.m_current_tag = CmtSystem::getenv ("CMTCONFIG");
        }

      if (tag_debug) cerr << "set_standard_macro2> current_tag=" << Me.m_current_tag << endl;
    }

  if (Me.m_debug)
    {
      cout << "set_standard_macro3>" << endl;
    }

  StandardMacroBuilder builder (Me.m_current_tag,
                                current_use.get_package_name (),//Me.m_current_package,
                                current_use.version,//Me.m_current_version,
                                current_use.prefix,//Me.m_current_prefix,
                                current_use.style);//Me.m_current_style);

  builder.fill_for_current_package ();

  builder.fill_for_branches ();
  builder.fill_for_project ();

  builder.fill_for_install_area ();

  builder.fill_for_use_requirements ();
  builder.fill_for_use_includes ();
  builder.fill_for_use_fincludes ();
  builder.fill_for_use_stamps ();
  builder.fill_for_use_cflags ();
  builder.fill_for_use_pp_cflags ();
  builder.fill_for_use_cppflags ();
  builder.fill_for_use_pp_cppflags ();
  builder.fill_for_use_fflags ();
  builder.fill_for_use_pp_fflags ();
  builder.fill_for_use_linkopts ();
  builder.fill_for_use_libraries ();
  builder.fill_for_includes ();
  builder.fill_for_fincludes ();
  builder.fill_for_all_constituents ();
  builder.fill_for_constituent_macros ();
}

void Cmt::set_all_sets_done ()
{
  Me.m_all_sets_done = true;
}

void Cmt::reset_all_sets_done ()
{
  Me.m_all_sets_done = false;
}

//----------------------------------------------------------
void Cmt::use_cmt ()
{
  UseRef use;
  bool recursive_copy = Me.m_recursive;
  bool debug_copy = Me.m_debug;

  if (Me.m_default_path.size () <= 0) return;
  if (Me.m_current_package == "CMT") return;

  Me.m_recursive = true;
  //Me.m_debug = false;
  use = Use::add (Me.m_default_path, "CMT", Me.m_cmt_version, "", "", "", 0);
  Me.m_recursive = recursive_copy;
  Me.m_debug = debug_copy;
}

//----------------------------------------------------------
void Cmt::use_home_requirements ()
{
  use_special_requirements (Me.m_cmt_home, 
			    CmtSystem::get_home_package (), 
			    "requirements");
}

//----------------------------------------------------------
void Cmt::use_user_context_requirements ()
{
  use_special_requirements (Me.m_cmt_user_context, 
			    CmtSystem::get_user_context_package (), 
			    "requirements");
}

//----------------------------------------------------------
void Cmt::use_special_requirements (const cmt_string& path, 
				    const cmt_string& name, 
				    const cmt_string& file_name)
{
  if (path == "") 
    {
      return;
    }

  UseRef use;
  bool recursive_copy = Me.m_recursive;

  if (Me.m_default_path.size () <= 0) return;
  if (Me.m_current_package == "CMT") return;

  Me.m_recursive = true;

  use = Use::add (path, name, "v0", "", "", "", 0);

  cmt_string f = path;
  f += CmtSystem::file_separator ();
  f += file_name;
  if (CmtSystem::test_file (f))
    {
      use->m_located = true;
    }
  SyntaxParser::parse_requirements (f, use);

  Me.m_recursive = recursive_copy;
}

//-------------------------------------------------
void Cmt::vector_to_string (const CmtSystem::cmt_string_vector& v,
                            const cmt_string& separator,
                            cmt_string& result)
{
  result.erase (0);

  for (int i = 0; i < v.size (); i++)
    {
      const cmt_string& s = v[i];
      if (s == "") continue;

      if (result.size () != 0) result += separator;
      //if (i > 0) result += separator;
      result += v[i];
    }
}

//-------------------------------------------------
cmt_string Cmt::vector_to_string (const CmtSystem::cmt_string_vector& v)
{
  cmt_string result;

  vector_to_string (v, " ", result);

  return (result);
}
