//-----------------------------------------------------------
// Copyright Christian Arnault LAL-Orsay CNRS
// arnault@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_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_current_dir     = "";
  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_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);
};


/**
 *  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);
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);
  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)
{
  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)
{
  //
  // 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)
{
  cmt_string dir = path;
  dir += CmtSystem::file_separator ();
  dir += package;
  dir += CmtSystem::file_separator ();
  if (version != "")
    {
      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) && 
                  ((words[2] == m_version) || (m_version == "")))
                {
                  cout << "# " << package << " " << version << " " << path;
                  if (m_version == "")
                    {
                      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.clear ();

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

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

  if (configured) return;

  Me.clear ();

  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_home" << log_endl;
  // CMTHOME, CMTUSERCONTEXT and CMTPATH
  configure_home (0);
  log << "configure_current_dir" << log_endl;


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


  configure_current_dir ();

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

  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.change_path (Me.m_current_path);

  guess_current_project ();

  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;

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

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

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

      if (show_set_hidden)
        {
          show_set_hidden = false;
          Me.m_action = action_show_set;
        }
    }
  else
    {
      s = CmtSystem::getenv ("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 ();
    }
}

//----------------------------------------------------------
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)
  {
    //cout << "line=" << line << endl;

    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 ();
}

//----------------------------------------------------------
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 version_file = "..";
      version_file += CmtSystem::file_separator ();
      version_file += "cmt";
      version_file += CmtSystem::file_separator ();
      version_file += "version.cmt";

      if (CmtSystem::test_file (version_file))
	{
	  // 
	  // 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*";
	    }

	  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_style = no_version_style;
	}
      else if (CmtSystem::is_version_directory (up_branch))
        {
	  // The up branch IS a version directory.

	  Me.m_current_version = up_branch;
          CmtSystem::dirname (up_dir, up_dir);
          CmtSystem::basename (up_dir, Me.m_current_package);
          CmtSystem::dirname (up_dir, Me.m_current_path);
        }
      else
        {
	  // No version descriptor
	  // No version directory. The version is defaulted to v*
 
          CmtSystem::basename (up_dir, Me.m_current_package);
          Me.m_current_version = "v*";
          CmtSystem::dirname (up_dir, Me.m_current_path);

          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 = "";
      Me.m_current_path = Me.m_current_dir;
      build_prefix (Me.m_current_package, Me.m_current_prefix);
      build_config (Me.m_current_prefix, Me.m_current_config);
      Me.m_current_style = none_style;
    }

  //cout << "configure_current_package> current style=" << Me.m_current_style << endl;
}

//----------------------------------------------------------
void Cmt::configure_current_structuring_style ()
{
  cmt_string s;

  s = CmtSystem::getenv ("CMTSTRUCTURINGSTYLE");
  if (s == "without_version_directory")
    {
      Me.m_current_structuring_style = without_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 ();
    }
}

//----------------------------------------------------------
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";

      if (use != 0)
        {
          s += " in ";
        }

      Tag* tag;

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

//----------------------------------------------------------
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";

      if (use != 0)
        {
          s += " in ";
        }

      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 ();
        }
    }
}

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

  Log;

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

  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);
    }

  //if (Me.m_debug) cout << "configure_tags> current_tag=" << Me.m_current_tag << endl;
  log << "current_tag=" << Me.m_current_tag << log_endl;

  cmt_string s = "CMTCONFIG";

  if (use != 0)
    {
      s += " in ";
    }

  Tag* tag;

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

    //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 ();
    }
}

//----------------------------------------------------------
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 ();

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

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

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

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

}

//----------------------------------------------------------
//
//   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)
    {
      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;

  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->located ())
            {
              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 ();

                  //cout << ">>> adding " << s << " to selection" << endl;
                }
            }
        }
          
      {
        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";
          }

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

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

        //cout << ">>> adding current " << s << " to selection" << endl;
      }
    }

  bool started = false;

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

  set_standard_macros ();
  Cmt::reset_all_sets_done ();
  Symbol::all_set ();

  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;

      if (path_selections.size () > 0)
        {
          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)
            {
              cerr << "#CMT> Currently not in a CMT package" << endl;
            }
          else
            {
              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)
        {
          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);


      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);
              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;
    }
  if (ap.arguments.size () > 0) 
    {
      set_standard_macros ();
      Generator::build_constituent_makefile (ap.arguments[0]);
    }
}

//----------------------------------------------------------
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 ();

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

//----------------------------------------------------------
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) 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 ();

      //cout << "#IA2>" << endl;
      
      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->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]);
    }
}

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

  static CmtSystem::cmt_string_vector tags;

  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)) 
	{
	  cerr << "#CMT> The tag " << t << " is not used in any tag expression. Please check spelling" << endl;
	}
    }

  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)) 
    {
      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)
{
  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 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"))
        {
          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_test_setup_scripts ();
          install_test_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)?$");

  CmtSystem::scan_dir (".", expression, makes);

  if (makes.size () > 0)
    {
      cout << "Removing all previous make fragments from " << branch << endl;

      for (int i = 0; i < makes.size (); i++)
        {
          const cmt_string& s = makes[i];
          CmtSystem::remove_file (s);
        }
    }

  CmtSystem::cd ("..");

  CmtSystem::scan_dir (Me.m_cmt_config, expression, makes); 
    
  if (makes.size () > 0) 
    {
      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::remove_file (s); 
        }    
    } 

  /*
  // cout << "Try a cleanup of the installation area " << endl;

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

      //cout << "#IA3>" << endl;

      if (current_use.get_strategy ("SetupCleanup"))
	{
	  ia_mgr.config ();
	}
    }
  */

  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;

  //cout << "do_config> current style=" << Me.m_current_style << endl;

  Me.m_quiet = true;

  if (!reach_current_package ())
    {
      cout << "Cannot read the requirements file" << endl;
      return;
    }

  install_setup_scripts ();
  install_cleanup_scripts ();

  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))
            {
              cout << "Cannot create the " << branch_name <<" branch" << endl;
            }
          else
            {
              cout << "Installing the " << branch_name << " directory" << endl;
            }
        }
      else
        {
          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 (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

  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))
        {
          cout << "Cannot create the path directory" << endl;
          return;
        }
      else
        {
          cout << "Installing the path directory" << endl;
        }
    }

  CmtSystem::cd (the_path);

  if (!CmtSystem::test_directory (package))
    {
      if (!CmtSystem::mkdir (package))
        {
          cout << "Cannot create the package directory" << endl;
          return;
        }
      else
        {
          cout << "Installing the package directory" << endl;
        }
    }
  else
    {
      cout << "Package directory already installed" << endl;
    }

  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))
            {
              cout << "Cannot create the version directory" << endl;
              return;
            }
          else
            {
              cout << "Installing the version directory" << endl;
            }
        }
      else
        {
          cout << "Version directory already installed" << endl;
        }

      CmtSystem::cd (version);
    }
  else
    {
      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"))
            {
              cout << "Cannot create the cmt directory" << endl;
              return;
            }
          else
            {
              if (with_version_dir)
                {
                  Me.m_current_style = cmt_style;
                }
              else
                {
                  Me.m_current_style = no_version_style;
                }

              cout << "Installing the cmt directory" << endl;
            }
        }
      else
        {
          if (with_version_dir)
            {
              Me.m_current_style = mgr_style;
            }
          else
            {
              Me.m_current_style = no_version_style;
            }
          
          cout << "Mgr directory already installed" << endl;
        }
    }
  else
    {
      if (with_version_dir)
        {
          Me.m_current_style = cmt_style;
        }
      else
        {
          Me.m_current_style = no_version_style;
        }

      cout << "Cmt directory already installed" << endl;
    }

  if (!CmtSystem::test_directory ("src"))
    {
      if (!CmtSystem::mkdir ("src"))
        {
          cout << "Cannot create the src directory" << endl;
          return;
        }
      else
        {
          cout << "Installing the src directory" << endl;
        }
    }
  else
    {
      cout << "src directory already installed" << endl;
    }

  switch (Me.m_current_style)
    {
    case cmt_style:
    case no_version_style:
      CmtSystem::cd ("cmt");
      break;
    case mgr_style:
      CmtSystem::cd ("mgr");
      break;
    }

  Generator::build_default_makefile ();

  if (!CmtSystem::test_file ("requirements"))
    {
      // create an empty requirement file.
      ofstream f ("requirements");
      if (f)
        {
          f << "package " << package << endl;
          f << endl;
          f.close ();
        }
    }

  if (!with_version_dir)
    {
      ofstream f ("version.cmt");
      if (f)
        {
          f << version << endl;
          f.close ();
        }
    }

  Me.m_current_package = package;
  Me.m_current_version = version;
  Me.m_current_path    = the_path;
  Me.m_current_dir     = CmtSystem::pwd ();

  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);

      cout << "Execute action " << ap.arguments[0] << " => " << cmd << endl;

      CmtSystem::execute (cmd);
    }
}

//----------------------------------------------------------
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))
    {
      cerr << "#CMT> File " << input << " not found" << endl;
      return;
    }

  cmt_string text;

  text.read (input);

  set_standard_macros ();

  Symbol::expand (text);

  FILE* file = fopen (output, "wb");
  if (file == NULL)
    {
      cerr << "#CMT> Cannot write filtered file " << output << endl;
    }
  else
    {
      text.write (file);
      fclose (file);
    }
}

//----------------------------------------------------------
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();

  cout << "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);

  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))
    {
      cout << "Path " << the_path << " not reachable" << endl;
      return;
    }

  if (CmtSystem::test_directory (version))
    {
      if (CmtSystem::remove_directory (version))
        {
          cout << "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))
                {
                  cout << "Package " << package << " has no more versions. Thus it has been removed."<< endl;
                }
            }
        }
      else
        {
          cout << "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");
      if (v == version)
        {
          CmtSystem::cd ("..");
          if (!CmtSystem::remove_directory ("cmt"))
            {
              cout << "Unstructured version " << version
                   << " has been removed from " << the_path << endl;
            }
          else
            {
              cout << "Impossible to remove unstructured version " << version
                   << " from " << the_path << endl;
            }
        }
      else
        {
          cout << "Version " << version << " not found" << endl;
        }
    }
  else
    {
      cout << "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 ();
  int i;
  cmt_string shlibsuffix;
  cmt_string symunlink;

  {
    Symbol* macro = Symbol::find ("shlibsuffix");
    if (macro == 0) return;
    shlibsuffix = macro->build_macro_value ();
    Symbol::expand (shlibsuffix);
  }

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

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

      if (use->discarded) continue;

      if (!use->located ())
        {
          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") continue;
          if (use->get_package_name () == current_use.get_package_name ()) continue;

          cmt_string s;

          s = use->get_package_name ();
          s += "_libraries";

          Symbol* libraries_macro = Symbol::find (s);

          if (libraries_macro == 0) continue;

          cmt_string libraries = libraries_macro->build_macro_value ();
	  Symbol::expand (libraries);

          static CmtSystem::cmt_string_vector values;

          CmtSystem::split (libraries, " \t", values);

          for (int j = 0; j < values.size (); j++)
            {
              const cmt_string& library = values[j];

              static cmt_string libname;
              static cmt_string name;

              // Is it a simple name or a complete path?

              libname = library;
              Symbol::expand (libname);

              if (CmtSystem::absolute_path (libname))
                {
                  /**
                   *   We assume here that "library" contains a complete path.
                   *   (including the complete syntax libxxx.so)
                   */

                  cmt_string suffix;
                  CmtSystem::basename (library, name);
                }
              else
                {
                  /**
                   *   Here we expect that only the base name of the library
                   *   is given : ie it should not contain the "lib" prefix, 
                   *   nor the suffix .so, nor any path prefix.
                   *    This of course should generally correspond to a constituent name.
                   */

                  name = "lib";
                  name += libname;
                  name += ".";
                  name += shlibsuffix;
                }

              Symbol::expand (libname);

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

		  //cout << "#IA4>" << endl;

                  cmt_string s1 = ia_mgr.get_installarea ();

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

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

                    // Now deleting the reference file

                  s = symunlink;
                  s += " ";
                  s += s1;
                  s += CmtSystem::file_separator ();
                  s += s2;
                  s += CmtSystem::file_separator ();
                  s += "lib";
                  s += CmtSystem::file_separator ();
                  s += name;
                  s += ".cmtref";
                  s += " ";
                  s += s1;
                  s += CmtSystem::file_separator ();
                  s += s2;
                  s += CmtSystem::file_separator ();
                  s += "lib";
                  s += CmtSystem::file_separator ();
                  s += name;
                }
              else
                {
                  s = symunlink;
                  s += " ../$(";
                  s += current_use.get_package_name ();
                  s += "_tag)/";
                  s += name;
                }

              Symbol::expand (s);

              if (!Me.m_quiet) cout << s << endl;
              int status = CmtSystem::execute (s);

              if (status != 0)
                {
                  if (status != 2) CmtError::set (CmtError::execution_error, s);

                  cerr << "#CMT> Cannot remove the symbolic link " << s << endl;

                  break;
                }
            }
        }
    }
}

//----------------------------------------------------------
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 += " ";
	}

      CmtSystem::execute (cmd);
    }
}

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

  SequenceRunner runner;

  cout << "# 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) 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))
    {
      cerr << "#CMT> set version " << version << " is not a correct version syntax" << endl;
      return;
    }

  if ((v == -1) || (r == -1) || (p == -1))
    {
      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")
    {
      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)
    {
      cerr << "#CMT> set version " << version << " is already available as a version directory" 
	   << endl;
      return;
    }

  cout << "Writing version file : " << version << endl;

  version.write ("version.cmt");
}

//----------------------------------------------------------
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);

  print (ap.mode);

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

      //cout << "#IA5>" << endl;

      ia_mgr.setup ();

      /*
      if (current_use.get_strategy ("SetupCleanup"))
        {
	  const cmt_string& installarea = ia_mgr.get_installarea ();

	  if (installarea != "")
	    {
	      cmt_string q;
	      
	      switch (mode)
		{
		case Sh :
		case Csh :
		  q = "\'";
		  break;
		default :
		  break;
		}
	      
	      if (!Me.m_quiet)
		{
		  cout << "echo "  << q 
		       << "# Doing cleanup in the installation area " << installarea 
		       << q << endl;
		}
	    }

	  ia_mgr.config ();
        }
      */
    }
}

//----------------------------------------------------------
void Cmt::do_show_action (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 a ";

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

	      CmtError::set (CmtError::warning, t);
	    }
        }
    }

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

  symbol->show_macro (ap.mode);
}

//----------------------------------------------------------
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_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_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 ();

  cout << "# ----------- Clients of " << package <<
    " " << 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 ();
	}
    }
}

//----------------------------------------------------------
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_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*/)
{
  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 ();
}

//----------------------------------------------------------
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 a ";

      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";
		}

	      CmtError::set (CmtError::warning, 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";

	      CmtError::set (CmtError::warning, 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)
{
  cmt_string path_name;

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

  PathScanner scanner;
  PackageViewer viewer;

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

//----------------------------------------------------------
void Cmt::do_show_path (const ArgParser& /*ap*/)
{
  Project::show_paths ();
}

//----------------------------------------------------------
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*/)
{
  Project::show_all ();
}

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

//----------------------------------------------------------
void Cmt::do_show_setup (const ArgParser& ap)
{
  cout << "----------> uses" << endl;
  do_show_uses (ap);

  cout << "----------> tags" << endl;
  do_show_tags (ap);

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

//----------------------------------------------------------
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";
    }

  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*/)
{
  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);
        }
    }
}

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

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

  current->get_all_clients (to_name);
}

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

//----------------------------------------------------------
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();

  cout << "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_package ()
{
  return (Me.m_current_package);
}

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_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);
}

/**---------------------------------------------------------
  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;

  if (Project::find_in_cmt_paths (Me.m_current_dir) == "")
    {
      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);

	      /*
	      cmt_string temp = "path_prepend CMTPATH \"";
	      temp += pwd;
	      temp += "\"";
	      
              Use& use = Use::current();

	      SyntaxParser::parse_requirements_line (temp, &use);
	      */

	      break;
	    }

	  log << "pwd=" << CmtSystem::pwd () << log_endl;
	  
	  if (!CmtSystem::cd (".."))
	    {
	      break;
	    }
	  if (CmtSystem::pwd () == pwd)
	    {
	      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;
}

//----------------------------------------------------------
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& 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_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 cmttempfile=\"%%TEMP%%\\tmpsetup.bat\"\n");
  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 >%%cmttempfile%%\n",
	   action.c_str (),
	   package.c_str (),
	   version.c_str (),
	   no_device.c_str (),
	   option.c_str ());
  fprintf (f, "if exist %%cmttempfile%% call %%cmttempfile%%\n");
  fprintf (f, "if exist %%cmttempfile%% del %%cmttempfile%%\n");
  fprintf (f, "set cmttempfile=\n");
}

//----------------------------------------------------------
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

  cout << "Creating cleanup scripts." << endl;

  cmt_string temp;
  int i;

  cmt_string version = Me.m_current_version;
  if (version == "v*") version = "";

  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 tempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n");
              fprintf (f, "if $status != 0 then\n  set tempfile=/tmp/cmt.$$\nendif\n");
              fprintf (f, "${CMTROOT}/mgr/cmt cleanup -%s "
                       "-pack=%s -version=%s -path=%s $* >${tempfile}; "
                       "source ${tempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str ());
              fprintf (f, "/bin/rm -f ${tempfile}\n");
            }
          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, "tempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n");
              fprintf (f, "if test ! $? = 0 ; then tempfile=/tmp/cmt.$$; fi\n");
              fprintf (f, "${CMTROOT}/mgr/cmt cleanup -%s "
                       "-pack=%s -version=%s -path=%s $* >${tempfile}; "
                       ". ${tempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_package.c_str (),
                       version.c_str (),
                       Me.m_current_path.c_str ());
              fprintf (f, "/bin/rm -f ${tempfile}\n");
            }
          else if (mode[i] == Bat)
            {
	      dos_script_prefix (f, Me.m_cmt_root, 
				 Me.m_current_package, version, Me.m_current_path,
				 "cleanup");
            }

          fprintf (f, "\n");

          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);
        }
    }
}

//----------------------------------------------------------
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

  cout << "Creating setup scripts." << endl;

  Use& current_use = Use::current ();
  
  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 = "";

  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, "\n");
              fprintf (f, "set tempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n");
              fprintf (f, "if $status != 0 then\n  set tempfile=/tmp/cmt.$$\nendif\n");
              fprintf (f, "${CMTROOT}/mgr/cmt setup -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${tempfile}; "
                       "source ${tempfile}\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 ());
              fprintf (f, "/bin/rm -f ${tempfile}\n");
            }
          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, "\n");
              fprintf (f, "tempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n");
              fprintf (f, "if test ! $? = 0 ; then tempfile=/tmp/cmt.$$; fi\n");
              fprintf (f, "${CMTROOT}/mgr/cmt setup -%s "
                       "-pack=%s -version=%s -path=%s %s $* >${tempfile}; "
                       ". ${tempfile}\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 ());
              fprintf (f, "/bin/rm -f ${tempfile}\n");
            }
          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, version, Me.m_current_path,
				 "setup", no_cleanup_opt);
            }

          fprintf (f, "\n");

          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);
        }
    }
}

//----------------------------------------------------------
void Cmt::install_test_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

  cout << "Creating cleanup scripts." << endl;

  cmt_string temp;
  int i;

  cmt_string version = Me.m_current_version;
  if (version == "v*") version = "";

  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 tempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n");
              fprintf (f, "if $status != 0 then\n  set tempfile=/tmp/cmt.$$\nendif\n");
              fprintf (f, "${CMTROOT}/mgr/cmt cleanup -%s -pack=cmt_standalone -path=%s $* >${tempfile}; "
                       "source ${tempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_path.c_str ());
              fprintf (f, "/bin/rm -f ${tempfile}\n");
            }
          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, "tempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n");
              fprintf (f, "if test ! $? = 0 ; then tempfile=/tmp/cmt.$$; fi\n");
              fprintf (f, "${CMTROOT}/mgr/cmt cleanup -%s -pack=cmt_standalone -path=%s $* >${tempfile}; "
                       ". ${tempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_path.c_str ());
              fprintf (f, "/bin/rm -f ${tempfile}\n");
            }
          else
            {
	      dos_script_prefix (f, Me.m_cmt_root, 
				 "cmt_standalone", "", Me.m_current_path, 
				 "cleanup");
            }

          fprintf (f, "\n");

          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);
        }
    }
}

//----------------------------------------------------------
void Cmt::install_test_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

  cout << "Creating setup scripts." << endl;

  Use& current_use = Use::current ();

  cmt_string no_cleanup_opt;

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

  cmt_string temp;
  int i;

  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 standalone package\"\n");
              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 tempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n");
              fprintf (f, "if $status != 0 then\n  set tempfile=/tmp/cmt.$$\nendif\n");
              fprintf (f, "${CMTROOT}/mgr/cmt setup -%s -pack=cmt_standalone -path=%s %s $* >${tempfile}; "
                       "source ${tempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str ());
              fprintf (f, "/bin/rm -f ${tempfile}\n");
            }
          else if (mode[i] == Sh)
            {
              fprintf (f, "# echo \"Setting standalone package\"\n");
              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, "\n");
              fprintf (f, "tempfile=`${CMTROOT}/mgr/cmt -quiet build temporary_name`\n");
              fprintf (f, "if test ! $? = 0 ; then tempfile=/tmp/cmt.$$; fi\n");
              fprintf (f, "${CMTROOT}/mgr/cmt setup -%s -pack=cmt_standalone -path=%s %s $* >${tempfile}; "
                       ". ${tempfile}\n",
                       suffix[i].c_str (),
                       Me.m_current_path.c_str (),
		       no_cleanup_opt.c_str ());
              fprintf (f, "/bin/rm -f ${tempfile}\n");
            }
          else
            {
              fprintf (f, "rem Setting standalone package\n");
	      dos_script_prefix (f, Me.m_cmt_root, 
				 "cmt_standalone", "", Me.m_current_path, 
				 "setup", no_cleanup_opt);
            }

          fprintf (f, "\n");

          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);
        }
    }
}

/**
 *    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,
                const cmt_string& package,
                const cmt_string& version,
                const cmt_string& tag_name)
{
  clear ();
  configure ();

  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 ();
    }

  /*
    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))
    {
      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))
    {
      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;

  if (!CmtSystem::cd (Me.m_current_version))
    {
      if (!CmtSystem::test_directory ("cmt"))
        {
          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 = 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;
    }
  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;
        }
      else
        {
          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 ();
          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;

  /*
    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);
      exit (0);
    }

  clear ();
  configure ();

  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 (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 != "")
    {
      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 ();
      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);
      return (0);
    }

  switch (Me.m_action)
    {
      // case action_none :
    case action_awk :
    case action_broadcast :
    case action_build_constituent_makefile :
    case action_build_constituents_makefile :
    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_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_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_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 :
      use_cmt ();
        //
        // Now parse the requirements file stored in ${CMTHOME}
        //
      
      use_home_requirements ();

      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_constituents_makefile :
    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_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_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_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_constituents_makefile :
    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_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_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_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 :
      reach_current_package ();
      use_user_context_requirements ();
      break;
    default:
      break;
    }

  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_constituents_makefile :
        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_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_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_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_constituents_makefile :
	  do_build_constituents_makefile (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 :
	  cerr << "#CMT> action not implemented" << endl;
	  break;
	case action_lock :
	  do_lock (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_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_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_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;
	}
    }

  if (CmtError::has_pending_error ())
    {
      int code = CmtError::get_last_error_code ();
      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 (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;

          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;
    }

  cout << endl;
}


/**
 * 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);

  switch (mode)
    {
    case Csh :
      if (Me.m_current_package != "CMT")
        {
          cout << "unsetenv " << Me.m_current_prefix << "ROOT" << endl;
          cout << "unsetenv " << Me.m_current_prefix << "CONFIG" << endl;
        }
      break;
    case Sh :
      if (Me.m_current_package != "CMT")
        {
          cout << "unset " << Me.m_current_prefix << "ROOT" << endl;
          cout << "unset " << Me.m_current_prefix << "CONFIG" << endl;
        }
      break;
    case Bat :
      if (Me.m_current_package != "CMT")
        {
          cout << "set " << Me.m_current_prefix << "ROOT=" << endl;
          cout << "set " << Me.m_current_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;

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

          switch (mode)
            {
            case Csh :
              cout << "unsetenv " << use->prefix << "ROOT" << endl;
              cout << "unsetenv " << use->prefix << "CONFIG" << endl;
              break;
            case Sh :
              cout << "unset " << use->prefix << "ROOT" << endl;
              cout << "unset " << use->prefix << "CONFIG" << endl;
              break;
            case Bat :
              cout << "set " << use->prefix << "ROOT=" << endl;
              cout << "set " << use->prefix << "CONFIG" << endl;
              break;
            }
        }
    }

  switch (mode)
    {
    case Csh :
      cout << "unsetenv CMTEXTRATAGS" << endl;
      break;
    case Sh :
      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");

  switch (mode)
    {
    case Csh :
      if (do_root)
	{
	  cout << "setenv " << use.prefix << "ROOT \"" <<
	    use.get_full_path () << "\"" << endl;
	}

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

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

      if (use.get_package_name () == "CMT")
        {
          cout << "set CMTCONFIG=" << system << endl;
        }
      else
        {
	  if (do_config)
	    {
	      cout << "set " << use.prefix << "CONFIG=" << tag << 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.
          if ((symbol.type == Symbol::SymbolMacro) ||
              (symbol.type == Symbol::SymbolAction)) continue;
        }
      else if (Me.m_action == action_show_action_names)
        {
          // Exclude macros.
          if (symbol.type != Symbol::SymbolAction) 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)
{
  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)
        {
          // 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;
        }

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

      symbol.show_macro (mode);
    }
}

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

//----------------------------------------------------------
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"))
        {
            /*
          if (!Me.m_quiet)
            {
              cout << "#CMT> Cannot reach the requirements file" << endl;
            }
              
          CmtError::set (CmtError::package_not_found,
                         "ReachCurrentPackage> Cannot reach the requirements file");
            */
          return (0);
        }
    }
  else if (Me.m_current_package != "")
    {
      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
            {
              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);
            }
        }

      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);
        }
      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_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;
    }

  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 ();
            //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);
}

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;
  
    //cout << "Package " << use->get_package_name () << endl;
  
  for (i = 0; i < m; i++)
    {
      const cmt_string& fa = va[i];
      const cmt_string& fb = pwd[i];
      
        //cout << "  fa=" << fa << " fb=" << fb << endl;
      
      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 (const cmt_string& current_dir)
  {
    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)
      {
        buffer = "macro srcdir \".";
        buffer += "\"";
        apply ();

        buffer = "macro src \".";
        buffer += fs;
        buffer += "\"";
        apply ();

        buffer = "macro inc \".";
        buffer += fs;
        buffer += "\"";
        apply ();

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

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

        buffer = "macro javabin \".";
        buffer += fs;
        buffer += "\"";
        apply ();

        buffer = "macro doc \".";
        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 ();
          }

	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->located ())
              {
                buffer += "$(";
                buffer += use->prefix;
                buffer += "ROOT)";
                buffer += fs;
                
                if (use->style == mgr_style) 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;

	    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;

	    Package* p = use->get_package ();
	    if (p->is_cmt ()) continue;
            
            use->fill_macro (buffer, "stamps");
          }
        
        buffer += "\"";
        
        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;
            
	    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
   *
   */
  void fill_for_all_constituents ()
  {
    /// First, finish the parsing of constituent parameters.
    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];

	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;

		    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;
          }

        /**
	 * 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);

        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 (Cmt::get_debug ())
		  {
		    cout << constituent.name  << " needs imports " << import << " "
			 << use_index << " " 
			 << u->get_package()->get_name() << endl;
		  }

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

                if (u->auto_imports != Off) continue;

                Use::set_auto_imports_state (use_index, auto_imports_states);
              }
          }

        if (Cmt::get_debug ())
          {
            cout << constituent.name  << " has imports " << endl;
          }


	/**
	 *   Find all newly exposed packages and precompute this list inside
	 *   a vector.
	 */
	for (i = 0; i < base_auto_imports_states.size (); i++)
	  {
	    if (auto_imports_states[i] != base_auto_imports_states[i])
	      {
                Use* u = Uses[i];

                if (u->discarded) continue;

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

                if (Cmt::get_debug ())
                  {
                    cout << constituent.name  << " has import " << p->get_name () << endl;
                  }

                if (u->auto_imports != Off) continue;

                imports.push_back (u);
	      }
	  }
        
        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 ();
	
	/**
           *  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 ();
       
       /**
         *  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;
		
		Package* p = u->get_package ();
		if (p->is_cmt ()) continue;

		u->fill_macro (buffer, "linkopts");
	      }
	  }
	buffer += "\"";
	apply ();

	//==== GLAST addition for vs.net ==========
	buffer = "macro ";
	buffer += constituent.name;
	buffer += "_GUID \"{88BF15AB-5A2D-4bea-B64F-02752C2A1F4F}\" ";
	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 ();

	//cout << "#IA7>" << endl;
	
	ia_mgr.setup ();
      }
  }

  /**
   * Macros to be defined once current_package is known
   * and even before reading its requirements file.
   */
  void fill_for_current_package (const cmt_string& current_dir)
  {
    fill_for_tag ();
    fill_for_package (current_dir);
  }

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_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 ();

  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
     */

  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,
                                Me.m_current_package,
                                Me.m_current_version,
                                Me.m_current_prefix,
                                Me.m_current_style);


    //
    //  Definitions for installation area mechanisms
    //
  /*
  if (current_use.get_strategy ("InstallArea"))
    {
      CmtInstallAreaMgr& ia_mgr = CmtInstallAreaMgr::instance ();

      //cout << "#IA6>" << endl;

      ia_mgr.setup_current_installarea ();
    }
  */

  builder.fill_for_current_package (Me.m_current_dir);

  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 = Me.m_cmt_user_context;
  f += CmtSystem::file_separator ();
  f += file_name;
  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 (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);
}
