source: CMT/HEAD/source/cmt_use.cxx @ 572

Last change on this file since 572 was 572, checked in by rybkin, 13 years ago

See C.L. 455

  • Property svn:eol-style set to native
File size: 124.3 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// Modified by garonne@lal.in2p3.fr
5// See the complete license in cmt_license.txt "http://www.cecill.info".
6//-----------------------------------------------------------
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include "cmt_use.h"
13#include "cmt_system.h"
14#include "cmt_symbol.h"
15#include "cmt_error.h"
16#include "cmt_database.h"
17#include "cmt_syntax.h"
18#include "cmt_log.h"
19
20static void show_packages ();
21
22/*
23 *   Design.
24 *
25 *   There is one central database of all Use objects. This in the Database using:
26 *       Database::instance().get_instances ();
27 *
28 *   There is also a list of selected Use pointers available from
29 *       Database::instance().get_ordered_uses ();
30 *
31 *   A new Use object is created when a new use statement requires it:
32 *     o if the specified version is specified for the first time
33 *     o if the specified path is specified for the first time
34 *
35 */
36
37static bool add_request (const cmt_string& path,
38                         const cmt_string& package_name,
39                         const cmt_string& version)
40{
41  static cmt_map <cmt_string, bool> requests;
42
43  cmt_string request = package_name;
44  request += " ";
45  request += version;
46  request += " ";
47  request += path;
48  static bool b = true;
49
50  bool new_request = false;
51
52  if (!requests.has ((const cmt_string&) request))
53    {
54      new_request = true;
55      requests.add ((const cmt_string&) request, b);
56    }
57
58  return (new_request);
59}
60
61class UseContext
62{
63public:
64
65  static UseContext& current ()
66  {
67    static UseContext me;
68
69    return (me);
70  }
71
72  UseContext ()
73  {
74    m_auto_imports = Unspecified;
75    //m_auto_imports = On;
76  }
77
78  UseContext (const UseContext& other)
79  {
80    m_auto_imports = other.m_auto_imports;
81  }
82
83  UseContext& operator = (const UseContext& other)
84  {
85    m_auto_imports = other.m_auto_imports;
86
87    return (*this);
88  }
89
90  static void set_current (State auto_imports)
91  {
92    UseContext& c = current ();
93
94    c.m_auto_imports = auto_imports;
95  }
96
97  static State get_current_auto_imports ()
98  {
99    UseContext& c = current ();
100
101    return (c.m_auto_imports);
102  }
103
104  static State mask_auto_imports (State context_state, State auto_imports)
105  {
106    switch (auto_imports)
107      {
108      case Unspecified:
109        return context_state;
110        break;
111      case Off:
112        return Off;
113        break;
114      case On:
115        if (context_state != Off)
116          return On;
117        else
118          return context_state;
119        break;
120      }
121  }
122
123private:
124  State m_auto_imports;
125};
126
127
128class BestFitSelector
129{
130public:
131  Use* operate (Use* ref_use, Use* new_use);
132};
133
134//----------------------------------------------------------
135
136typedef enum
137  {
138    IdenticalIds,
139
140    IncompatibleMajorIds,
141    NewMajorIdGreaterThanOld,
142    OldMajorIdGreaterThanNew,
143    ExplicitOldMajorIdWinsAgainstWildarded,
144    ExplicitNewMajorIdWinsAgainstWildarded,
145
146    ExplicitOldMinorIdWinsAgainstWildarded,
147    ExplicitNewMinorIdWinsAgainstWildarded,
148    NewMinorIdGreaterThanOld,
149
150    ExplicitOldPatchIdWinsAgainstWildarded,
151    ExplicitNewPatchIdWinsAgainstWildarded,
152    NewPatchIdGreaterThanOld
153  } CompareStatus;
154
155static CompareStatus compare_versions (const cmt_string& ref_version, const cmt_string& new_version, bool match = false)
156{
157  CompareStatus result = IdenticalIds;
158
159  if (match)
160    {
161      if (ref_version == "" ||
162          ref_version == "*" ||
163          ref_version == "v*")
164        return IdenticalIds;
165
166      int wild_card = ref_version.find ('*');
167      if (wild_card != cmt_string::npos)
168        {
169          cmt_string ref_ver (ref_version.substr (0, wild_card));
170          if (ref_ver.size () > new_version.size ())
171            return IncompatibleMajorIds;
172          else if (strncmp (ref_ver.c_str (), new_version.c_str (), wild_card) == 0)
173            return IdenticalIds;
174          else
175            return IncompatibleMajorIds;
176        }
177      else if (ref_version == new_version)
178            return IdenticalIds;
179      else
180            return IncompatibleMajorIds;
181    }
182
183  int old_v = -1;
184  int old_r = -1;
185  int old_p = -1;
186
187  int new_v = -1;
188  int new_r = -1;
189  int new_p = -1;
190
191  CmtSystem::is_version_directory (ref_version, old_v, old_r, old_p);
192
193  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
194
195  if ((new_v != -1) && (old_v != -1) && (new_v != old_v))
196    {
197      /*
198        if (!Cmt::get_quiet ())
199        {
200        cerr << "#1 Required version " << new_version <<
201        " incompatible with selected version " << ref_version <<
202        endl;
203        }
204      */
205
206      if (new_v > old_v)
207        {
208          result = NewMajorIdGreaterThanOld;
209        }
210      else
211        {
212          result = OldMajorIdGreaterThanNew;
213        }
214      //result = IncompatibleMajorIds;
215    }
216  else if ((new_v == -1) || (old_v == -1))
217    {
218      //
219      // we plan to discard new_use, but if it was specified as explicit
220      // and ref_use was wildcarded then new_use will win !!
221      //
222      // So then we'll have to understand where are the wild
223      // cards... If they are on v or r, then we consider them.
224      //
225      //
226
227
228      if ((old_v == -1) && (new_v != -1))
229        {
230          /*
231            if (!Cmt::get_quiet ())
232            {
233            cerr << "#2 Select version " << new_version <<
234            " instead of existing " << ref_version <<
235            endl;
236            }
237          */
238
239          result = ExplicitNewMajorIdWinsAgainstWildarded;
240        }
241      else
242        {
243          /*
244            if (!Cmt::get_quiet ())
245            cerr << "#3 keep version " << ref_version <<
246            " (ignore version " << new_version << ")" <<
247            endl;
248          */
249
250          result = ExplicitOldMajorIdWinsAgainstWildarded;
251        }
252    }
253  else if ((new_r == -1) || (old_r == -1) || (new_r < old_r))
254    {
255      //
256      // we plan to discard new_use, but if it was specified as explicit
257      // and ref_use was wildcarded then new_use will win !!
258      //
259      // So then we'll have to understand where are the wild
260      // cards... If they are on v or r, then we consider them.
261      //
262      //
263
264
265      if ((old_r == -1) && (new_r != -1))
266        {
267          // old has wild card and new has not => new wins
268
269          /*
270            if (!Cmt::get_quiet ())
271            {
272            cerr << "#4 Select release " << new_version
273            << " instead of existing " << ref_version
274            << endl;
275            }
276          */
277
278          result = ExplicitNewMinorIdWinsAgainstWildarded;
279        }
280      else
281        {
282          /*
283            if (!Cmt::get_quiet ())
284            cerr << "#5 keep release " << ref_version <<
285            " (ignore release " << new_version << ")" <<
286            endl;
287          */
288
289          result = ExplicitOldMinorIdWinsAgainstWildarded;
290        }
291    }
292  else if (new_r > old_r)
293    {
294      /*
295        if (!Cmt::get_quiet ())
296        {
297        cerr << "#6 Select release " << new_version <<
298        " instead of existing " << ref_version <<
299        endl;
300        }
301      */
302 
303      result = NewMinorIdGreaterThanOld;
304    }
305  else if ((new_p == -1) || (old_p == -1) || (new_p < old_p))
306    {
307      //
308      // we plan to discard new_use, but if it was specified as explicit
309      // and ref_use was wildcarded then new_use will win !!
310      //
311
312
313      if ((old_p == -1) && (new_p != -1))
314        {
315          /*
316            if (!Cmt::get_quiet ())
317            {
318            cerr << "#7 Select patch " << new_version <<
319            " instead of existing " << ref_version <<
320            endl;
321            }
322          */
323
324          result = ExplicitNewPatchIdWinsAgainstWildarded;
325        }
326      else
327        {
328          /*
329            if (!Cmt::get_quiet ())
330            cerr << "#8 keep patch " << ref_version <<
331            " (ignore version " << new_version << ")" <<
332            endl;
333          */
334
335          result = ExplicitOldPatchIdWinsAgainstWildarded;
336        }
337    }
338  else if (new_p > old_p)
339    {
340      /*
341        if (!Cmt::get_quiet ())
342        {
343        cerr << "#9 Select patch " << new_version <<
344        " instead of existing " << ref_version <<
345        endl;
346        }
347      */
348
349      result = NewPatchIdGreaterThanOld;
350    }
351
352  return (result);
353}
354
355//----------------------------------------------------------
356//
357//  Operations on Use
358//
359//----------------------------------------------------------
360
361/**
362 *  Mark all clients of the current package.
363 */
364void Use::select_clients (const cmt_string& package,
365                          const cmt_string& version)
366{
367  static UsePtrVector& uses = get_ordered_uses ();
368
369  int number;
370  Use* use = 0;
371
372  unselect_all ();
373  undiscard_all ();
374
375  for (number = uses.size () - 1; number >= 0; number--)
376    {
377      use = uses[number];
378      if (use == 0) continue;
379      if (use->is_selected ()) continue;
380      use->select ();
381      if (!use->is_client (package, version)) use->discard ();
382    }
383}
384
385//----------------------------------------------------------
386void Use::show_all (bool skip_discarded, ostream& out, PrintMode mode)
387//void Use::show_all (bool skip_discarded, ostream& out)
388//void Use::show_all (bool skip_discarded)
389{
390  show_all ("use ", skip_discarded, out, mode);
391  //  show_all ("use ", skip_discarded, out);
392}
393
394//----------------------------------------------------------
395void Use::show_cycles ()
396{
397  static int level = 0;
398  static UsePtrVector stack;
399  int size = 0;
400
401  if (level == 0)
402    {
403      unselect_all ();
404      unselect ();
405      stack.clear ();
406    }
407
408  //for (int i = 0; i < level; i++) cout << "  ";
409  //cout << "Use::show_cycles> " << level << " " << get_package_name () << endl;
410 
411  // Detect cycles.
412  for (int k = 0; k < level; k++)
413    {
414      Use* u = stack[k];
415      if (u == this) 
416        {
417          for (;k < level; k++)
418            {
419              u = stack[k];
420              cout << u->get_package_name () << " ";
421            }
422
423          cout << endl;
424
425          return;
426        }
427    }
428
429  // Save this to the stack.
430  if (stack.size () <= level)
431    {
432      stack.push_back (this);
433    }
434  else
435    {
436      stack[level] = this;
437    }
438
439  if (selected) return;
440  selected = true;
441
442  size = sub_uses.size ();
443  for (int n = 0; n < size; n++)
444    {
445      Use* use = sub_uses[n];
446     
447      if (use == 0) continue;
448     
449      //for (int i = 0; i < level; i++) cout << "  ";
450      //cout << "Use::show_cycles> " << get_package_name () << " uses " << use->get_package_name () << endl;
451
452      if (use->discarded)
453        {
454          Use* u;
455         
456          u = use->get_selected_version ();
457          if (u == 0) continue;
458         
459          use = u;
460        }
461     
462      level++;
463      use->show_cycles ();
464      level--;
465    }
466}
467
468//----------------------------------------------------------
469void Use::push_scope_section (ScopeType type)
470{
471  scope_sections.push_back (type);
472}
473
474//----------------------------------------------------------
475void Use::pop_scope_section ()
476{
477  scope_sections.pop_back ();
478}
479
480//----------------------------------------------------------
481void Use::close_scope_sections ()
482{
483  scope_sections.clear ();
484}
485
486//----------------------------------------------------------
487ScopeType Use::get_current_scope () const
488{
489  if (scope_sections.size () == 0) return (initial_scope);
490  const ScopeSection& s = scope_sections.back ();
491  return (s.get_scope ());
492}
493
494//----------------------------------------------------------
495void Use::show_all (const cmt_string& prefix, bool skip_discarded, ostream& out, PrintMode mode)
496//void Use::show_all (const cmt_string& prefix, bool skip_discarded, ostream& out)
497//void Use::show_all (const cmt_string& prefix, bool skip_discarded)
498{
499  static UsePtrVector& uses = get_ordered_uses ();
500
501  Use* use;
502  int number;
503
504  if (Cmt::get_debug ())
505    {
506      cout << "use::show_all-1> ";
507     
508      int i;
509     
510      for (i = 0; i < uses.size (); i++)
511        {
512          Use* u = uses[i];
513          cout << u->get_package_name () << "[" << u->get_index () << "]" << " ";
514        }
515     
516      cout << endl;
517    }
518
519  unselect_all ();
520
521  use = &(current ());
522  use->unselect ();
523  cmt_map <Use*, bool> visited;
524  if (!Cmt::get_quiet () && mode != Xml) use->show_sub_uses (visited, "", use->auto_imports, skip_discarded, out);
525
526  if (uses.size () > 0)
527    {
528      if (!Cmt::get_quiet () && mode != Xml)
529        {
530          out << "#\n";
531          out << "# Selection :\n";
532        }
533
534      //
535      //  First move the CMT package to the end of the use set.
536      //  (ie. used by everybody)
537      //
538      use = Use::find ("CMT");
539      Use::move (use);
540
541      switch (mode)
542        {
543        case Xml :
544          Cmt::print_xml_prolog ("uses", out);
545          out << "<uses>";
546          break;
547        }
548     
549      for (number = uses.size () - 1; number >= 0; number--)
550        {
551          use = uses[number];
552
553          if (use->discarded) continue;
554          if (use->m_hidden) continue;
555
556          if (!use->located ())
557            {
558              CmtMessage::warning ("package " + use->get_package_name ()
559                                   + " " + use->version + " " + use->path
560                                   + " not found");
561              /*
562              if (!Cmt::get_quiet ())
563                {
564                  out << "# package " << use->get_package_name () <<
565                    " " << use->version << " " << use->path <<
566                    " not found" <<
567                    endl;
568                }
569              */
570              CmtError::set (CmtError::package_not_found, use->get_package_name ());
571            }
572          else
573            {
574              switch (mode)
575                {
576                case Xml :
577                  Symbol* s;
578                  out << "<package"
579                      << (use->auto_imports == Off ? " auto_imports=\"no\"" : "")
580                      << ">";
581                  // out << "<order>" << use->get_index () << "</order>";
582                  out << "<name>" << use->get_package_name ()
583                      << "</name><version>" << use->version << "</version>";
584                  out << "<offset>" <<
585                    ( (s = Symbol::find (use->get_package_name () + "_offset"))
586                      ? s->build_macro_value ()
587                      : (CmtMessage::warning
588                         (CmtError::get_error_name (CmtError::symbol_not_found)
589                          + ": macro " + use->get_package_name () + "_offset")
590                         , "") )
591                      << "</offset>";
592                  out << "<cmtpath>" <<
593                    ( (s = Symbol::find (use->get_package_name () + "_cmtpath"))
594                      ? s->build_macro_value ()
595                      : (CmtMessage::warning
596                         (CmtError::get_error_name (CmtError::symbol_not_found)
597                          + ": macro " + use->get_package_name () + "_cmtpath")
598                         , "") )
599                      << "</cmtpath>";
600                  //out << "<offset>" << use->path << "</offset>";
601                  //out << "<cmtpath>" << p << "</cmtpath>";
602                  out << "<root>" << use->get_full_path () << "</root>";
603                  //if (use->auto_imports == Off)
604                  //out << "<no_auto_imports/>";
605                  out << "</package>";
606                  break;
607                default :
608              static const cmt_string empty;
609              cmt_string p = use->real_path;
610              if (use->path != "")
611                {
612                  int pos = p.find_last_of (use->path);
613                  if (pos != cmt_string::npos)
614                    {
615                      if (pos > 0 &&
616                          p[pos - 1] == CmtSystem::file_separator ())
617                        {
618                          // strip trailing file separator
619                          p.erase (pos - 1);
620                        }
621                      else
622                        p.erase (pos);
623                    }
624                }
625
626              out << prefix << use->get_package_name ()
627                   << " " << use->version;
628
629              if (CmtSystem::absolute_path (use->path))
630                {
631                  if (!Cmt::get_quiet ()) 
632                    {
633                      out << " (" << use->path << ")";
634                    }
635                }
636              else
637                {
638                  out << " " << use->path;
639                }
640
641              if (!Cmt::get_quiet ()) 
642                {
643                  if (p != "") out << " (" << p << ")";
644                  if (use->auto_imports == Off) out << " (no_auto_imports)";
645                }
646
647              out << endl;
648                  break;
649                }
650            }
651        }
652
653      Use* suse = Use::find (CmtSystem::get_home_package ());
654      if (suse != 0 && !suse->discarded && !suse->m_hidden && suse->located ())
655        {
656          switch (mode)
657            {
658            case Xml :
659              out << "<package>";
660              out << "<name>" << suse->get_package_name ()
661                  << "</name><version>" << suse->version << "</version>";
662              out << "<offset></offset>";
663              out << "<cmtpath>" << suse->path << "</cmtpath>";
664              out << "<root>" << suse->path << "</root>";
665              out << "</package>";
666              break;
667            default :
668          out << prefix << suse->get_package_name ()
669               << " " << suse->version;
670          if (!Cmt::get_quiet ()) 
671            {
672              out << " (" << suse->path << ")";
673            }
674          out << endl;
675              break;
676            }
677        }
678      suse = Use::find (CmtSystem::get_user_context_package ());
679      if (suse != 0 && !suse->discarded && !suse->m_hidden && suse->located ())
680        {
681          switch (mode)
682            {
683            case Xml :
684              out << "<package>";
685              out << "<name>" << suse->get_package_name ()
686                  << "</name><version>" << suse->version << "</version>";
687              out << "<offset></offset>";
688              out << "<cmtpath>" << suse->path << "</cmtpath>";
689              out << "<root>" << suse->path << "</root>";
690              out << "</package>";
691              break;
692            default :
693          out << prefix << suse->get_package_name ()
694               << " " << suse->version;
695          if (!Cmt::get_quiet ()) 
696            {
697              out << " (" << suse->path << ")";
698            }
699          out << endl;
700              break;
701            }
702        }
703
704      switch (mode)
705        {
706        case Xml :
707          out << "</uses>" << endl;
708          break;
709        }
710      /*
711      if (Cmt::get_cmt_home () != "")
712        {
713          out << prefix << CmtSystem::get_home_package () << " v0";
714          if (!Cmt::get_quiet ())
715            {
716              out << " (" << Cmt::get_cmt_home () << ")";
717            }
718          out << endl;
719        }
720
721      if (Cmt::get_cmt_user_context () != "")
722        {
723          out << prefix << CmtSystem::get_user_context_package () << " v0";
724          if (!Cmt::get_quiet ())
725            {
726              out << " (" << Cmt::get_cmt_user_context () << ")";
727            }
728          out << endl;
729        }
730      */
731    }
732 
733  const UseVector& instances = get_instances ();
734  for (int use_index = 0; use_index < instances.size (); use_index++)
735    {
736      Use* use = &(instances[use_index]);
737      //Use* use = uses[j];
738     
739      if (use->discarded) continue;
740      if (use->m_hidden) continue;
741     
742      if (!use->located ())
743        {
744          CmtError::set (CmtError::package_not_found, use->get_info ());
745        }
746      else
747        {
748          /*
749            CmtMessage::info ("package " +
750            use->get_package_name () +
751            " " + use->version +
752            (use->path != "" ? " " + use->path : "") +
753            " found");
754          */
755        }
756    }
757}
758
759/**
760 *   This private class parses the use statement after macro expansion
761 *   This is a finite state machine.
762 *    It maintains the results of the parsing in terms of a package name,
763 *   a version, a path, and state variables (no_auto_imports)
764 */
765class use_action_iterator
766{
767public:
768
769  use_action_iterator ()
770  {
771    state = need_package;
772    auto_imports = Unspecified;
773  }
774
775  void set (const cmt_string& w)
776  {
777    if (w.find (0, "-native_version=") != -1)
778      {
779        native_version = w.substr (16);
780      }
781    else if (w == "-auto_imports")
782      {
783        auto_imports = On;
784      }
785    else if (w == "-no_auto_imports")
786      {
787        auto_imports = Off;
788      }
789    else if (w == "|")
790      {
791        state = need_version_alias;
792      }
793    else
794      {
795        switch (state)
796          {
797          case need_package:
798            package = w;
799            state = need_version;
800            break;
801          case need_version:
802            version = w;
803            state = need_path;
804            break;
805          case need_path:
806            path = w;
807            while (path[path.size() - 1] == '/') path.erase (path.size() - 1);
808            while (path[path.size() - 1] == '\\') path.erase (path.size() - 1);
809            state = finished;
810            break;
811          case need_version_alias:
812            version_alias = w;
813            state = need_path_alias;
814            break;
815          case need_path_alias:
816            path_alias = w;
817            while (path_alias[path_alias.size() - 1] == '/') path_alias.erase (path_alias.size() - 1);
818            while (path_alias[path_alias.size() - 1] == '\\') path_alias.erase (path_alias.size() - 1);
819            state = finished;
820            break;
821          }
822      }
823  }
824
825  bool ok ()
826  {
827    if (package == "") return (false);
828    if (CmtSystem::is_home_package (package, version)) return (false);
829    if (CmtSystem::is_user_context_package (package, version)) return (false);
830    if (CmtSystem::is_project_package (package, version)) return (false);
831
832    return (true);
833  }
834
835  /**
836   *
837   *  Build or retreive the Use object corresponding to the parsed specification.
838   *
839   */
840  Use* get_use (Use* parent)
841  {
842    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
843
844    if (version == "") version = "*";
845
846    if (Cmt::get_debug ())
847      {
848        int i;
849
850        cout << "use::action1> current=" << parent->get_package_name () <<
851          " package=" << package << "(" << version << ")" << " ";
852
853        for (i = 0; i < uses.size (); i++)
854          {
855            Use* u = uses[i];
856            cout << u->get_package_name () << " ";
857          }
858        cout << endl;
859      }
860
861    const Use& cu = Use::current ();
862
863    /**
864     *   Do not continue the operations for private uses
865     *  accessed from an external context.
866     *
867     *   Exceptions should be considered for
868     *     - cmt broadcast
869     *     - cmt show uses
870     */
871
872    ActionType action = Cmt::get_action ();
873
874    if (Cmt::get_debug ())
875      {
876        cout << "before adding " << package <<"> auto_imports=" << auto_imports
877             << " (current AI was " << UseContext::get_current_auto_imports () << ")" 
878             << " (Use::scope=" << parent->get_current_scope () << ")"
879             << " (parent=" << parent->get_package_name () << ")"
880             << endl;
881      }
882
883    bool hidden_by_scope = false;
884
885    if (parent->get_current_scope () == ScopePrivate)
886      {
887        hidden_by_scope = true;
888
889        // Do not hide immediate children of the current package.
890        if ((parent == 0) || 
891            (parent->get_package () == cu.get_package ())) hidden_by_scope = false;
892
893        // Override default rule according to the scope filtering mode.
894
895        if (Cmt::get_scope_filtering_mode () == reach_private_uses) hidden_by_scope = false;
896      }
897
898    if (hidden_by_scope)
899      {
900        return (0);
901      }
902
903    // Here the version may contain wild cards
904
905    //UseContext save = UseContext::current ();
906
907    /**
908     *  "auto_imports" is the state which is specified on the use statement
909     *  currently being parsed.
910     */
911    //UseContext::set_current (UseContext::mask_auto_imports (UseContext::get_current_auto_imports (), auto_imports));
912    /*
913    switch (auto_imports)
914      {
915      case Unspecified:
916
917        // unspecified => we forward the state saved in the current use context
918
919        //UseContext::set_current (UseContext::get_current_auto_imports ());
920        break;
921      case Off:
922
923        // off => the context becomes constrained to be off
924
925        UseContext::set_current (Off);
926        break;
927      case On:
928
929        // on => if current context is off it is kept off
930        //       otherwise it is forced to on
931
932        if (UseContext::get_current_auto_imports () != Off)
933          {
934            UseContext::set_current (On);
935          }
936        break;
937      }
938*/
939    if (Cmt::get_debug ())
940      {
941        cout << "about to add " << package << endl;
942        //show_packages ();
943      }
944
945    /// Now do create or retreive the Use object.
946        Use* new_use = Use::add (path, package, version, 
947                                 version_alias, path_alias, native_version,
948                                 parent, auto_imports);
949
950        if (new_use != 0)
951          {
952            if (Cmt::get_debug ())
953              {
954                cout << "after adding1 " << package
955                     << "> auto_imports=" << new_use->auto_imports << endl;
956
957                //show_packages ();
958              }
959            /*
960            if (&(Use::current()) == parent)
961              {
962                cmt_map <Use*, bool> visited;
963                static bool yes (true);
964                visited.add (&(Use::current()), yes);
965                new_use->set_auto_imports
966                  (UseContext::mask_auto_imports (Use::current().auto_imports,
967                                                  auto_imports),
968                   auto_imports, visited);
969              }
970            */
971            //new_use->set_auto_imports (UseContext::get_current_auto_imports (),
972            //                 auto_imports);
973            /*
974            switch (new_use->auto_imports)
975              {
976              case Unspecified:
977                new_use->auto_imports = UseContext::get_current_auto_imports ();
978                if (new_use->auto_imports == Unspecified)
979                  {
980                    new_use->auto_imports = On;
981                  }
982                break;
983              case On:
984                break;
985              case Off:
986                if (UseContext::get_current_auto_imports () != Off)
987                  //if (UseContext::get_current_auto_imports () == On)
988                  {
989            */
990                    /**
991                     *  Warning : this Use had been previously specified as -no_auto_imports
992                     *  Now this new specification tries to turn it to auto_imports.
993                     *  It will be required to propagate the change, according to the
994                     *  specifications:
995                     *
996                     *    for all sub_uses:
997                     *       if it is unspecified OR specified as auto_imports:
998                     *          turn it to auto_imports
999                     *
1000                     */
1001            /*
1002                    new_use->set_auto_imports (UseContext::get_current_auto_imports ());
1003                    //new_use->set_auto_imports (On);
1004                  }
1005                break;
1006              }
1007            */
1008
1009            if (Cmt::get_debug ())
1010              {
1011                cout << "after adding2 " << package
1012                     << "> auto_imports=" << new_use->auto_imports << " ";
1013                cout << endl;
1014              }
1015
1016            //UseContext& c = UseContext::current ();
1017            //c = save;
1018
1019            Use::reorder (new_use, parent);
1020           
1021            if (Cmt::get_debug ())
1022              {
1023                cout << "use::action2> current=" << parent->get_package_name ()
1024                     << " package=" << package << " ";
1025
1026                int i;
1027               
1028                for (i = 0; i < uses.size (); i++)
1029                  {
1030                    Use* u = uses[i];
1031                    cout << u->get_package_name () << "[" << u->get_index () << "]" << " ";
1032                  }
1033
1034                cout << endl;
1035              }
1036          }
1037        /*
1038        else // new_use == 0
1039          {
1040            cerr << "action: " << action << " new_use: " <<  new_use
1041                 << " package: " <<  package << endl;
1042
1043            CmtError::set (CmtError::package_not_found, package);
1044          }
1045        */
1046
1047        return (new_use);
1048  }
1049
1050private:
1051
1052  enum
1053    {
1054      need_package,
1055      need_version,
1056      need_path,
1057      need_version_alias,
1058      need_path_alias,
1059      finished
1060    } state;
1061 
1062  State auto_imports;
1063  cmt_string native_version;
1064  cmt_string package;
1065  cmt_string version;
1066  cmt_string path;
1067  cmt_string version_alias;
1068  cmt_string path_alias;
1069};
1070
1071//----------------------------------------------------------
1072Use* Use::action (const CmtSystem::cmt_string_vector& words, Use* parent)
1073{
1074  Use* new_use;
1075
1076  //
1077  // complete syntax : "use <package> <version> <path> <-native_version=<version>>" 
1078  // minimal syntax  : "use <package>"
1079  //
1080  //  o if <version> is omitted then take any version available
1081  //  o <version> can be specified using "v*" or "v<n>r*" or "v<n>r<m>p*"
1082  //
1083  //  o the notation "v*" is preferred to omission (particularly since
1084  //    omission does not permit <path>)
1085  //
1086  if (words.size () < 2) return (0);
1087
1088  use_action_iterator it;
1089
1090  for (int i = 1; i < words.size (); i++)
1091    {
1092      const cmt_string& w = words[i];
1093      cmt_string ew = w;
1094
1095      Symbol::expand (ew);
1096      if (ew != w)
1097        {
1098          CmtSystem::cmt_string_vector ws;
1099
1100          CmtSystem::split (ew, " ", ws);
1101
1102          for (int j = 0; j < ws.size (); ++j)
1103            {
1104              const cmt_string& ww = ws[j];
1105              it.set (ww);
1106            }
1107        }
1108      else
1109        {
1110          it.set (ew);
1111        }
1112    }
1113
1114  if (!it.ok ()) return (0);
1115
1116  static int level = 0;
1117
1118  level++;
1119  new_use = it.get_use (parent);
1120  level--;
1121
1122  return (new_use);
1123}
1124
1125//----------------------------------------------------------
1126void Use::author_action (const CmtSystem::cmt_string_vector& words)
1127{
1128  if (author != "") author += "\n";
1129  for (int i = 1; i < words.size (); i++)
1130    {
1131      const cmt_string& w = words[i];
1132     
1133      if (i > 1) author += " ";
1134      author += w;
1135    }
1136}
1137//----------------------------------------------------------
1138void Use::manager_action (const CmtSystem::cmt_string_vector& words)
1139{
1140  if (manager != "") manager += "\n";
1141  for (int i = 1; i < words.size (); i++)
1142    {
1143      const cmt_string& w = words[i];
1144     
1145      if (i > 1) manager += " ";
1146      manager += w;
1147    }
1148}
1149
1150//----------------------------------------------------------
1151Use* Use::find (const cmt_string& package, 
1152                const cmt_string& version, 
1153                const cmt_string& path)
1154{
1155  Package* p = Package::find (package);
1156  if (p == 0) return (0);
1157
1158  UsePtrVector& uses = p->get_uses ();
1159
1160  int use_index;
1161  int size = uses.size ();
1162
1163  for (use_index = 0; use_index < size; use_index++)
1164    {
1165      Use& use = (*uses[use_index]);
1166
1167      // If the version argument is omitted then
1168      // take the first registered version
1169      if (version == "") return (&use);
1170         
1171      // Otherwise compare against specified_version and path
1172      //if ((use.specified_version == version) &&
1173      //  (use.specified_path == path)) return (&use);
1174     
1175      // what about comparing wild cards?
1176
1177      if (use.specified_version == version) return (&use);
1178    }
1179
1180  return (0);
1181}
1182
1183//----------------------------------------------------------
1184int Use::find_index (const cmt_string& package_name, 
1185                     const cmt_string& version, 
1186                     const cmt_string& path)
1187{
1188  Package* package = Package::find (package_name);
1189  if (package == 0) return (-1);
1190
1191  UsePtrVector& uses = package->get_uses ();
1192
1193  int use_index;
1194  int size = uses.size ();
1195  for (use_index = 0; use_index < size; use_index++)
1196    {
1197      Use* use = uses[use_index];
1198
1199      if (Cmt::get_debug ())
1200        {
1201          cout << "Use::find_index> " << package_name
1202               << " " << use
1203               << " " << use->m_index
1204               << endl;
1205        }
1206
1207      // If the version argument is omitted then
1208      // take the first registered version
1209      if (version == "") return (use->m_index);
1210     
1211      // Otherwise compare against specified_version and path
1212      //if ((use.specified_version == version) &&
1213      //  (use.specified_path == path)) return (&use);
1214     
1215      // what about comparing wild cards?
1216     
1217      if (use->specified_version == version) return (use->m_index);
1218    }
1219
1220  return (-1);
1221}
1222
1223//----------------------------------------------------------
1224/**
1225 *    Find by @package@ Use-object that is
1226 *    o not discarded
1227 *    o in ordereded Uses list (i.e., has non-negative m_index)
1228 */
1229//----------------------------------------------------------
1230Use* Use::find_valid (const cmt_string& package)
1231{
1232  Package* p = Package::find (package);
1233  if (p == 0) return (0);
1234
1235  UsePtrVector& uses = p->get_uses ();
1236
1237  for (int use_index = 0; use_index < uses.size (); use_index++)
1238    {
1239      Use* use = uses[use_index];
1240
1241      if (use->discarded) continue;
1242      if (use->m_index < 0) continue;
1243      // take the first not discarded and ordered
1244      // there should not be more than one
1245      return use;
1246    }
1247
1248  return (0);
1249}
1250
1251//----------------------------------------------------------
1252void Use::set_auto_imports_state (const Use::UsePtrVector& uses,
1253                                  cmt_vector<bool>& auto_imports_states,
1254                                  cmt_map <Use*, bool>& visited)
1255{
1256  if (0 == uses.size ()) return;
1257  static bool yes (true);
1258
1259  static int level (-1);
1260  level++;
1261  if (level == 0)
1262    {
1263      unselect_all ();
1264    }
1265
1266  if (Cmt::get_debug ())
1267    {
1268      cout << "Use::set_auto_imports_state>|";
1269      for (int i = level; i > 0; i--) cout << "-";
1270      for (int i = 0; i < uses.size (); i++)
1271      //for (int i = uses.size () - 1; i >= 0; i--)
1272        {
1273          cout << " " << uses[i]->get_package_name ()
1274               << "(" << uses[i]->auto_imports << ")";
1275        }
1276      cout << ">" << endl;
1277    }
1278
1279  for (int i = 0; i < uses.size (); i++)
1280  //for (int i = uses.size () - 1; i >= 0; i--)
1281    {
1282      Use* use = uses[i];
1283      if (visited.has (use) &&
1284          (0 != level || use->is_selected ()))
1285        // revisit uses specified explicitly with -import=<package> (level == 0)
1286        // encountered in constituent specification for the first time (selected == false)
1287        // to ensure <package> is imported
1288        {
1289          continue;
1290        }
1291
1292      visited.add (use, yes);
1293      if (0 == level) use->select ();
1294
1295      if (!auto_imports_states[use->m_index])
1296        auto_imports_states[use->m_index] = true;
1297      //if (0 == level && use->is_selected ()) continue;
1298
1299      Use::UsePtrVector subuses;
1300      for (int i = 0; i < use->sub_uses.size (); i++)
1301        {
1302          if (use->sub_uses[i]->m_index >= 0 && !use->sub_uses[i]->discarded)
1303            {
1304              if (use->sub_use_auto_imports[i] != Off)
1305                {
1306                  subuses.push_back (use->sub_uses[i]);
1307                }
1308              else
1309                {
1310                  visited.add (use->sub_uses[i], yes);
1311                }
1312            }
1313          else
1314            {
1315              if (Cmt::get_debug ())
1316                {
1317                  cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1318                       << " -> sub_use " << use->sub_uses[i]->get_package_name ()
1319                       << "[" << use->sub_uses[i] << ", discarded="
1320                       << use->sub_uses[i]->discarded << ", m_index="
1321                       << use->sub_uses[i]->m_index << " : invalid]" << endl;
1322                }
1323              Use* au (find_valid (use->sub_uses[i]->get_package_name ()));
1324              if (au)
1325                {
1326                  if (Cmt::get_debug ())
1327                    {
1328                      cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1329                           << " -> sub_use " << au->get_package_name ()
1330                           << "[" << au << ", discarded="
1331                           << au->discarded << ", m_index="
1332                           << au->m_index << " : valid]" << endl;
1333                    }
1334                  if (use->sub_use_auto_imports[i] != Off)
1335                    {
1336                      subuses.push_back (au);
1337                    }
1338                  else
1339                    {
1340                      visited.add (au, yes);
1341                    }
1342                }
1343              else
1344                {
1345                  visited.add (use->sub_uses[i], yes);
1346                }
1347            }
1348        }
1349      Use::set_auto_imports_state (subuses, auto_imports_states, visited);
1350    }
1351
1352  if (Cmt::get_debug ())
1353    {
1354      cout << "Use::set_auto_imports_state><";
1355      for (int i = level; i > 0; i--) cout << "-";
1356      for (int i = 0; i < uses.size (); i++)
1357      //for (int i = uses.size () - 1; i >= 0; i--)
1358        {
1359          cout << " " << uses[i]->get_package_name ()
1360               << "(" << (auto_imports_states[uses[i]->m_index] ? "+" : "-") << ")";
1361        }
1362      cout << "|" << endl;
1363    }
1364
1365  level--;
1366  return;
1367}
1368
1369/**
1370 *   1) Given a Use object identified by its index in the ordered_uses() array,
1371 *   2) Given a vector of states containing the auto_imports states of all uses,
1372 *
1373 *     we want to switch to 'On' the auto_imports states of all
1374 *     sub_uses of the argument that were Off.
1375 *
1376 */
1377 /*
1378void Use::set_auto_imports_state (int use_index,
1379                                  cmt_vector<bool>& auto_imports_states)
1380{
1381  // check boundaries (this should be an error when out bondaries)
1382  if ((use_index < 0) || (use_index >= auto_imports_states.size ())) return;
1383
1384  Use::UsePtrVector& uses = Use::get_ordered_uses ();
1385
1386  if (Cmt::get_debug ())
1387    {
1388      int i;
1389     
1390      cout << "Use::set_auto_imports_state> use_index=" << use_index << " ";
1391     
1392      for (i = 0; i < auto_imports_states.size (); i++)
1393        {
1394          cout << (auto_imports_states[i] ? "|" : "o");
1395        }
1396
1397      for (i = 0; i < auto_imports_states.size (); i++)
1398        {
1399          cout << " " << (uses[i])->get_package_name ();
1400        }
1401
1402      cout << endl;
1403    }
1404
1405  // check if this is already done (recursivity ending)
1406  if (auto_imports_states[use_index]) return;
1407  auto_imports_states[use_index] = true;
1408
1409  Use* use = uses[use_index];
1410
1411  // We only have to deal with Use objects that were
1412  // actually turned Off
1413  //  if (use->auto_imports != Off) return;
1414  */
1415  /**
1416   *  Here, use points to a Use object which had been declared as
1417   *  no_auto_imports. But we need to switch it On. Therefore,
1418   *
1419   *    1) the state in auto_imports_states has to be set On
1420   *    2) the operation has to be recursively propagated to all
1421   *         sub_uses which also had no_auto_imports. (only to those)
1422   * 
1423   */
1424 
1425  //  auto_imports_states[use_index] = true;
1426  /*
1427  cmt_string s;
1428  static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
1429 
1430  if (Cmt::get_debug ())
1431    {
1432      s = "Use::set_auto_imports_state>(";
1433      s += use->get_package_name ();
1434      s += ")";
1435      //cout << s << endl;
1436    }
1437
1438  int size = use->sub_uses.size ();
1439  for (int i = 0; i < size; i++)
1440    {
1441      Use* u = use->sub_uses[i];
1442
1443      // first find the index of this use.
1444     
1445      int j = u->m_index;
1446
1447      if (Cmt::get_debug ())
1448        {
1449          char num[32]; sprintf (num, "%#x", u);
1450          s += " ";
1451          s += use->sub_uses[i]->get_package_name ();
1452          s += "(";
1453          s += state_text[use->sub_use_auto_imports[i] + 1];
1454          s += ")[p=";
1455          s += num;
1456          s += "]";
1457        }
1458     
1459      if (j >= 0)
1460        {
1461          if (use->sub_use_auto_imports[i] != Off)
1462            {
1463              set_auto_imports_state (j, auto_imports_states);
1464            }
1465  */
1466          /*
1467          if (u->sub_use_auto_imports[i] == Off)
1468            {
1469              set_auto_imports_state (j, auto_imports_states);
1470            }
1471          else
1472            {
1473              auto_imports_states[j] = true;
1474            }
1475            */
1476  /*
1477        }
1478      else
1479        {
1480          if (Cmt::get_debug ())
1481            {
1482              cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1483                   << ": sub_use " << u->get_package_name () << "[" << u
1484                   << "] invalid" << endl;
1485            }
1486        }
1487    }
1488  if (Cmt::get_debug ())
1489    {
1490      cout << s << endl;
1491    }
1492}
1493  */
1494//----------------------------------------------------------
1495//
1496//  Move use to the end
1497//
1498//----------------------------------------------------------
1499void Use::move (Use* use)
1500{
1501  if (use == 0) return;
1502
1503  static UsePtrVector& uses = get_ordered_uses ();
1504
1505  int size = uses.size ();
1506
1507  if (size == 0) return;
1508
1509  //
1510  // On se positionne sur le pointeur.
1511  //
1512
1513  int use_index = use->m_index;
1514
1515  if (use_index < 0) return;
1516
1517  //
1518  // On deplace tous les pointeurs d'une case en arriere
1519  //
1520  for (use_index++; use_index < size; use_index++)
1521    {
1522      Use* u = uses[use_index];
1523      u->m_index--;
1524
1525      uses[use_index - 1] = uses[use_index];
1526    }
1527
1528  //
1529  // use est donc replace en derniere position
1530  //
1531
1532  use->m_index = size - 1;
1533  uses[size - 1] = use;
1534}
1535
1536/**
1537 *   Reorder provider versus client in the UsePtrVector list,
1538 *  so that the order reflects the fact that client makes use of provider.
1539 *   The result should be that provider appears before client in the list.
1540 */
1541void Use::reorder (Use* provider, Use* client)
1542{
1543  static UsePtrVector& uses = get_ordered_uses ();
1544
1545  int use_index;
1546
1547  int size = uses.size ();
1548
1549  if (size == 0) return;
1550  if (provider == client) return;
1551
1552  //
1553  // First locate the two use objects into the uses vector.
1554  //   -> provider_index and client_index
1555  //
1556
1557  int provider_index = -1;
1558  int client_index = -1;
1559
1560  provider_index = provider->m_index;
1561  client_index = client->m_index;
1562
1563  if (Cmt::get_debug ())
1564    {
1565      cout << "Use::reorder> provider=" << provider_index << " client=" << client_index << endl;
1566    }
1567
1568  //
1569  // Both objects must be installed in uses before acting.
1570  //
1571  if (provider_index == -1) return;
1572  if (client_index == -1) return;
1573
1574  if (client_index < provider_index)
1575    {
1576      //
1577      // client is already before provider so job is finished
1578      //
1579      return;
1580    }
1581
1582  //
1583  // before : <a a a P b b b C c c c>
1584  //                 ^       ^
1585  //                 ip      ic
1586  //
1587  //  1) move "P b b b" by one place to the right
1588  // thus :   <a a a P P b b b c c c>
1589  //
1590  //  2) move "C" to [ip]
1591  //
1592  // after  : <a a a C P b b b c c c>
1593  //
1594 
1595  for (use_index = client_index - 1; use_index >= provider_index; use_index--)
1596    {
1597      Use* use = uses[use_index];
1598      use->m_index++;
1599
1600      uses[use_index + 1] = uses[use_index];
1601    }
1602 
1603  uses[provider_index] = client;
1604  client->m_index = provider_index;
1605}
1606
1607//----------------------------------------------------------
1608void Use::clear_all ()
1609{
1610  static UsePtrVector& uses = get_ordered_uses ();
1611  static UseVector& instances = get_instances ();
1612
1613  int use_index;
1614
1615  for (use_index = 0; use_index < instances.size (); use_index++)
1616    {
1617      Use& use = instances[use_index];
1618      use.clear ();
1619    }
1620
1621  uses.clear ();
1622  instances.clear ();
1623}
1624
1625//----------------------------------------------------------
1626void Use::unselect_all ()
1627{
1628  static UsePtrVector& uses = get_ordered_uses ();
1629
1630  int use_index;
1631
1632  int size = uses.size ();
1633
1634  if (size == 0) return;
1635
1636  for (use_index = 0; use_index < size; use_index++)
1637    {
1638      Use* use = uses[use_index];
1639
1640      if (use != 0)
1641        {
1642          use->unselect ();
1643        }
1644    }
1645}
1646
1647//----------------------------------------------------------
1648void Use::undiscard_all ()
1649{
1650  static UsePtrVector& uses = get_ordered_uses ();
1651
1652  int use_index;
1653
1654  if (uses.size () == 0) return;
1655
1656  for (use_index = 0; use_index < uses.size (); use_index++)
1657    {
1658      Use* use = uses[use_index];
1659
1660      if (use != 0)
1661        {
1662          use->undiscard ();
1663        }
1664    }
1665}
1666
1667//----------------------------------------------------------
1668void Use::fill_macro_all (cmt_string& buffer, const cmt_string& suffix)
1669{
1670  UsePtrVector& uses = get_ordered_uses ();
1671
1672  buffer = "macro_append use_";
1673  buffer += suffix;
1674  buffer += " \" ";
1675  (Use::current()).fill_macro (buffer, suffix);
1676
1677  for (int number = 0; number < uses.size (); number++)
1678    {
1679      Use* use = uses[number];
1680     
1681      Package* p = use->get_package ();
1682      if (p->is_cmt ()) continue;
1683
1684      if (use->discarded) continue;
1685      if (use->auto_imports == Off) continue;
1686
1687      use->fill_macro (buffer, suffix);
1688    }
1689 
1690  buffer += "\"";
1691}
1692
1693//----------------------------------------------------------
1694Use::Use ()
1695{
1696  done = false;
1697  discarded = false;
1698  auto_imports = Unspecified;
1699  m_package = 0;
1700  m_index = -1;
1701  native_version = "";
1702
1703  clear ();
1704}
1705
1706//----------------------------------------------------------
1707Use::Use (const cmt_string& new_package,
1708          const cmt_string& new_version,
1709          const cmt_string& new_path)
1710{
1711  auto_imports = Unspecified;
1712  m_located = false;
1713  m_package = 0;
1714  m_index = -1;
1715
1716  set (new_package, new_version, new_path);
1717}
1718
1719//----------------------------------------------------------
1720Use::~Use ()
1721{
1722  clear ();
1723}
1724
1725//----------------------------------------------------------
1726void Use::clear ()
1727{
1728  specified_path = "";
1729  path      = "";
1730
1731  if (m_package != 0)
1732    {
1733      m_package->remove_use (this);
1734      m_package = 0;
1735    }
1736
1737  version   = "";
1738  author    = "";
1739  manager   = "";
1740  real_path = "";
1741
1742  prefix    = "";
1743  style     = mgr_style;
1744  initial_scope = ScopePublic;
1745  done      = false;
1746  discarded = false;
1747  selected  = false;
1748  m_hidden  = false;
1749  auto_imports = Unspecified;
1750
1751  includes.clear ();
1752  include_path = "";
1753  scripts.clear ();
1754  apply_patterns.clear ();
1755  ignore_patterns.clear ();
1756
1757  sub_uses.clear ();
1758  sub_use_scopes.clear ();
1759  sub_use_auto_imports.clear ();
1760
1761  requests.clear ();
1762
1763  alternate_versions.clear ();
1764  alternate_paths.clear ();
1765
1766  version_alias = "";
1767  path_alias    = "";
1768
1769  m_located = false;
1770  m_has_native_version = false;
1771  m_index = -1;
1772}
1773
1774//----------------------------------------------------------
1775void Use::set (const cmt_string& new_package,
1776               const cmt_string& new_version,
1777               const cmt_string& new_path,
1778               const cmt_string& new_version_alias,
1779               const cmt_string& new_path_alias)
1780{
1781  clear ();
1782
1783  Package* p = Package::add (new_package);
1784
1785  m_package = p;
1786  p->add_use (this);
1787
1788  specified_path    = new_path;
1789  // specified_path.replace_all ("\\", "/");
1790
1791  specified_version = new_version;
1792  version           = new_version;
1793  path              = specified_path;
1794  Symbol::expand (path);
1795  real_path         = "";
1796  style             = mgr_style;
1797  initial_scope     = ScopePublic;
1798  done              = false;
1799  discarded         = false;
1800  Cmt::build_prefix (new_package, prefix);
1801
1802  version_alias = new_version_alias;
1803  path_alias    = new_path_alias;
1804}
1805
1806//----------------------------------------------------------
1807void Use::change_path (const cmt_string& new_path)
1808{
1809  //
1810  // This methods changes real_path after an actual location
1811  // where this package/version has been found.
1812  //
1813
1814  real_path = "";
1815
1816  if (new_path != "")
1817    {
1818      if ((path.size () > 0) &&
1819          (!CmtSystem::absolute_path (path)))
1820        {
1821          real_path = new_path;
1822          real_path += CmtSystem::file_separator ();
1823          real_path += path;
1824        }
1825      else
1826        {
1827          real_path = new_path;
1828        }
1829      // real_path.replace_all ("\\", "/");
1830
1831      CmtSystem::compress_path (real_path);
1832    }
1833 
1834  m_located = true;
1835}
1836
1837//----------------------------------------------------------
1838int Use::reach_package (const cmt_string& from_path, const cmt_string& n_version)
1839{
1840  if (Cmt::get_debug ())
1841    {
1842      cout << "Use::reach_package> " << get_package_name ()
1843           << "(" << version << ") from " << from_path << endl;
1844      cout << "Use::reach_package> native_version required "<<n_version<<endl;
1845    }
1846   
1847  //
1848  // We try to reach a package/version starting from from_path
1849  //
1850
1851  // check if from_path is at least real
1852  if ((from_path != "") && !CmtSystem::cd (from_path)) return (0);
1853
1854  if (Cmt::get_debug ())
1855    {
1856      cout << "Use::reach_package-2>" << endl;
1857    }
1858
1859  // check in case from_path is a new search path
1860  if (from_path != real_path)
1861    {
1862      // Move to that prefix only if it is a relative path.
1863      if ((path.size () > 0) && (!CmtSystem::absolute_path (path)))
1864        {
1865          if (!CmtSystem::cd (path))
1866            {
1867              return (0);
1868            }
1869        }
1870    }
1871
1872  if (Cmt::get_debug ())
1873    {
1874      cout << "Use::reach_package-3>" << endl;
1875    }
1876
1877  // Special treatment for CMTHOME package...
1878  if (get_package_name () == CmtSystem::get_home_package ())
1879    {
1880      discarded = 1;
1881      if (!CmtSystem::test_file ("requirements"))
1882        {
1883          return (0);
1884        }
1885      else
1886        {
1887          return (1);
1888        }
1889    }
1890
1891  if (Cmt::get_debug ())
1892    {
1893      cout << "Use::reach_package-4>" << endl;
1894    }
1895
1896  // Special treatment for CMTUSERCONTEXT package...
1897  if (get_package_name () == CmtSystem::get_user_context_package ())
1898    {
1899      discarded = 1;
1900      if (!CmtSystem::test_file ("requirements"))
1901        {
1902          return (0);
1903        }
1904      else
1905        {
1906          return (1);
1907        }
1908    }
1909
1910  // Special treatment for PROJECT package...
1911  if (get_package_name () == CmtSystem::get_project_package ())
1912    {
1913      discarded = 1;
1914      if (!CmtSystem::test_file ("project"))
1915        {
1916          return (0);
1917        }
1918      else
1919        {
1920          return (1);
1921        }
1922    }
1923
1924  if (Cmt::get_debug ())
1925    {
1926      cout << "Use::reach_package-5>" << endl;
1927    }
1928
1929  // Now from_path exists, try if the package exists there
1930  if (!CmtSystem::cd (get_package_name ()))
1931    {
1932      return (0);
1933    }
1934
1935  if (Cmt::get_debug ())
1936    {
1937      cout << "Use::reach_package-6>" << endl;
1938    }
1939
1940  if (CmtSystem::test_file ("cmt/requirements"))
1941    {
1942      //      CmtSystem::cd ("cmt");
1943
1944      //      style = no_version_style;
1945
1946      cmt_string v;
1947      //      if (Package::get_version (v))
1948      if (Package::get_version (v, "cmt"))
1949        {
1950          CompareStatus s = compare_versions (version, v, true);
1951          if (Cmt::get_debug ())
1952            {
1953              cout << "Use::reach_package-6.1> version=" << version << " v=" << v << " s=" << s << endl;
1954            }
1955
1956          switch (s)
1957            {
1958            case IdenticalIds:
1959            case ExplicitOldMajorIdWinsAgainstWildarded:
1960            case ExplicitOldMinorIdWinsAgainstWildarded:
1961            case ExplicitOldPatchIdWinsAgainstWildarded:
1962              break;
1963            case ExplicitNewMajorIdWinsAgainstWildarded:
1964            case ExplicitNewMinorIdWinsAgainstWildarded:
1965            case NewMinorIdGreaterThanOld:
1966            case ExplicitNewPatchIdWinsAgainstWildarded:
1967            case NewPatchIdGreaterThanOld:
1968              break;
1969            case OldMajorIdGreaterThanNew:
1970            case NewMajorIdGreaterThanOld:
1971              break;
1972            case IncompatibleMajorIds:
1973              if (!is_head_version (v))
1974                return (0);
1975              break;
1976            }
1977          version = v;
1978        }
1979      else if (version == "")
1980        {
1981          version = "v0";
1982        }
1983      CmtSystem::cd ("cmt");
1984      style = cmt_style;
1985      structuring_style = without_version_directory;
1986      return (1);
1987    }
1988  else if (!CmtSystem::cd (version) || (version == ""))
1989    //  else if (!CmtSystem::cd (version))
1990    {
1991      //
1992      // The specified version cannot be found per-se
1993      // There are alternate possibilities when it contains wild cards
1994      //
1995      if ((version.find ("*") != cmt_string::npos) || (version == ""))
1996      //      if ((version == "") || (version.find ("*") != cmt_string::npos))
1997      //      if (version.find ("*") != cmt_string::npos)
1998        {
1999          static CmtSystem::cmt_string_vector versions;
2000          static cmt_string name;
2001
2002          name = ".";
2003          name += CmtSystem::file_separator ();
2004          if (version != "") name += version;
2005          else name += "*";
2006          /*
2007          if (version == "") name += "*";
2008          else name += version;
2009          */
2010          //          name += version;
2011          CmtSystem::scan_dir (name, versions);
2012          if (n_version != "")
2013            {
2014              CmtSystem::cmt_string_vector native_versions;           
2015              for (int i = 0; i < versions.size (); i++)
2016                {
2017                  cmt_string path;
2018                  if (CmtSystem::test_directory (versions[i]))
2019                    {
2020                      path  = versions[i];
2021                      path += CmtSystem::file_separator ();
2022                      path += "cmt";
2023                    }
2024                  else
2025                    {
2026                      path = "cmt";
2027                    }
2028                  path += CmtSystem::file_separator ();
2029                  path += "native_version.cmt";       
2030                                 
2031                  if (CmtSystem::test_file (path))
2032                    {
2033                      cmt_string nv;
2034
2035                      nv.read (path);
2036                      int pos = nv.find ('\n');
2037                      if (pos != cmt_string::npos) nv.erase (pos);
2038
2039                      pos = nv.find ('\r');
2040                      if (pos != cmt_string::npos) nv.erase (pos);
2041
2042                      if (nv == n_version)
2043                        {
2044                          cmt_string& name_entry = native_versions.add ();
2045
2046                          // We have found at least one
2047                          // cout << "native_version :" << n_version << " ,version: " << versions[i] << endl;
2048                          this->native_version   = n_version;
2049                          name_entry            += versions[i];
2050                        }
2051                    }                   
2052                }
2053              versions = native_versions;
2054            }
2055         
2056          int i;
2057          bool found = false;
2058         
2059          for (i = 0; i < versions.size (); i++)
2060            {
2061              const cmt_string& vers = versions[i];
2062             
2063              if (Cmt::get_debug ())
2064                {
2065                  cout << "     ... version " << vers << " exists" << endl;
2066                }
2067
2068              CmtSystem::basename (vers, name);
2069             
2070              int v;
2071              int r;
2072              int p;
2073             
2074              if (CmtSystem::is_version_directory (name, v, r, p))
2075                {
2076                  /*
2077                    This check is not sufficient !! We need to check in addition
2078                    that the selected directory is really the start of a true CMT
2079                    package (ie with either cmt/requirements or mgr/requirements below)
2080                  */
2081
2082                  cmt_string req;
2083
2084                  req = name;
2085                  req += CmtSystem::file_separator ();
2086                  req += "cmt";
2087                  req += CmtSystem::file_separator ();
2088                  req += "requirements";
2089
2090                  if (!CmtSystem::test_file (req))
2091                    {
2092                      req = name;
2093                      req += CmtSystem::file_separator ();
2094                      req += "mgr";
2095                      req += CmtSystem::file_separator ();
2096                      req += "requirements";
2097
2098                      if (!CmtSystem::test_file (req)) continue;
2099                    }
2100
2101                  cmt_string& new_v = alternate_versions.add ();
2102                  new_v = name;
2103                  cmt_string& new_p = alternate_paths.add ();
2104                  new_p = from_path;
2105                  bool& new_i = alternate_is_head_versions.add ();
2106                  new_i = is_head_version (name);
2107
2108                  found = true;
2109                }
2110            }
2111
2112              /*
2113          if (!found)
2114            {
2115              if (CmtSystem::test_file ("cmt/requirements"))
2116                {
2117                  CmtSystem::cd ("cmt");
2118                  style = no_version_style;
2119                  return (1);
2120                }
2121            }
2122              */
2123        }
2124
2125      if (Cmt::get_debug ())
2126        {
2127          cout << "  ... end of version scan" << endl;
2128        }
2129
2130      //
2131      //  We have now the list of possible alternate versions. However
2132      // we return that the expected package/version was not found (yet).
2133      //
2134
2135      return (0);
2136    }
2137
2138  if (Cmt::get_debug ())
2139    {
2140      cout << "Use::reach_package-7>" << endl;
2141    }
2142
2143  //cerr << "  ... version " << version << " exists" << endl;
2144
2145  // Now we have met the exact specified version!
2146  if (CmtSystem::test_file ("cmt/requirements"))
2147    {
2148      CmtSystem::cd ("cmt");
2149      style = cmt_style;
2150      structuring_style = with_version_directory;
2151    }
2152  else if (CmtSystem::test_file ("mgr/requirements"))
2153    {
2154      CmtSystem::cd ("mgr");
2155      style = mgr_style;
2156      structuring_style = with_version_directory;
2157    }
2158  else
2159    {
2160      return (0);
2161    }
2162
2163  if (Cmt::get_debug ())
2164    {
2165      cout << "Use::reach_package-8>" << endl;
2166    }
2167
2168  return (1);
2169}
2170
2171class UseProjectAction : public IProjectAction
2172{
2173public:
2174  UseProjectAction (Use* use, cmt_string n_version="") : m_use (use), m_found (false), native_version(n_version)
2175  {
2176  }
2177
2178  bool found () const
2179  {
2180    return (m_found);
2181  }
2182
2183  bool run (const Project& project)
2184  {
2185    const cmt_string& path = project.get_cmtpath ();
2186     
2187    m_use->alternate_versions.clear ();
2188    m_use->alternate_paths.clear ();
2189
2190    if (m_use->reach_package (path, this->native_version))
2191      {
2192        if (Cmt::get_debug ())
2193          {
2194            cout << "move_to4> " << path << endl;
2195          }
2196       
2197        m_use->change_path (path);
2198
2199        m_found = true;
2200
2201        return (false);
2202      }
2203    else if (m_use->alternate_versions.size () > 0)
2204      {
2205        if (m_use->select_alternate ()) 
2206          {
2207            if (Cmt::get_debug ())
2208              {
2209                cout << "move_to5> " << m_use->real_path << endl;
2210              }
2211
2212            m_found = true;
2213
2214            return (false);
2215          }
2216      }
2217   
2218    return (true);
2219  }
2220
2221private:
2222  Use* m_use;
2223  bool m_found;
2224  cmt_string native_version;
2225};
2226
2227//----------------------------------------------------------
2228bool Use::move_to (const cmt_string& native_version, bool curdir)
2229//bool Use::move_to (const cmt_string& native_version)
2230{
2231  if (m_located)
2232    {
2233      //
2234      // The real path where this version/package can be found
2235      // has already been resolved. We thus first go there.
2236      //
2237
2238      if (Cmt::get_debug ())
2239        {
2240          cout << "move_to1> " << real_path << endl;
2241        }
2242
2243      reach_package (real_path, native_version);
2244
2245      return (true);
2246    }
2247
2248  cmt_string expanded_path = path;
2249
2250  //
2251  // If the path specified in this use is a true absolute path,
2252  // then we search the package from there first.
2253  //
2254  if (CmtSystem::absolute_path (expanded_path))
2255    {
2256      if (reach_package (expanded_path,  native_version))
2257        {
2258          if (Cmt::get_debug ())
2259            {
2260              cout << "move_to3> " << expanded_path << endl;
2261            }
2262
2263          change_path (expanded_path);
2264
2265          return (true);
2266        }
2267      else if (alternate_versions.size () > 0)
2268        {
2269          if (select_alternate ()) 
2270            {
2271              if (Cmt::get_debug ())
2272                {
2273                  cout << "move_to5> " << real_path << endl;
2274                }             
2275
2276              return (true);
2277            }
2278        }
2279    }
2280
2281  //
2282  // Try here.
2283  //
2284  if (curdir)
2285    {
2286//   if (expanded_path == "")
2287//     {
2288//       if (reach_package ("", native_version))
2289
2290      cmt_string here = CmtSystem::pwd ();
2291
2292      if (reach_package (here,  native_version))
2293        {
2294          if (Cmt::get_debug ())
2295            {
2296              cout << "move_to2> " << expanded_path << endl;
2297            }
2298
2299          change_path (here);
2300
2301          return (true);
2302        }
2303      else if (alternate_versions.size () > 0)
2304        {
2305          if (select_alternate ()) 
2306            {
2307              if (Cmt::get_debug ())
2308                {
2309                  cout << "move_to5> " << real_path << endl;
2310                }
2311             
2312              return (true);
2313            }
2314        }
2315      return (false);
2316//     }
2317    } // end of curdir     
2318     
2319  //
2320  // Second try is among the CMTPATHs
2321  //
2322  UseProjectAction pa (this, native_version);
2323
2324  Project::broadcast (pa);
2325
2326  if (pa.found ()) return (true);
2327
2328  return (false);
2329}
2330
2331//----------------------------------------------------------
2332bool Use::select_alternate ()
2333{
2334  int i;
2335
2336  int v0 = 0;
2337  int r0 = 0;
2338  int p0 = 0;
2339
2340  int v = 0;
2341  int r = 0;
2342  int p = 0;
2343
2344  int selected_index = -1;
2345
2346  for (i = 0; i < alternate_versions.size (); i++)
2347    {
2348      cmt_string& name = alternate_versions[i];
2349
2350      if (i == 0)
2351        {
2352          CmtSystem::is_version_directory (name, v0, r0, p0);
2353          selected_index = 0;
2354        }
2355      else
2356        {
2357          if (alternate_is_head_versions[selected_index] &&
2358              alternate_is_head_versions[i])
2359            {
2360              if (strcmp(name.c_str (), alternate_versions[selected_index].c_str ()) > 0)
2361                {
2362                  selected_index = i;
2363                }
2364              continue;
2365            }
2366          else if (alternate_is_head_versions[selected_index])
2367            {
2368              continue;
2369            }
2370          else if (alternate_is_head_versions[i])
2371            {
2372              selected_index = i;
2373              continue;
2374            }
2375
2376          CmtSystem::is_version_directory (name, v, r, p);
2377
2378          if (v > v0)
2379            {
2380              selected_index = i;
2381              v0 = v;
2382              r0 = r;
2383              p0 = p;
2384            }
2385          else if (v == v0)
2386            {
2387              if (r > r0)
2388                {
2389                  selected_index = i;
2390                  r0 = r;
2391                  p0 = p;
2392                }
2393              else if (r == r0)
2394                {
2395                  if (p > p0)
2396                    {
2397                      selected_index = i;
2398                      p0 = p;
2399                    }
2400                }
2401            }
2402        }
2403    }
2404
2405  if (selected_index >= 0)
2406    {
2407      if (CmtSystem::cd (alternate_paths[selected_index]))
2408        {
2409          version = alternate_versions[selected_index];
2410          if (reach_package (alternate_paths[selected_index]))
2411            {
2412              if (Cmt::get_debug ())
2413                {
2414                  cout << "select_alternate> " << alternate_paths[selected_index] << endl;
2415                }
2416
2417              change_path (alternate_paths[selected_index]);
2418              return (true);
2419            }
2420        }
2421    }
2422
2423  return (false);
2424}
2425
2426//----------------------------------------------------------
2427bool Use::need_new (const cmt_string& path,
2428                    const cmt_string& package,
2429                    const cmt_string& version,
2430                    const cmt_string& n_version,
2431                    Use** old_use,
2432                    Use* context_use)
2433{
2434  bool new_request = add_request (path, package, version);
2435   
2436  Use& current_use = Use::current ();
2437
2438  if (package == current_use.get_package_name ())
2439    {
2440      if (Cmt::get_debug ())
2441        {
2442          cout << "  ... recursive use to current package" << endl;
2443        }
2444
2445      if (old_use != 0) *old_use = &current_use;
2446      return (false);
2447    }
2448
2449  Package* p = Package::add (package);
2450
2451  UsePtrVector& uses = p->get_uses ();
2452
2453  bool do_need_new = true;
2454  Use* found = 0;
2455  Use* registered = 0;
2456
2457  int req_v = -1;
2458  int req_r = -1;
2459  int req_p = -1;
2460
2461  CmtSystem::is_version_directory (version, req_v, req_r, req_p);
2462
2463  if (Cmt::get_debug ())
2464    {
2465      cout << "need_new> p=" << package << " v=" << version << " v=" << req_v << " r=" << req_r << " p=" << req_p << endl;
2466    }
2467
2468  bool has_wild_card = (req_v == -1) || (req_r == -1) || (req_p == -1);
2469
2470  int new_v = -1;
2471  int new_r = -1;
2472  int new_p = -1;
2473
2474  int use_index;
2475
2476  if (old_use != 0) *old_use = 0;
2477
2478  // Acquire the registered use.
2479  for (use_index = 0; use_index < uses.size (); use_index++)
2480    {
2481      Use& use = (*uses[use_index]);
2482
2483      if (use.m_index < 0) continue;
2484
2485      registered = &use;
2486
2487      break;
2488    }
2489
2490  // Make a first try with the registered use if it exists.
2491
2492  cmt_string decision;
2493
2494  if (registered != 0)
2495    {
2496      Use& use = (*registered);
2497
2498      found = &use;
2499
2500      CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2501
2502      bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2503
2504      if (has_wild_card && !use_has_wild_card)
2505        {
2506          if (Cmt::get_debug ())
2507            {
2508              cout << "  ... wildcarded request loses against existing explicit" << endl;
2509            }
2510         
2511          do_need_new = false; // We don't need a new one
2512        }
2513      else
2514        {
2515          // here either !has_wild_card or use_has_wild_card
2516
2517          if ((version == use.specified_version) &&
2518              (path == use.specified_path))
2519            {
2520             
2521              if (Cmt::get_debug ())
2522                {
2523                  cout << " ... exactly same version and path!" << endl;
2524                }             
2525              do_need_new = false; // We don't need a new one
2526              if (n_version != use.native_version)
2527                {
2528                  if (Cmt::get_debug ())
2529                    {
2530                      cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl; 
2531                    }
2532
2533                  do_need_new = true;   
2534                }             
2535            }
2536          else if (version != use.specified_version)
2537            {
2538              if (Cmt::get_debug ())
2539                {
2540                  cout << "requested explicit wins against existing wildcarded"
2541                       << endl;
2542                }
2543
2544              // The registered use loses against the request
2545            }
2546          else
2547            {
2548              if (Cmt::get_debug ())
2549                {
2550                  cout << "only paths differ, consider the new one."
2551                       << endl;
2552                }
2553
2554              // The registered use loses against the request
2555            }
2556        }
2557
2558
2559      //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2560      if (new_request && !Cmt::get_quiet ())
2561        {
2562          if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2563            {
2564              cerr << "# Required version " << version
2565                   << " of package " << package;
2566
2567              if (context_use != 0)
2568                {
2569                  cerr << " [from " << context_use->get_package_name () << "]";
2570                }
2571
2572              cerr << " incompatible with selected version " << use.version;
2573
2574              if (use.version != use.specified_version)
2575                {
2576                  cerr << " (" << use.specified_version << ")" ;
2577                }
2578
2579              cerr << endl;
2580            }
2581        }
2582
2583      if (Cmt::get_debug ())
2584        {
2585          cout << "# " << package << " " << version;
2586
2587          if (context_use != 0)
2588            {
2589              cout << " [from " << context_use->get_package_name () << "]";
2590            }
2591
2592          if (do_need_new)
2593            {
2594              cout << " > ";
2595            }
2596          else
2597            {
2598              cout << " < ";
2599            }
2600
2601          cout << use.version;
2602          if (use.version != use.specified_version)
2603            {
2604              cout << " (" << use.specified_version << ")" ;
2605            }
2606
2607          cout << " (r) ";
2608
2609          cout << endl;
2610        }
2611    }
2612
2613  if (do_need_new)
2614    {
2615      // Now try unregistered uses, since the registered one is not appropriate.
2616      // to see is any other existing use could match
2617
2618      for (use_index = 0; use_index < uses.size (); use_index++)
2619        {
2620          Use& use = (*uses[use_index]);
2621         
2622          if (use.m_index >= 0) continue;
2623         
2624          // Always save the latest found.
2625         
2626          found = &use;
2627
2628          CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2629
2630          bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2631
2632          if (has_wild_card && !use_has_wild_card)
2633            {
2634              if (Cmt::get_debug ())
2635                {
2636                  cout << "  ... requested wildcarded loses against existing explicit" << endl;
2637                }
2638             
2639              do_need_new = false; // We don't need a new one
2640            }
2641          else
2642            {
2643              // here either !has_wild_card or use_has_wild_card
2644         
2645              if ((version == use.specified_version) &&
2646                  (path == use.specified_path))
2647                {
2648                  if (Cmt::get_debug ())
2649                    {
2650                      cout << " ... exactly same version and path!" << endl;
2651                    }
2652             
2653                  do_need_new = false; // We don't need a new one
2654                  if (n_version != use.native_version)
2655                    {
2656                      if (Cmt::get_debug ())
2657                        {
2658                          cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl;
2659                        }
2660
2661                      do_need_new = true;   
2662                    }
2663                 
2664                }
2665              else if (version != use.specified_version)
2666                {
2667                  if (Cmt::get_debug ())
2668                    {
2669                      cout << "requested explicit wins against existing wildcarded"
2670                           << endl;
2671                    }
2672
2673                  // This use loses against the request
2674                }
2675              else
2676                {
2677                  if (Cmt::get_debug ())
2678                    {
2679                      cout << "only paths differ, consider the new one."
2680                           << endl;
2681                    }
2682
2683                  // This use loses against the request
2684                }
2685            }
2686
2687          //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2688          if (new_request && !Cmt::get_quiet ())
2689            {
2690              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2691                {
2692                  cerr << "# Required version " << version
2693                       << " of package " << package;
2694
2695                  if (context_use != 0)
2696                    {
2697                      cerr << " [from " << context_use->get_package_name () << "]";
2698                    }
2699             
2700                  cerr << " incompatible with selected version " << use.version;
2701
2702                  if (use.version != use.specified_version)
2703                    {
2704                      cerr << " (" << use.specified_version << ")" ;
2705                    }
2706
2707                  cerr << endl;
2708                }
2709            }
2710
2711          if (Cmt::get_debug ())
2712            {
2713              cout << "# " << package << " " << version;
2714             
2715              if (context_use != 0)
2716                {
2717                  cout << " [from " << context_use->get_package_name () << "]";
2718                }
2719             
2720              if (do_need_new)
2721                {
2722                  cout << " > ";
2723                }
2724              else
2725                {
2726                  cout << " < ";
2727                }
2728             
2729              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2730                {
2731                  cout << "(incompatible) ";
2732                }
2733
2734              cout << use.version;
2735              if (use.version != use.specified_version)
2736                {
2737                  cout << " (" << use.specified_version << ")" ;
2738                }
2739              cout << endl;
2740            }
2741        }
2742    }
2743
2744  if (old_use != 0)
2745    {
2746      if (registered != 0) *old_use = registered;
2747      else *old_use = found;
2748    }
2749
2750  return (do_need_new);
2751}
2752
2753//----------------------------------------------------------
2754//
2755//  Here the version which is provided here is the specified version.
2756// It may contain wild cards or it may be simply empty.
2757//
2758//----------------------------------------------------------
2759Use* Use::create (const cmt_string& path,
2760                  const cmt_string& package,
2761                  const cmt_string& version,
2762                  const cmt_string& version_alias,
2763                  const cmt_string& path_alias,
2764                  const cmt_string& n_version)
2765{
2766  Package* p = 0;
2767
2768  p = Package::add (package);
2769
2770  UsePtrVector& vector = p->get_uses ();
2771
2772  // We first look in the database.
2773  for (int use_index = 0; use_index < vector.size (); use_index++)
2774    {
2775      Use* use = vector[use_index];
2776
2777      if ((use->specified_version == version) && 
2778          (use->specified_path == path) && use->native_version==n_version) return (use);
2779    }
2780
2781  // We now really create a new Use entry.
2782
2783  static UseVector& instances = get_instances ();
2784
2785  Use& use_object = instances.add ();
2786
2787  use_object.set (package, version, path, version_alias, path_alias);
2788
2789  return (&use_object);
2790}
2791
2792//----------------------------------------------------------
2793//  Add a use request into the database.
2794//
2795//  o If a use request already exist in the database,
2796//    check the version compatibility
2797//
2798//----------------------------------------------------------
2799Use* Use::add (const cmt_string& path,
2800               const cmt_string& package_name,
2801               const cmt_string& version,
2802               const cmt_string& version_alias,
2803               const cmt_string& path_alias,
2804               const cmt_string& native_version,
2805               Use* context_use,
2806               const State specified_auto_imports)
2807{
2808  bool do_need_new = false;
2809
2810  Use* old_use = 0;
2811  Use* use = 0;
2812
2813  do_need_new = need_new (path, package_name, version, native_version, &old_use, context_use);
2814
2815  if (Cmt::get_debug ())
2816    {
2817      if (old_use != 0 && !do_need_new)
2818        {
2819          cout << "add> old_use " << old_use->get_package_name () <<
2820            " " << old_use->version <<
2821            " " << old_use->path <<
2822            endl;
2823        }
2824    }
2825
2826  if (do_need_new)
2827    {
2828      use = create (path, package_name, version, version_alias, path_alias, native_version);
2829    }
2830  else
2831    {
2832      // Since we don't need a new Use, it means that old_use exists !
2833
2834      use = old_use;
2835      old_use = 0;
2836    }
2837
2838  if (package_name == CmtSystem::get_home_package ())
2839    {
2840      return (use);
2841    }
2842
2843  if (package_name == CmtSystem::get_user_context_package ())
2844    {
2845      return (use);
2846    }
2847
2848  if (package_name == CmtSystem::get_project_package ())
2849    {
2850      return (use);
2851    }
2852
2853  cmt_string here = CmtSystem::pwd ();
2854
2855  //
2856  // Store the specified sub_uses. Some of them may become discarded
2857  // later on.
2858  //
2859  if (context_use != 0)
2860    {
2861      context_use->sub_uses.push_back (use);
2862
2863      context_use->sub_use_scopes.push_back (context_use->get_current_scope ());
2864
2865      context_use->sub_use_auto_imports.push_back (specified_auto_imports);
2866
2867      cmt_string& request = context_use->requests.add ();
2868
2869      request = package_name;
2870      request += " ";
2871      request += version;
2872      request += " ";
2873      request += path;
2874
2875
2876      if (Cmt::get_debug ())
2877        {
2878          cout << "Use::add context(" << context_use->get_package_name () << ") "
2879               << "[u:" << package_name
2880               << " s:" << context_use->get_current_scope ()
2881               << " ai:" << specified_auto_imports
2882               << "]" << endl;
2883        }
2884    }
2885
2886  if (use == &(Use::current ())) 
2887    {
2888      return (use);
2889    }
2890
2891  /*
2892   *   Now we have a Use object. If it is a new one, we have to
2893   *    1) understand if it exists physically
2894   *    2) it is better than the old ones.
2895   *
2896   *   Here, we may have :
2897   *    1) old_use = 0
2898   *         there was no Use object before for this package
2899   *         the existing one is fine
2900   *
2901   *    2) old_use != 0
2902   *         we have created a new Use (which has to be validated)
2903   */
2904  bool found = use->move_to (native_version);
2905
2906  if (Cmt::get_debug ())
2907    {
2908      cout << "add> use [" << use << "] " << use->get_package_name () 
2909           << " " << use->version
2910           << " " << use->path
2911           << " found=" << found
2912           << " done=" << use->done
2913           << endl;
2914
2915      show_packages ();
2916    }
2917     
2918  if (!found)
2919    {
2920      CmtMessage::warning (CmtError::get_error_name (CmtError::package_not_found)
2921                           + ": " + use->get_info ()
2922                           + ( (context_use != 0) ?
2923                               " (requested by " + context_use->get_package_name () + ")" :
2924                               "" )
2925                           );
2926      /*
2927      CmtMessage::warning ("package " + use->get_package_name ()
2928                           + " " + use->version + " " + use->path
2929                           + " not found"
2930                           + ( (context_use != 0) ?
2931                               " (requested by " + context_use->get_package_name () + ")" :
2932                               "" )
2933                           );
2934      */
2935      /*
2936      if (!Cmt::get_quiet ())
2937        {
2938          cerr << "#CMT> Warning: package " << use->get_package_name () <<
2939            " " << use->version << " " << use->path <<
2940            " not found";
2941
2942          if (context_use != 0)
2943            {
2944              cerr << " (requested by " << context_use->get_package_name () << ")";
2945            }
2946
2947          cerr << endl;
2948        }
2949      */
2950
2951      //CmtError::set (CmtError::package_not_found, use->get_package_name ());
2952      use->m_located = false;
2953      //use = 0;
2954    }
2955
2956  if ((old_use != 0) && (use != old_use))
2957    {
2958      if (Cmt::get_debug ())
2959        {
2960          cout << "There was another version of this Use. \n"
2961               << "But a new one was created due to some criteria. \n"
2962               << "Now we are going to apply the version strategy to make the final selection"
2963               << endl;
2964        }
2965
2966      /*
2967       *    There was another version of this Use.
2968       *    But a new one was created due to some criteria.
2969       *    Now we are going to apply the version strategy to make the final selection.
2970       */
2971
2972      if (Cmt::get_debug ())
2973        {
2974          cout << "select? [" << use << "] "<< use->version <<" vs old_use[" << old_use << "] "
2975               << old_use->get_package_name ()
2976               << " " << old_use->version
2977               << " " << old_use->path
2978               << endl;
2979        }
2980
2981      if (!found)
2982        {
2983          /*
2984           *  This new Use does not correspond to any physical package.
2985           *  let's simply discard it (and go back to old_use)
2986           */
2987
2988          //if (use != 0) use->discard ();
2989          use->discard ();
2990          use = old_use;
2991          if (context_use != 0)
2992            {
2993              context_use->sub_uses[context_use->sub_uses.size () - 1] = use;
2994            }
2995          found = use->move_to (native_version);
2996        }
2997      else
2998        {
2999          //
3000          //  This new version is different from the old one
3001          // thus we have to choose
3002          //
3003          bool old_use_is_head_version (use->is_head_version (old_use->version));
3004          bool use_is_head_version (use->is_head_version (use->version));
3005          Use* selected_use (old_use);
3006          if (old_use_is_head_version && use_is_head_version)
3007            {
3008              if (strcmp(use->version.c_str (), old_use->version.c_str ()) > 0)
3009                {
3010                  selected_use = use;
3011                  if (Cmt::get_debug ())
3012                    {
3013                      cout << "add> new head version " << use->version
3014                           << " wins old head version " << old_use->version
3015                           << endl;
3016                    }
3017                }
3018            }
3019          else if (old_use_is_head_version)
3020            {
3021            }
3022          else if (use_is_head_version)
3023            {
3024              selected_use = use;
3025              if (Cmt::get_debug ())
3026                {
3027                  cout << "add> new head version " << use->version
3028                       << " wins old version " << old_use->version
3029                       << endl;
3030                }
3031            }
3032          else
3033            {
3034              static BestFitSelector selector;
3035              selected_use = selector.operate (old_use, use);
3036              if (Cmt::get_debug ())
3037                {
3038                  cout << "add> operate on old version " << old_use->version
3039                       << " and new version " << use->version
3040                       << endl;
3041                }
3042            }
3043
3044          if (Cmt::get_debug ())
3045            {
3046              cout << "add> old=" << old_use << "i=" << old_use->m_index
3047                   << " new=" << use << "i=" << use->m_index
3048                   << " => selected=" << selected_use
3049                   << endl;
3050            }
3051
3052          //
3053          // Some situations managed by selector.operate happen
3054          // to fail discarding the rejected Use.
3055          //
3056          if (use != selected_use) 
3057            {
3058              use = use->set_selected_version (selected_use);
3059              if (context_use != 0)
3060                {
3061                  context_use->sub_uses[context_use->sub_uses.size () - 1] = use;
3062                }
3063            }
3064         
3065
3066          /*
3067           *   current directory is moved to the selected one
3068           */
3069          found = use->move_to (native_version);
3070        }
3071    }
3072
3073  //
3074  // The following statement is no longer considered as useful.
3075  // It is commented. But we should clarify why it was really needed!
3076  //
3077  //use->undiscard ();
3078
3079  if (found)
3080    {
3081      static UsePtrVector& uses = get_ordered_uses ();
3082
3083      bool registered = false;
3084      const Use& cu = Use::current ();
3085
3086      Package* package = Package::find (package_name);
3087
3088      //
3089      // A pointer to this new object is also added or replaced.
3090      //
3091      if ((use != &cu) && (package == cu.get_package ()))
3092        {
3093          // This is a recursive call to the current package!!
3094          registered = true;
3095          use->done = true;
3096          use->m_index = -1;
3097        }
3098      else
3099        {
3100          //
3101          // Now sort out the registration in ordered uses
3102          //
3103          //  cases:
3104          //
3105          //   use is not yet registered (m_index < 0)
3106          //     o if another use of the same package is registered,
3107          //       it must be substituted with the new one
3108          //     o otherwise create a new entry at the end (it will be sorted
3109          //       afterwards)
3110          //
3111          //   use is already registered (m_index >= 0)
3112          //     o if another use of the same package is registered,
3113          //       it must be discarded, but this may mean that
3114          //       two versions are simultaneously registered (bug?)
3115          //     o otherwise we keep it in place
3116          //
3117
3118          UsePtrVector& puses = package->get_uses ();
3119
3120          if (use->m_index >= 0) registered = true;
3121
3122          /*
3123            We look for all existing uses in that package.
3124          */
3125          for (int i = 0; i < puses.size(); i++)
3126            {
3127              Use* u = puses[i];
3128             
3129              if (Cmt::get_debug ())
3130                {
3131                  cout << "add> check registering between " << use
3132                       << ":" << use->get_package_name ()
3133                       << "(" << use->m_index << ")"
3134                       << " and " << u
3135                       << ":" << u->get_package_name () 
3136                       << "(" << u->m_index << ")"
3137                       << endl;
3138                }
3139
3140              if ((u != use) && (u->m_index >= 0))
3141                {
3142                  // Another use of that package is already registered
3143
3144                  if (Cmt::get_debug ())
3145                    {
3146                      cout << "add> Another use of that package is already registered " 
3147                           << " use(" << use->m_index << ")";
3148                      if (use->m_index >= 0)
3149                        {
3150                          cout << "[" << (uses[use->m_index])->get_package_name () << "]";
3151                        }
3152                      cout << " u(" << u->m_index << ")";
3153                      if (u->m_index >= 0)
3154                        {
3155                          cout << "[" << (uses[u->m_index])->get_package_name () << "]";
3156                        }
3157                      cout << endl;
3158                    }
3159
3160                  if (use->m_index < 0)
3161                    {
3162                      /*
3163                        the newly selected use (use) should replace the one which was registered (u)
3164                      */
3165
3166                      u->set_selected_version (use);
3167
3168                      registered = true;
3169                    }
3170                  else
3171                    {
3172                      // bug??
3173                      if (Cmt::get_debug ())
3174                        {
3175                          cout << "Duplicate entry in ordered uses" << endl;
3176                        }
3177                    }
3178                }
3179            }
3180
3181          if (Cmt::get_debug ())
3182            {
3183              cout << "add> registering completed" << endl;
3184              //show_packages ();
3185            }
3186        }
3187     
3188      if (!registered) 
3189        {
3190          if (Cmt::get_debug ())
3191            {
3192              cout << "add> We install use at the end the ordered list of uses" << endl;
3193            }
3194
3195          uses.push_back (use);
3196          use->m_index = uses.size () - 1;
3197        }
3198
3199      if (Cmt::get_debug ())
3200        {
3201          for (int use_index = 0; use_index < uses.size (); use_index++)
3202            {
3203              Use* u = (Use*) uses[use_index];
3204              cout << "  use[" << use_index << "] p=(" << u << ")" << u->get_package_name () 
3205                   << " v=" << u->version
3206                   << " discarded=" << u->discarded
3207                   << " selected=" << u->selected
3208                   << " done=" << u->done
3209                   << " index=" << u->m_index
3210                   << endl;
3211            }
3212         
3213        }
3214         
3215      if (!use->done && Cmt::get_recursive ())
3216        {
3217          use->done = true;
3218
3219          if (Cmt::get_debug ())
3220            {
3221              cout << "Parsing requirements file at " << CmtSystem::pwd () << endl;
3222            }
3223
3224          SyntaxParser::parse_requirements ("requirements", use);
3225        }
3226      else
3227        {
3228          if (Cmt::get_debug ())
3229            {
3230              cout << "Requirements file at " << CmtSystem::pwd () << " already parsed" << endl;
3231            }
3232        }
3233    }
3234
3235  CmtSystem::cd (here);
3236
3237  return (use);
3238}
3239
3240//----------------------------------------------------------
3241void Use::discard ()
3242{
3243  discarded = true;
3244}
3245
3246//----------------------------------------------------------
3247void Use::undiscard ()
3248{
3249  discarded = false;
3250}
3251
3252//----------------------------------------------------------
3253void Use::select ()
3254{
3255  selected = true;
3256}
3257
3258//----------------------------------------------------------
3259void Use::unselect ()
3260{
3261  selected = false;
3262}
3263
3264//----------------------------------------------------------
3265bool Use::is_selected ()
3266{
3267  return (selected);
3268}
3269
3270/**
3271 *    Check if the package makes use of the specified package/version
3272 *
3273 *    The seach only considers the first level of uses (thus it is
3274 *   NOT recursive)
3275 */
3276bool Use::is_client (const cmt_string& used_package,
3277                     const cmt_string& used_version)
3278{
3279  // A package is client of itself
3280
3281  Package* package = Package::find (used_package);
3282
3283  if ((get_package () == package) &&
3284      (version == used_version)) return (true);
3285
3286  if (discarded) return (false);
3287
3288  int i;
3289
3290  for (i = 0; i < sub_uses.size (); i++)
3291    {
3292      Use* use = sub_uses[i];
3293      if (use == 0) continue;
3294
3295      if ((use->get_package () == package) &&
3296          (use->version == used_version)) return (true);
3297
3298      /*
3299        if (use->is_client (used_package, used_version))
3300        {
3301        return (true);
3302        }
3303      */
3304    }
3305
3306  return (false);
3307}
3308
3309//----------------------------------------------------------
3310void Use::apply_global_patterns ()
3311{
3312  int i;
3313
3314  Pattern::PatternVector& vector = Pattern::patterns ();
3315
3316  for (i = 0; i < vector.size (); i++)
3317    {
3318      Pattern& p = vector[i];
3319
3320      if (p.global)
3321        {
3322          p.apply (this);
3323        }
3324    }
3325}
3326
3327//----------------------------------------------------------
3328void Use::set_include_path (const cmt_string& new_path)
3329{
3330  include_path = new_path;
3331}
3332
3333/**
3334 *   Compute the full real path of a found package.
3335 *   Takes the structuring style into account
3336 *
3337 *    Result is used to fill in the referenced string
3338 *    Result does NOT include the trailing file_separator
3339 */
3340void Use::get_full_path (cmt_string& s) const
3341{
3342  if (real_path == "") s = CmtSystem::pwd ();
3343  else s = real_path;
3344
3345  if (style != none_style)
3346    {
3347      s += CmtSystem::file_separator ();
3348      s += get_package_name ();
3349    }
3350 
3351  //  if (style != no_version_style)
3352  if (structuring_style == with_version_directory)
3353    {
3354      s += CmtSystem::file_separator ();
3355      s += version;
3356    }
3357}
3358
3359/**
3360 *   Compute the full real path of a found package.
3361 *   Takes the structuring style into account
3362 */
3363cmt_string Use::get_full_path () const
3364{
3365  cmt_string result;
3366
3367  get_full_path (result);
3368
3369  return (result);
3370}
3371
3372/**
3373 *   Considering a given path, try and reduce the part of it
3374 *  that corresponds to the full path of this package into its
3375 *  normal form ${<PACKAGE>ROOT}
3376 *   The argument is modified if the pattern is exactly found.
3377 */
3378void Use::reduce_path (cmt_string& s) const
3379{
3380  cmt_string pattern;
3381  get_full_path (pattern);
3382  pattern += CmtSystem::file_separator ();
3383 
3384  cmt_string replacement = "${";
3385  replacement += prefix;
3386  replacement += "ROOT}";
3387  replacement += CmtSystem::file_separator ();
3388
3389  s.replace (pattern, replacement);
3390}
3391
3392//----------------------------------------------------------
3393void Use::get_cmtpath_and_offset (cmt_string& cmtpath, cmt_string& offset) const
3394{
3395  if (get_package_name () == CmtSystem::get_project_package ())
3396    {
3397      offset = "";
3398      CmtSystem::dirname (path, cmtpath);
3399      return;
3400    }
3401  else if (get_package_name () == CmtSystem::get_home_package ())
3402    {
3403      offset = "";
3404      cmtpath = path;
3405      return;
3406    }
3407  else if (get_package_name () == CmtSystem::get_user_context_package ())
3408    {
3409      offset = "";
3410      cmtpath = path;
3411      return;
3412    }
3413
3414  cmtpath = "";
3415  offset = "";
3416
3417  cmtpath = Project::find_in_cmt_paths (real_path);
3418  Project* p = Project::find_by_cmtpath (cmtpath);
3419
3420  //  if (cmtpath != "")
3421  if (p != 0)
3422    {
3423      CmtSystem::compress_path (cmtpath);
3424
3425      static const cmt_string empty_string;
3426      static const cmt_string fs = CmtSystem::file_separator ();
3427     
3428      // In case there are symlinks
3429      //      offset = real_path;
3430      //      offset.replace (cmtpath, empty_string);
3431      //cerr << "realpath_: get_cmtpath_and_offset" << endl;
3432      CmtSystem::realpath_ (real_path, offset);
3433      offset.replace (p->get_cmtpath_real (), empty_string);
3434
3435      /**
3436         try to remove this current CMTPATH entry from path.  This
3437         has a meaning when the specified path already contains an
3438         absolute path.
3439      */
3440     
3441      if (offset[0] == CmtSystem::file_separator ())
3442        {
3443          // Just in case there is a part left after removing the cmtpath entry
3444               
3445          offset.replace (fs, empty_string);
3446        }
3447    }
3448  else
3449    {
3450      offset = real_path;
3451    }
3452}
3453
3454//------------------------------------------------------------
3455bool Use::get_strategy (const cmt_string& name) const
3456{
3457  const Project* p = Project::find_by_cmtpath (Project::find_in_cmt_paths (real_path));
3458
3459  bool strategy;
3460
3461  if (p == 0)
3462    {
3463      static const Project::ProjectPtrVector Ordered = Project::ordered_projects ();
3464      //static const Project::ProjectVector& projects = Project::projects ();
3465
3466      if (Ordered.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
3467      //if (projects.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
3468      else
3469        {
3470          p = Ordered[0];
3471          //p = &(projects[0]);
3472          strategy = p->get_strategy (name);
3473        }
3474    }
3475  else
3476    {
3477      strategy = p->get_strategy (name);
3478    }
3479
3480  return (strategy);
3481}
3482
3483//----------------------------------------------------------
3484void Use::fill_includes_macro (cmt_string& buffer) const
3485{
3486  if (include_path == "")
3487    {
3488      buffer += "$(ppcmd)\"$(";
3489      buffer += get_package_name ();
3490      buffer += "_root)";
3491      buffer += CmtSystem::file_separator ();
3492      buffer += "src\" ";
3493    }
3494  else if (include_path != "none")
3495    {
3496      buffer += "$(ppcmd)\"";
3497      buffer += include_path;
3498      buffer += "\" ";
3499    }
3500 
3501  for (int i = 0; i < includes.size (); i++)
3502    {
3503      Include& incl = includes[i];
3504
3505      if (incl.name == "") continue;
3506     
3507      buffer += "$(ppcmd)\"";
3508      buffer += incl.name;
3509      buffer += "\" ";
3510    }
3511}
3512
3513//----------------------------------------------------------
3514void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
3515{
3516  buffer += " $(";
3517  buffer += get_package_name ();
3518  buffer += "_";
3519  buffer += suffix;
3520  buffer += ") ";
3521}
3522
3523//----------------------------------------------------------
3524void Use::fill_standard_macros (cmt_string& buffer) const
3525{
3526  static cmt_string fs = CmtSystem::file_separator ();
3527
3528  buffer = "";
3529
3530  cmt_string package_name = get_package_name ();
3531
3532  buffer += "macro ";
3533  buffer += package_name;
3534  buffer += "_tag";
3535  buffer += " \"$(tag)\"";
3536  buffer += "\n";
3537
3538  if (located ())
3539    {
3540      buffer += "macro ";
3541      buffer += prefix;
3542      buffer += "ROOT";
3543      buffer += " \"";
3544      buffer += get_full_path ();
3545      buffer += "\"";
3546      buffer += "\n";
3547
3548      buffer += "macro ";
3549      buffer += package_name;
3550      buffer += "_root";
3551      buffer += " \"";
3552      buffer += real_path;
3553      if (style != none_style)
3554        {
3555          buffer += fs;
3556          buffer += package_name;
3557        }
3558      //      if (style != no_version_style)
3559      if (structuring_style == with_version_directory)
3560        {
3561          buffer += fs;
3562          buffer += version;
3563        }
3564      buffer += "\"";
3565      buffer += "\n";
3566    }
3567
3568  buffer += "macro ";
3569  buffer += prefix;
3570  buffer += "VERSION";
3571  buffer += " \"";
3572  buffer += version;
3573  buffer += "\"";
3574  buffer += "\n";
3575
3576  cmt_string cmtpath = "";
3577  cmt_string offset = "";
3578
3579  get_cmtpath_and_offset (cmtpath, offset);
3580
3581  buffer += "macro ";
3582  buffer += package_name;
3583  buffer += "_cmtpath";
3584  buffer += " \"";
3585  buffer += cmtpath;
3586  buffer += "\"";
3587  buffer += "\n";
3588
3589  buffer += "macro ";
3590  buffer += package_name;
3591  buffer += "_offset";
3592  buffer += " \"";
3593  buffer += offset;
3594  buffer += "\"";
3595  buffer += "\n";
3596 
3597  Project* p = Project::find_by_cmtpath (cmtpath);
3598
3599  buffer += "macro ";
3600  buffer += package_name;
3601  buffer += "_project";
3602  buffer += " \"";
3603  if (p != 0)
3604    {
3605      buffer += p->get_name ();
3606    }
3607  buffer += "\"";
3608  buffer += "\n";
3609
3610  buffer += "macro ";
3611  buffer += package_name;
3612  buffer += "_project_release";
3613  buffer += " \"";
3614  if (p != 0)
3615    {
3616      buffer += p->get_release ();
3617    }
3618  buffer += "\"";
3619}
3620
3621
3622//----------------------------------------------------------
3623static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
3624{
3625  bool result = false;
3626
3627  cmt_string here = CmtSystem::pwd ();
3628
3629  cmt_string h1;
3630  if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
3631
3632  CmtSystem::cd (here);
3633
3634  cmt_string h2;
3635  if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
3636
3637  result = (h1 == h2);
3638
3639  CmtSystem::cd (here);
3640
3641  return (result);
3642}
3643
3644//----------------------------------------------------------
3645static bool install_library (const cmt_string& source_library_name, 
3646                             const cmt_string& dest_library_name, 
3647                             const cmt_string& cmtinstallarea, 
3648                             const cmt_string& tag, 
3649                             const cmt_string& symlinkcmd)
3650{
3651  cmt_string libname = source_library_name;
3652  cmt_string name = dest_library_name;
3653  cmt_string s;
3654  Use& current_use = Use::current ();
3655
3656  Symbol::expand (name);
3657  Symbol::expand (libname);
3658
3659  if (cmtinstallarea != "")
3660    {
3661      s = cmtinstallarea;
3662      s += CmtSystem::file_separator ();
3663      s += tag;
3664      s += CmtSystem::file_separator ();
3665      s += "lib";
3666      s += CmtSystem::file_separator ();
3667      s += name;
3668     
3669      // Now creating the reference file
3670
3671      cmt_string ref_file = s;
3672      ref_file += ".cmtref";
3673
3674      cmt_string text = libname;
3675      text += "\n";
3676
3677      Symbol::expand (ref_file);
3678      Symbol::expand (text);
3679
3680      if (CmtMessage::active (Info))
3681        cerr << "   Creating the reference file " << ref_file << endl;
3682          //      if (!Cmt::get_quiet ()) cerr << "   Creating the reference file " << ref_file << endl;
3683      text.write (ref_file);
3684    }
3685  else
3686    {
3687      if (current_use.style != none_style)
3688        {
3689          s = "../$(";
3690          s += current_use.get_package_name ();
3691          s += "_tag)/";
3692        }
3693      else
3694        {
3695          s = "./";
3696        }
3697      s += name;
3698    }
3699
3700  Symbol::expand (s);
3701
3702  cmt_string source;
3703  cmt_string dest;
3704
3705  CmtSystem::dirname (libname, source);
3706  CmtSystem::dirname (s, dest);
3707
3708  if (same_dirs (source, dest))
3709    {
3710      return (false);
3711    }
3712
3713  //if (!Cmt::get_quiet ())
3714  if (CmtMessage::active (Info))
3715    cerr << "   Symlinking " << libname << " to " << s << endl;
3716
3717  if (symlinkcmd == "")
3718    {
3719      if (!CmtSystem::create_symlink (libname, s))
3720        {
3721          CmtMessage::error ("Cannot create a symbolic link to " + libname);
3722          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3723          return (false);
3724        }
3725    }
3726  else
3727    {
3728      cmt_string cmd = symlinkcmd;
3729      cmd += " ";
3730      cmd += libname;
3731      cmd += " ";
3732      cmd += s;
3733     
3734      int status = CmtSystem::execute (cmd);
3735     
3736      if (status != 0)
3737        {
3738          CmtMessage::error ("Cannot create a symbolic link to " + libname);
3739          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3740          return (false);
3741        }
3742    }
3743
3744  return (true);
3745}
3746
3747
3748/**
3749   Centralize the construction of library links for this Use.
3750*/
3751void Use::build_library_links (const cmt_string& cmtinstallarea, 
3752                               const cmt_string& tag, 
3753                               const cmt_string& shlibsuffix, 
3754                               const cmt_string& symlinkcmd) const
3755{
3756  if (!located ())
3757    {
3758      CmtMessage::warning ("package " + get_package_name ()
3759                           + " " + version + " " + path
3760                           + " not found");
3761      /*
3762      if (!Cmt::get_quiet ())
3763        {
3764          cerr << "# package " << get_package_name () <<
3765            " " << version << " " << path <<
3766            " not found" <<
3767            endl;
3768        }
3769      */
3770      return;
3771    }
3772
3773  cmt_string s;
3774
3775  s = get_package_name ();
3776  s += "_libraries";
3777
3778  Symbol* libraries_macro = Symbol::find (s);
3779
3780  if (libraries_macro == 0) return;
3781
3782  cmt_string libraries = libraries_macro->build_macro_value ();
3783  Symbol::expand (libraries);
3784  static CmtSystem::cmt_string_vector values;
3785
3786  CmtSystem::split (libraries, " \t", values);
3787
3788  for (int j = 0; j < values.size (); j++)
3789    {
3790      const cmt_string& library = values[j];
3791
3792      static cmt_string libname;
3793      static cmt_string name;
3794
3795      // Is it a simple name or a complete path?
3796
3797      libname = library;
3798      Symbol::expand (libname);
3799
3800      bool is_absolute = false;
3801
3802      is_absolute = CmtSystem::absolute_path (libname);
3803
3804      if (is_absolute)
3805        {
3806          /**
3807           *   We assume here that "library" contains a complete path.
3808           *   (including the complete syntax libxxx.so)
3809           */
3810
3811          cmt_string suffix;
3812          CmtSystem::basename (library, name);
3813        }
3814      else
3815        {
3816          /**
3817           *   Here we expect that only the base name of the library
3818           *   is given : ie it should not contain the "lib" prefix,
3819           *   nor the suffix .so, nor any path prefix.
3820           *    This of course should generally correspond to a constituent name.
3821           */
3822         
3823          if (style != none_style)
3824            {
3825          libname = "${";
3826          libname += prefix;
3827          libname += "ROOT}/${";
3828          libname += get_package_name ();
3829          libname += "_tag}/";
3830            }
3831          else
3832            {
3833          libname = "${";
3834          libname += prefix;
3835          libname += "ROOT}/";
3836            }
3837          libname += "$(library_prefix)";
3838          libname += library;
3839          libname += "$(library_suffix)";
3840          libname += ".";
3841          libname += shlibsuffix;
3842
3843          name = "$(library_prefix)";
3844          name += library;
3845          name += "$(library_suffix)";
3846          name += ".";
3847          name += shlibsuffix;
3848        }
3849
3850      if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3851        {
3852          continue;
3853        }
3854
3855#ifdef __APPLE__
3856      if (!is_absolute)
3857        {
3858          if (style != none_style)
3859            {
3860          libname = "${";
3861          libname += prefix;
3862          libname += "ROOT}/${";
3863          libname += get_package_name ();
3864          libname += "_tag}/";
3865            }
3866          else
3867            {
3868          libname = "${";
3869          libname += prefix;
3870          libname += "ROOT}/";
3871            }
3872          libname += library;
3873          libname += ".bundle";
3874
3875          name = library;
3876          name += ".bundle";
3877         
3878          if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3879            {
3880              continue;
3881            }
3882        }
3883#endif
3884    }
3885}
3886
3887/**
3888 *   This function tries to get the replacement of a Use when it has
3889 *  been discarded by a better match to version constraints.
3890 */
3891Use* Use::get_selected_version ()
3892{
3893  if (!discarded) return (this);
3894
3895  Package* p = m_package;
3896
3897  Use::UsePtrVector& uses = p->get_uses ();
3898
3899  bool dbg = Cmt::get_debug ();
3900
3901  int size = uses.size ();
3902
3903  for (int i = 0; i < size; i++)
3904    {
3905      Use* u = uses[i];
3906      if (u == 0) continue;
3907      if (u->discarded) continue;
3908      if (dbg)
3909        {
3910          cout << "Use::get_selected_version> for package " << get_package_name ()
3911               << "  got a version " << u << endl;
3912        }
3913      return (u);
3914    }
3915
3916  return (0);
3917}
3918
3919/**
3920   Switching from one use to another one, (better wrt
3921   various criteria).
3922
3923   When switching, m_index and auto_imports are
3924   transfered from the un-selected to the newly selected.
3925*/
3926Use* Use::set_selected_version (Use* selected_use)
3927{
3928  if (this == selected_use) return (this);
3929
3930  static UsePtrVector& uses = get_ordered_uses ();
3931
3932  if (m_index >= 0)
3933    {
3934      // This discarded package was registered. We have to substitute
3935      // it with the new one.
3936
3937      if (Cmt::get_debug ())
3938        {
3939          cout << "set_selected_version> Replace "
3940               << get_package_name () << "(" << m_index << ")[" << this << "] with "
3941               << selected_use->get_package_name () << "(" << selected_use->m_index << ")[" << selected_use << "]" << endl;
3942        }
3943
3944      selected_use->m_index = m_index;
3945      selected_use->auto_imports = auto_imports;
3946
3947      selected_use->undiscard ();
3948
3949      m_index = -1;
3950
3951      uses[selected_use->m_index] = selected_use;
3952    }
3953
3954  discard ();
3955
3956  return (selected_use);
3957}
3958
3959//----------------------------------------------------------
3960void Use::set_auto_imports (State context_state, State specified_state,
3961                            cmt_map <Use*, bool>& visited)
3962{
3963  static int level (-1);
3964  level++;
3965  /*
3966  if (level == 0)
3967    {
3968      unselect_all ();
3969      selected = true;
3970    }
3971  */
3972  switch (context_state)
3973    {
3974    case Unspecified:
3975    case On:
3976      if (!visited.has (this) ||
3977          // revisit uses that may be turned into Off != auto_imports
3978          // via some other use(s)
3979          // policy being use has Off != auto_imports,
3980          // if it is (direct) sub-use without -no_auto_imports of
3981          // either current use or sub-use with Off != auto_imports
3982          (Off == auto_imports && Off != specified_state)
3983          )
3984        {
3985          auto_imports = specified_state;
3986          context_state = UseContext::mask_auto_imports (context_state, auto_imports);
3987        }
3988      else
3989        {
3990          level--;
3991          return;
3992        }
3993      break;
3994    case Off:
3995      if (visited.has (this))
3996        {
3997          level--;
3998          return;
3999        }
4000      auto_imports = context_state;
4001      break;
4002    }
4003
4004  if (Cmt::get_debug ())
4005    {
4006      cout << "Use::set_auto_imports>|";
4007      for (int i = level; i > 0; i--) cout << "-";
4008      cout << get_package_name () << "> " 
4009           << auto_imports << " -> " 
4010           << "(" << context_state << ")" << specified_state << endl;
4011    }
4012
4013  static bool yes (true);
4014  visited.add (this, yes);
4015
4016  cmt_string s;
4017  static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
4018 
4019  if (Cmt::get_debug ())
4020    {
4021      s = "Use::set_auto_imports><";
4022      for (int i = level; i > 0; i--) s += "-";
4023      s += get_package_name ();
4024      s += "|";
4025      //cout << s << endl;
4026    }
4027 
4028  for (int i = 0; i < sub_uses.size (); i++)
4029  //for (int i = sub_uses.size () - 1; i >= 0; i--)
4030    {
4031      State state = sub_use_auto_imports[i];
4032      if (Cmt::get_debug ())
4033        {
4034          s += " ";
4035          s += sub_uses[i]->get_package_name ();
4036          s += "(";
4037          s += state_text[state + 1];
4038          s += ")";
4039        }
4040      if (sub_uses[i]->m_index >= 0 && !sub_uses[i]->discarded)
4041        {
4042          sub_uses[i]->set_auto_imports (context_state, state, visited);
4043        }
4044      else
4045        {
4046          if (Cmt::get_debug ())
4047            {
4048              char num[32]; sprintf (num, "%#x", sub_uses[i]);
4049              char index[32]; sprintf (index, "%d", sub_uses[i]->m_index);
4050              s += "[";
4051              s += num;
4052              s += ", discarded=";
4053              s += (sub_uses[i]->discarded ? "1" : "0");
4054              s += ", m_index=";
4055              s += index;
4056              s += " : invalid]";
4057            }
4058          Use* au (find_valid (sub_uses[i]->get_package_name ()));
4059          if (au)
4060            {
4061              if (Cmt::get_debug ())
4062                {
4063                  char num[32]; sprintf (num, "%#x", au);
4064                  char index[32]; sprintf (index, "%d", au->m_index);
4065                  s += "[";
4066                  s += num;
4067                  s += ", discarded=";
4068                  s += (au->discarded ? "1" : "0");
4069                  s += ", m_index=";
4070                  s += index;
4071                  s += " : valid]";
4072                }
4073              au->set_auto_imports (context_state, state, visited);
4074            }
4075          else
4076            {
4077              visited.add (sub_uses[i], yes);
4078            }
4079        }
4080    }
4081
4082  if (Cmt::get_debug ())
4083    {
4084      cout << s << endl;
4085    }
4086
4087  level--;
4088  return;
4089}
4090/*
4091void Use::set_auto_imports (State new_state)
4092{
4093  if (Cmt::get_debug ())
4094    {
4095      cout << "Use::set_auto_imports>(" << get_package_name () << ") "
4096           << auto_imports << " -> " << new_state << endl;
4097    }
4098
4099  if (auto_imports == new_state) return;
4100 
4101  State old_state = auto_imports;
4102 
4103  auto_imports = new_state;
4104
4105  // We propagate only when we switch from Off to On
4106
4107  if ((old_state == Off) && (new_state == On))
4108    {
4109      cmt_string s;
4110      static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
4111
4112      if (Cmt::get_debug ())
4113        {
4114          s = "Use::set_auto_imports>(";
4115          s += get_package_name ();
4116          s += ") ";
4117
4118          cout << s << endl;
4119        }
4120
4121      for (int i = 0; i < sub_uses.size (); i++)
4122        {
4123          Use* u = sub_uses[i];
4124          State state = sub_use_auto_imports[i];
4125         
4126          if (Cmt::get_debug ())
4127            {
4128              s += " ";
4129              s += u->get_package_name ();
4130              s += "(";
4131              s += state_text[state + 1];
4132              s += ")";
4133            }
4134
4135          if (state == Unspecified)
4136            {
4137              u->set_auto_imports (On);
4138            }
4139        }
4140         
4141      if (Cmt::get_debug ())
4142        {
4143          cout << s << endl;
4144        }
4145    }
4146}
4147*/
4148
4149//----------------------------------------------------------
4150void Use::set_native_version (bool state)
4151{
4152  m_has_native_version = state;
4153}
4154
4155bool Use::has_native_version () const
4156{
4157  return (m_has_native_version);
4158}
4159
4160Package* Use::get_package () const
4161{
4162  return (m_package);
4163}
4164
4165const cmt_string& Use::get_package_name () const
4166{
4167  static const cmt_string null = "";
4168
4169  Package* p = m_package;
4170  if (p == 0) return (null);
4171
4172  return (p->get_name ());
4173}
4174
4175void Use::set_package_name (const cmt_string& name)
4176{
4177  Package* p = Package::add (name);
4178
4179  m_package = p;
4180  p->add_use (this);
4181}
4182
4183int Use::get_index () const
4184{
4185  return (m_index);
4186}
4187
4188//----------------------------------------------------------
4189bool Use::get_all_clients (const cmt_string& to_name)
4190{
4191  Use::UsePtrVector& uses = Use::get_ordered_uses ();
4192
4193  Use* use = Use::find (to_name);
4194
4195  if (use == 0)
4196    {
4197      //      CmtMessage::warning ("No access to " + to_name);
4198      return (false);
4199    }
4200
4201  cmt_map <cmt_string, Use*> all_clients;
4202  cmt_map <cmt_string, Use*> all_clients_ok;
4203
4204  const cmt_string& name = get_package_name ();
4205
4206  Use* me = this;
4207
4208  all_clients.add (name, me);
4209  all_clients_ok.add (name, me);
4210
4211  bool status = get_all_clients (use, to_name, all_clients, all_clients_ok); 
4212
4213  return (status);
4214}
4215
4216//----------------------------------------------------------
4217bool Use::get_all_clients (Use* to, 
4218                           const cmt_string& result, 
4219                           cmt_map <cmt_string, Use*>& all_clients, 
4220                           cmt_map <cmt_string, Use*>& all_clients_ok)
4221{
4222  if (this == to)
4223    {
4224      cout << result << endl;
4225      return (true);
4226    }
4227
4228  const cmt_string& to_name = to->get_package_name ();
4229  const cmt_string& to_version = to->version;
4230
4231  //cout << "gac> from " << get_package_name () << " to " << to_name << " -> " << result << endl;
4232
4233  if (all_clients.has (to_name))
4234    {
4235      if (all_clients_ok.has (to_name))
4236        {
4237          cout << "   ..." << result << endl;
4238          return (true);
4239        }
4240      else
4241        {
4242          return (false);
4243        }
4244    }
4245
4246  all_clients.add (to_name, to);
4247
4248  bool status = false;
4249
4250  Use::UsePtrVector& uses = Use::get_ordered_uses ();
4251  Use* use = 0;
4252
4253  for (int n = 0; n < uses.size (); ++n)
4254    {
4255      use = uses[n];
4256
4257      if (use->discarded) continue;
4258      if (use->m_hidden) continue;
4259
4260      if (!use->located ()) continue;
4261
4262      if (use == to) continue;
4263
4264      if (use->is_client (to_name, to_version))
4265        {
4266          const cmt_string& n = use->get_package_name ();
4267
4268          cmt_string r;
4269
4270          if ((use->initial_scope != ScopeUnspecified) &&
4271              (use->initial_scope != ScopePublic)) 
4272            {
4273              r += "(private)";
4274            }
4275         
4276          if (use->auto_imports == Off) r += "(no_auto_imports)";
4277
4278          r += n;
4279          r += ".";
4280          r += result;
4281
4282          //cout << "gac> " << n << " is client of " << to_name << endl;
4283
4284          if (get_all_clients (use, r, all_clients, all_clients_ok))
4285            {
4286              all_clients_ok.add (n, use);
4287              status = true;
4288            }
4289        }
4290    }
4291
4292  use = this;
4293
4294  if (use->is_client (to_name, to_version))
4295    {
4296      const cmt_string& n = use->get_package_name ();
4297     
4298      cmt_string r;
4299
4300      if ((use->initial_scope != ScopeUnspecified) &&
4301          (use->initial_scope != ScopePublic)) 
4302        {
4303          r += "(private)";
4304        }
4305     
4306      if (use->auto_imports == Off) r += "(no_auto_imports)";
4307
4308      r += n;
4309      r += ".";
4310      r += result;
4311     
4312      //cout << "gac> " << n << " is client of " << to_name << endl;
4313     
4314      if (get_all_clients (use, r, all_clients, all_clients_ok))
4315        {
4316          all_clients_ok.add (n, use);
4317          status = true;
4318        }
4319    }
4320
4321  return (status);
4322}
4323
4324/**
4325   Let's consider two packages in the use graph "this" and "to"
4326   This function finds all packages that are reached in between
4327   following all possible paths between "this" and "to"
4328
4329   Result s accumulated into "list"
4330*/
4331bool Use::get_paths (Use* to, UsePtrVector& list)
4332{
4333  bool is_in_path = false;
4334  bool cycle = false;
4335  bool already_in_path = false;
4336  bool dbg = Cmt::get_debug ();
4337
4338  static int level = 0;
4339
4340  int size = 0;
4341
4342  if (level == 0)
4343    {
4344      unselect_all ();
4345      selected = false;
4346    }
4347
4348  if (selected) 
4349    {
4350      /**
4351         If this use is already in the list, we don't duplicate the entry.
4352         (protection duplicate paths in the graph)
4353      */
4354
4355      size = list.size ();
4356
4357      for (int m = 0; m < size; m++)
4358        {
4359          Use* u = list[m];
4360          if (u == this)
4361            {
4362              if (dbg)
4363                {
4364                  for (int lll = 0; lll < level; lll++) cout << "  ";
4365                  cout << "  Use::get_paths." << level << "> try1.2 sub="
4366                       << get_package_name () << " already_in_path " << endl;
4367                }
4368             
4369              return (true);
4370            }
4371        }
4372
4373      return (false);
4374    }
4375
4376  selected = true;
4377
4378  if (dbg)
4379    {
4380      for (int lll = 0; lll < level; lll++) cout << "  ";
4381      cout << "Use::get_paths." << level << ">" << get_package_name ()
4382           << " to=" << to->get_package_name () 
4383           << " list=[";
4384
4385      for (int m = 0; m < list.size (); m++)
4386        {
4387          Use* u = list[m];
4388          cout << u->get_package_name () << " ";
4389        }
4390
4391      cout << "]" << endl;
4392    }
4393
4394  /**
4395     Now "this" is a candidate new entry in the list
4396  */
4397
4398  // First figure out whether 'to' is used by 'this'.
4399
4400  if (this->get_package_name () == to->get_package_name ())
4401    {
4402      // We've reached the goal (for the first time)
4403      is_in_path = true;
4404    }
4405  else
4406    {
4407      /**
4408         Let's scan sub_uses now
4409      */
4410      size = sub_uses.size ();
4411
4412      if (dbg)
4413        {
4414          for (int lll = 0; lll < level; lll++) cout << "  ";
4415          cout << "  Use::get_paths." << level << "> size=" << size << endl;
4416        }
4417
4418      for (int n = 0; n < size; n++)
4419        {
4420          Use* use = sub_uses[n];
4421
4422          if (use == 0) continue;
4423
4424          if (dbg)
4425            {
4426              for (int lll = 0; lll < level; lll++) cout << "  ";
4427              cout << "  Use::get_paths." << level << "> try1 sub="
4428                   << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
4429            }
4430
4431          if (use->discarded)
4432            {
4433              Use* u;
4434
4435              u = use->get_selected_version ();
4436              if (u == 0) 
4437                {
4438                  /**
4439                     No way to find a valid use for this used package.
4440                     Is that a bug?
4441                     Anyway we don't pursue on that branch.
4442                  */
4443                  continue;
4444                }
4445
4446              use = u;
4447            }
4448
4449          if (dbg)
4450            {
4451              for (int lll = 0; lll < level; lll++) cout << "  ";
4452              cout << "  Use::get_paths." << level << "> try2 sub="
4453                   << use->get_package_name () << " " << use->discarded << endl;
4454            }
4455
4456          level++;
4457          bool r = use->get_paths (to, list);
4458          level--;
4459
4460          if (r)
4461            {
4462              is_in_path = true;
4463            }
4464        }
4465    }
4466
4467  if (is_in_path)
4468    {
4469      if (dbg)
4470        {
4471          for (int lll = 0; lll < level; lll++) cout << "  ";
4472          cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
4473        }
4474      list.push_back (this);
4475    }
4476
4477  return (is_in_path);
4478}
4479
4480//----------------------------------------------------------
4481bool Use::located () const
4482{
4483  return (m_located);
4484}
4485
4486//----------------------------------------------------------
4487void Use::show_sub_uses (cmt_map <Use*, bool>& visited,
4488                         const cmt_string& request, State specified_state,
4489                         bool skip_discarded, ostream& out)
4490//void Use::show_sub_uses (const cmt_string& request, bool skip_discarded, ostream& out)
4491{
4492  if (skip_discarded && discarded) return;
4493  if (m_hidden) return;
4494
4495  Use* current = &(Use::current ());
4496  static State context_state (auto_imports);
4497  static int level (-1);
4498  level++;
4499
4500  if (level == 0)
4501    {
4502      unselect_all ();
4503      selected = true;
4504    }
4505
4506  State saved_context_state (context_state);
4507  switch (context_state)
4508    {
4509    case Unspecified:
4510    case On:
4511      if (!visited.has (this)
4512          || level == 1)
4513        // show all direct sub-uses of current use
4514        {
4515          context_state = UseContext::mask_auto_imports (context_state, specified_state);
4516        }
4517      else if (Off != auto_imports && Off != specified_state
4518               //      else if (specified_state == auto_imports && Off != specified_state
4519               && !selected)
4520        // show this sub-use as it may have been used to make Off != auto_imports
4521        // and is sufficient in order to consider it Off != auto_imports,
4522        // mark selected not to consider use again and thus avoid looping this way
4523        {
4524          selected = true;
4525          //      auto_imports = specified_state;
4526          context_state = UseContext::mask_auto_imports (context_state, specified_state);
4527        }
4528      else
4529        {
4530          level--;
4531          return;
4532        }
4533      break;
4534    case Off:
4535      if (visited.has (this)
4536          )
4537        {
4538          level--;
4539          return;
4540        }
4541      break;
4542    }
4543
4544  if (level > 0)
4545    {
4546      out << "# ";
4547      for (int n = 0; n < (level-1); n++) out << "  ";
4548
4549      if (request == "")
4550        {
4551          out << "use " << get_package_name () << " " << specified_version;
4552
4553          if (this == current) 
4554            {
4555              out << " (current)";
4556            }
4557          else
4558            {
4559              if (specified_path != "") out << " " << specified_path;
4560            }
4561        }
4562      else
4563        {
4564          out << "use " << request;
4565        }
4566
4567      if (version_alias != "")
4568        {
4569          out << " | " << version_alias << " " << path_alias;
4570        }
4571
4572      if (initial_scope == ScopeUnspecified) out << " (unspecified)";
4573      else if (initial_scope != ScopePublic) out << " (private)";
4574
4575      if (specified_state == Off) out << " (no_auto_imports)";
4576      //      if (auto_imports == Off) out << " (no_auto_imports)";
4577
4578      if (structuring_style == without_version_directory) out << " (no_version_directory)";
4579
4580      if (m_has_native_version)
4581        {
4582          cmt_string n = get_package_name ();
4583          n += "_native_version";
4584
4585          Symbol* s = Symbol::find (n);
4586          if (s != 0)
4587            {
4588              cmt_string value = s->resolve_macro_value ();
4589              out << " (native_version=" << value << ")";
4590            }
4591        }
4592
4593      out << endl;
4594    }
4595
4596  static bool yes (true);
4597  visited.add (this, yes);
4598
4599  for (int i = 0; i < sub_uses.size (); i++)
4600    {
4601      //if (use == 0) continue;
4602      Use* use;
4603      if (sub_uses[i]->m_index >= 0 && !sub_uses[i]->discarded)
4604        {
4605          use = sub_uses[i];
4606        }
4607      else
4608        {
4609          Use* au (find_valid (sub_uses[i]->get_package_name ()));
4610          if (au)
4611            {
4612              use = au;
4613            }
4614          else
4615            {
4616              visited.add (sub_uses[i], yes);
4617              continue;
4618            }
4619        }
4620
4621      const cmt_string& request = requests[i];
4622
4623      ScopeType saved_scope = use->initial_scope;
4624      //      State saved_state = use->auto_imports;
4625
4626      use->initial_scope = sub_use_scopes[i];
4627      //      use->auto_imports = sub_use_auto_imports[i];
4628
4629      use->show_sub_uses (visited, request, sub_use_auto_imports[i], skip_discarded, out);
4630      //use->show_sub_uses (request, skip_discarded, out);
4631
4632      use->initial_scope = saved_scope;
4633      //      use->auto_imports = saved_state;
4634    }
4635  level--;
4636
4637  context_state = saved_context_state;
4638}
4639
4640//----------------------------------------------------------
4641Use& Use::current ()
4642{
4643  static UseVector& instances = get_instances ();
4644  static Use* current_use = 0;
4645
4646  if ((current_use == 0) || (instances.size () == 0))
4647    {
4648      Use& use_object = instances.add ();
4649      current_use = &use_object;
4650    }
4651
4652  return (*current_use);
4653}
4654
4655//----------------------------------------------------------
4656const Use& Use::const_current ()
4657{
4658  const Use& use = Use::current ();
4659
4660  return (use);
4661}
4662
4663//----------------------------------------------------------
4664Use::UseVector& Use::get_instances ()
4665{
4666  static Database& db = Database::instance ();
4667  static UseVector& instances = db.all_uses ();
4668
4669  return (instances);
4670}
4671
4672//----------------------------------------------------------
4673Use::UsePtrVector& Use::get_ordered_uses ()
4674{
4675  static Database& db = Database::instance ();
4676  static UsePtrVector& uses = db.uses ();
4677
4678  return (uses);
4679}
4680
4681//----------------------------------------------------------
4682
4683//----------------------------------------------------------
4684//
4685//  Check if the specified version is better than the
4686//  current one.
4687//
4688//----------------------------------------------------------
4689Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
4690{
4691  Use* selected = ref_use;
4692
4693  int ref_v = -1;
4694  int ref_r = -1;
4695  int ref_p = -1;
4696  cmt_string ref_pp;
4697
4698  int new_v = -1;
4699  int new_r = -1;
4700  int new_p = -1;
4701  cmt_string new_pp;
4702
4703  int alias_v = -1;
4704  int alias_r = -1;
4705  int alias_p = -1;
4706  cmt_string alias_pp;
4707
4708  enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
4709
4710  // First analyze specified versions
4711  cmt_string ref_version = ref_use->specified_version;
4712  cmt_string new_version = new_use->specified_version;
4713
4714  CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
4715  ref_pp = ref_use->path;
4716
4717  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
4718  new_pp = new_use->path;
4719
4720  if (new_use->version_alias != "")
4721    {
4722      has_alias = new_has_alias;
4723      CmtSystem::is_version_directory (new_use->version_alias, 
4724                                       alias_v, alias_r, alias_p);
4725      alias_pp = new_use->path_alias;
4726    }
4727  else if (ref_use->version_alias != "")
4728    {
4729      has_alias = ref_has_alias;
4730      CmtSystem::is_version_directory (ref_use->version_alias, 
4731                                       alias_v, alias_r, alias_p);
4732      alias_pp = ref_use->path_alias;
4733    }
4734
4735  ref_use->undiscard ();
4736  new_use->undiscard ();
4737
4738  if (new_v != ref_v)
4739    {
4740      if (has_alias != no_alias)
4741        {
4742          if (has_alias == new_has_alias)
4743            {
4744              new_v = alias_v;
4745              new_r = alias_r;
4746              new_p = alias_p;
4747              new_pp = alias_pp;
4748            }
4749          else if (has_alias == ref_has_alias)
4750            {
4751              ref_v = alias_v;
4752              ref_r = alias_r;
4753              ref_p = alias_p;
4754              ref_pp = alias_pp;
4755            }
4756        }
4757    }
4758
4759  bool ref_v_wildcarded = ((ref_v) == -1);
4760  bool ref_r_wildcarded = ((ref_r) == -1);
4761  bool ref_p_wildcarded = ((ref_p) == -1);
4762
4763  bool ref_v_explicit = !ref_v_wildcarded;
4764  bool ref_r_explicit = !ref_r_wildcarded;
4765  bool ref_p_explicit = !ref_p_wildcarded;
4766
4767  bool new_v_wildcarded = ((new_v) == -1);
4768  bool new_r_wildcarded = ((new_r) == -1);
4769  bool new_p_wildcarded = ((new_p) == -1);
4770
4771  bool new_v_explicit = !new_v_wildcarded;
4772  bool new_r_explicit = !new_r_wildcarded;
4773  bool new_p_explicit = !new_p_wildcarded;
4774
4775  bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
4776
4777  cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
4778  cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
4779  cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
4780 
4781  cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
4782  cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
4783  cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
4784
4785  // Now compute effective version identifiers
4786  CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
4787  CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
4788
4789  cmt_string new_selected_version = new_use->version;
4790
4791  if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
4792    {
4793      /*
4794        if (verbose && !Cmt::get_quiet ())
4795        {
4796        cerr << "# Required explicit version " << new_version
4797        << " of package " << ref_use->get_package_name ()
4798        << " incompatible with selected explicit version " << ref_version
4799        << endl;
4800        }
4801
4802        CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
4803
4804        if (ref_use != new_use) new_use->discard ();
4805      */
4806
4807      if (new_v > ref_v)
4808        {
4809          if (verbose && !Cmt::get_quiet ())
4810            {
4811              cerr << "# Select " << new_vc << " version " << new_version
4812                   << " of package " << ref_use->get_package_name () 
4813                   << " instead of existing " << ref_vc << " " << ref_version
4814                   << endl;
4815            } 
4816         
4817          if (ref_use != new_use) ref_use->discard ();
4818          selected = new_use;
4819          selected->done = false; // Will read the new requirements
4820        }
4821    }
4822  else if (new_v_wildcarded || ref_v_wildcarded)
4823    {
4824      // at least one of ref or new is wildcarded
4825
4826      //
4827      // we plan to discard new_use, but if it was specified as explicit
4828      // and ref_use was wildcarded then new_use will win !!
4829      //
4830      // So then we'll have to understand where are the wild
4831      // cards... If they are on v or r, then we consider them.
4832      //
4833      //
4834
4835      if (ref_v_wildcarded && new_v_explicit)
4836        {
4837          if ((ref_use->real_path != new_use->real_path) ||
4838              (ref_use->version != new_use->version))
4839            {
4840              if (ref_use != new_use) ref_use->discard ();
4841              selected = new_use;
4842              selected->done = false; // Will read the new requirements
4843
4844              if (verbose && !Cmt::get_quiet ())
4845                {
4846                  cerr << "# Select explicit version " << new_version
4847                       << "(" << new_use->version << ")" 
4848                       << " of package " << ref_use->get_package_name () 
4849                       << " instead of existing wildcarded " << ref_version
4850                       << "(" << ref_use->version << ")" 
4851                       << endl;
4852                }
4853            }
4854          else
4855            {
4856              if (ref_use != new_use) new_use->discard ();
4857              //ref_use->version = new_selected_version;
4858            }
4859        }
4860      else
4861        {
4862          // ref is explicit or new is wildcarded
4863
4864          /*
4865            if (verbose && !Cmt::get_quiet ())
4866            {
4867            cerr << "# keep " << ref_vc << " version " << ref_version
4868            << " of package " << ref_use->get_package_name ()
4869            << " (ignore " << new_vc << " version " << new_version << ")"
4870            << endl;
4871            }
4872          */
4873
4874          if (ref_use != new_use) new_use->discard ();
4875        }
4876    }
4877  else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
4878    {
4879      //
4880      // we plan to discard new_use, but if it was specified as explicit
4881      // and ref_use was wildcarded then new_use will win !!
4882      //
4883      // So then we'll have to understand where are the wild
4884      // cards... If they are on v or r, then we consider them.
4885      //
4886      //
4887
4888      if (ref_r_wildcarded && new_r_explicit)
4889        {
4890          // ref has wild card and new has not => new wins
4891
4892          if ((ref_use->real_path != new_use->real_path) ||
4893              (ref_use->version != new_use->version))
4894            {
4895              if (ref_use != new_use) ref_use->discard ();
4896              selected = new_use;
4897              selected->done = false; // Will read the new requirements
4898
4899              if (verbose && !Cmt::get_quiet ())
4900                {
4901                  cerr << "# Select explicit release " << new_version
4902                       << " of package " << ref_use->get_package_name ()
4903                       << " instead of existing wildcarded " << ref_version
4904                       << endl;
4905                } 
4906            }
4907          else
4908            {
4909              // Just adapt version with new one.
4910
4911              if (ref_use != new_use) new_use->discard ();
4912              //ref_use->version = new_selected_version;
4913            }
4914        }
4915      else
4916        {
4917          /*
4918            if (verbose &&!Cmt::get_quiet ())
4919            {
4920            cerr << "# keep " << ref_rc << " release " << ref_version
4921            << " of package " << ref_use->get_package_name ()
4922            << " (ignore " << new_rc << " release " << new_version << ")"
4923            << endl;
4924            }
4925          */
4926
4927          if (ref_use != new_use) new_use->discard ();
4928        }
4929    }
4930  else if (new_r > ref_r)
4931    {
4932      if (verbose && !Cmt::get_quiet ())
4933        {
4934          cerr << "# Select " << new_rc << " release " << new_version
4935               << " of package " << ref_use->get_package_name () 
4936               << " instead of existing " << ref_rc << " " << ref_version
4937               << endl;
4938        } 
4939
4940      if (ref_use != new_use) ref_use->discard ();
4941      selected = new_use;
4942      selected->done = false; // Will read the new requirements
4943    }
4944  else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
4945    {
4946      //
4947      // we plan to discard new_use, but if it was specified as explicit
4948      // and ref_use was wildcarded then new_use will win !!
4949      //
4950
4951      if (ref_p_wildcarded && new_p_explicit)
4952        {
4953          if ((ref_use->real_path != new_use->real_path) ||
4954              (ref_use->version != new_use->version))
4955            {
4956              if (ref_use != new_use) ref_use->discard ();
4957              selected = new_use;
4958              selected->done = false; // Will read the new requirements
4959
4960              if (verbose && !Cmt::get_quiet ())
4961                {
4962                  cerr << "# Select explicit patch " << new_version
4963                       << " of package " << ref_use->get_package_name () 
4964                       << " instead of existing wildcarded " << ref_version
4965                       << endl;
4966                }
4967            }
4968          else
4969            {
4970              if (ref_use != new_use) new_use->discard ();
4971              ref_use->version = new_selected_version;
4972            }
4973        }
4974      else
4975        {
4976          /*
4977            if (verbose && !Cmt::get_quiet ())
4978            {
4979            cerr << "# keep " << ref_pc << " patch " << ref_version
4980            << " [" << ref_use->specified_version << "]"
4981            << " of package " << ref_use->get_package_name ()
4982            << " (ignore " << new_pc << " version " << new_version << ")"
4983            << " [" << new_use->specified_version << "]"
4984            << endl;
4985            }
4986          */
4987
4988          if (ref_use != new_use) new_use->discard ();
4989        }
4990    }
4991  else if (new_p > ref_p)
4992    {
4993      if (verbose && !Cmt::get_quiet ())
4994        {
4995          cerr << "# Select " << new_pc << " patch " << new_version
4996               << " of package " << ref_use->get_package_name () 
4997               << " instead of existing " << ref_pc << " " << ref_version
4998               << endl;
4999        }
5000
5001      if (ref_use != new_use) ref_use->discard ();
5002      selected = new_use;
5003      selected->done = false; // Will read the new requirements
5004    }
5005  else if (new_pp != ref_pp) // same version-r-p but from different path
5006    {
5007      if (ref_use != new_use) ref_use->discard ();
5008      selected = new_use;
5009      selected->done = false; // Will read the new requirements
5010    }
5011
5012  return (selected);
5013}
5014
5015
5016//----------------------------------------------------------
5017class VersionReader : public Awk
5018{
5019public:
5020
5021  VersionReader ()
5022  {
5023  }
5024 
5025  const cmt_string& get_version () const
5026  {
5027    return (m_version);
5028  }
5029 
5030  void filter (const cmt_string& line)
5031  {
5032    CmtSystem::cmt_string_vector words;
5033    CmtSystem::split (line, " \t", words);
5034    if (words[0] == "version")
5035      {
5036        m_version = words[1];
5037      }
5038  }
5039 
5040private:
5041  cmt_string m_version;
5042};
5043
5044//----------------------------------------------------------
5045class PackageReader : public Awk
5046{
5047public:
5048
5049  PackageReader ()
5050  {
5051  }
5052 
5053  const cmt_string& get_package () const
5054  {
5055    return (m_package);
5056  }
5057 
5058  void filter (const cmt_string& line)
5059  {
5060    CmtSystem::cmt_string_vector words;
5061    CmtSystem::split (line, " \t", words);
5062    if (words[0] == "package")
5063      {
5064        m_package = words[1];
5065      }
5066  }
5067 
5068private:
5069  cmt_string m_package;
5070};
5071
5072//----------------------------------------------------------
5073Package* Package::find (const cmt_string& name)
5074{
5075  static PackageMap& PackageMap = package_map ();
5076
5077  Package* result = 0;
5078
5079  result = PackageMap.find (name);
5080
5081  return (result);
5082}
5083
5084//----------------------------------------------------------
5085Package* Package::add (const cmt_string& name)
5086{
5087  static PackageVector& Packages = packages ();
5088  static PackageMap& PackageMap = package_map ();
5089
5090  {
5091    Package* package;
5092
5093    package = find (name);
5094    if (package != 0) return (package);
5095  }
5096
5097  Package& package = Packages.add ();
5098  PackageMap.add (name, package);
5099
5100  package.m_name = name;
5101
5102  if (name == "CMT")
5103    {
5104      package.m_is_cmt = true;
5105    }
5106  else if (name == "methods")
5107    {
5108      package.m_is_cmt = true;
5109    }
5110
5111  if (Cmt::get_debug ())
5112    {
5113      cout << "Package::add (" << name << ")" << endl;
5114    }
5115
5116  return (&package);
5117}
5118
5119//----------------------------------------------------------
5120Package::PackageVector& Package::packages ()
5121{
5122  static Database& db = Database::instance ();
5123  static PackageVector& Packages = db.packages ();
5124
5125  return (Packages);
5126}
5127
5128//----------------------------------------------------------
5129Package::PackageMap& Package::package_map ()
5130{
5131  static Database& db = Database::instance ();
5132  static PackageMap& PackageMap = db.package_map ();
5133
5134  return (PackageMap);
5135}
5136
5137//----------------------------------------------------------
5138void Package::clear_all ()
5139{
5140  static PackageVector& Packages = packages ();
5141  static PackageMap& PackageMap = package_map ();
5142
5143  PackageMap.clear ();
5144  Packages.clear ();
5145}
5146
5147//----------------------------------------------------------
5148bool Package::get_version (cmt_string& version, const cmt_string& path)
5149{
5150  cmt_string version_file = path;
5151  version_file += CmtSystem::file_separator ();
5152  version_file += get_version_file_name ();
5153  if (CmtSystem::test_file (version_file))
5154    {
5155      cmt_string v;
5156      if (v.read (version_file))
5157        {
5158          int pos;
5159          pos = v.find ('\n');
5160          if (pos != cmt_string::npos) v.erase (pos);
5161          pos = v.find ('\r');
5162          if (pos != cmt_string::npos) v.erase (pos);
5163          if (v != "")
5164            {
5165              version = v;
5166              return true;
5167            }
5168        }
5169      else
5170        {
5171          CmtMessage::warning ("Could not read `" + version_file + "'.");
5172        }
5173    }
5174
5175  version_file = path;
5176  version_file += CmtSystem::file_separator ();
5177  version_file += "requirements";
5178  cmt_string text;
5179  if (text.read (version_file))
5180    {
5181      VersionReader reader;
5182      reader.run (text);
5183      cmt_string v = reader.get_version ();
5184      if (v != "")
5185        {
5186          version = v;
5187          return true;
5188        }
5189    }
5190  else
5191    {
5192      CmtMessage::warning ("Could not read `" + version_file + "'.");
5193    }
5194
5195  return false;
5196}
5197
5198//----------------------------------------------------------
5199const cmt_string& Package::get_version_file_name ()
5200{
5201  static const cmt_string name = "version.cmt";
5202
5203  return (name);
5204}
5205
5206//----------------------------------------------------------
5207bool Package::get_name (cmt_string& name, const cmt_string& path)
5208{
5209  cmt_string name_file = path;
5210  name_file += CmtSystem::file_separator ();
5211  name_file += "requirements";
5212  cmt_string text;
5213  if (text.read (name_file))
5214    {
5215      PackageReader reader;
5216      reader.run (text);
5217      cmt_string v = reader.get_package ();
5218      if (v != "")
5219        {
5220          name = v;
5221          return true;
5222        }
5223    }
5224  else
5225    {
5226      CmtMessage::warning ("Could not read `" + name_file + "'.");
5227    }
5228
5229  return false;
5230}
5231
5232//----------------------------------------------------------
5233Package::Package () : m_is_cmt (false)
5234{
5235  if (Cmt::get_debug ())
5236    {
5237      cout << "Package::Package" << endl;
5238    }
5239}
5240
5241//----------------------------------------------------------
5242Package::~Package ()
5243{
5244  m_name = "";
5245}
5246
5247//----------------------------------------------------------
5248const cmt_string& Package::get_name () const
5249{
5250  return (m_name);
5251}
5252
5253//----------------------------------------------------------
5254void Package::add_use (Use* use)
5255{
5256  for (int i = 0; i < m_uses.size (); i++)
5257    {
5258      Use* u = m_uses[i];
5259      if (u == use) return;
5260    }
5261
5262  m_uses.push_back (use);
5263}
5264
5265//----------------------------------------------------------
5266void Package::remove_use (Use* use)
5267{
5268  if (Cmt::get_debug ())
5269    {
5270      cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
5271      cout << "  name=" << m_name
5272           << " uses=" << m_uses.size () << endl;
5273    }
5274
5275  Use::UsePtrVector temp;
5276
5277  temp = m_uses;
5278
5279  m_uses.clear ();
5280
5281  for (int i = 0; i < temp.size (); i++)
5282    {
5283      Use* u = temp[i];
5284      if (u != use)
5285        {
5286          m_uses.push_back (u);
5287        }
5288    }
5289}
5290
5291//----------------------------------------------------------
5292Use::UsePtrVector& Package::get_uses ()
5293{
5294  return (m_uses);
5295}
5296
5297//----------------------------------------------------------
5298bool Package::is_cmt ()
5299{
5300  return (m_is_cmt);
5301}
5302
5303//----------------------------------------------------------
5304static void show_packages ()
5305{
5306  Package::PackageVector& vector = Package::packages ();
5307
5308  int i;
5309  int j;
5310
5311  cout << "### Packages: ";
5312  for (i = 0; i < vector.size (); i++)
5313    {
5314      Package& p = vector[i];
5315      cout << p.get_name () << "[";
5316      Use::UsePtrVector& uses = p.get_uses ();
5317      for (j = 0; j < uses.size (); j++)
5318        {
5319          Use* u = uses[j];
5320          cout << u << ",";
5321        }
5322
5323      cout << "] ";
5324    }
5325  cout << endl;
5326
5327  {
5328    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
5329
5330    cout << "### Uses: ";
5331    for (i = 0; i < uses.size (); i++)
5332      {
5333        Use* u = uses[i];
5334        cout << "[" << u << "]" << u->get_package_name () << " ";
5335      }
5336  }
5337
5338  cout << endl;
5339}
5340
5341//----------------------------------------------------------
5342Project* Use::get_project ()
5343{   
5344  Project* p;
5345  cmt_string cmtpath = "";
5346  cmt_string offset  = "";   
5347  get_cmtpath_and_offset (cmtpath, offset);
5348  p = Project::find_by_cmtpath (cmtpath);
5349  return p;   
5350}
5351
5352//----------------------------------------------------------
5353cmt_string Use::get_info () const
5354{   
5355  return get_package_name () + " " + (version != "" ? version : "*") +
5356    (path != "" ? " " + path : "") ;
5357  //  return get_package_name () + " " + version + (path != "" ? " " + path : "") ;
5358}
5359
5360//----------------------------------------------------------
5361/**
5362 *    Check whether @version@
5363 *    is head version as specified by CMTHEADVERSION symbol/environment variable
5364 *    or equals HEAD|head
5365 */
5366//----------------------------------------------------------
5367bool Use::is_head_version (const cmt_string& version)
5368{
5369  if (!m_head_version.is_valid ())
5370    {
5371      cmt_string s (Symbol::get_env_value ("CMTHEADVERSION"));
5372      static const cmt_string package_template = "<package>";
5373      s.replace_all (package_template, get_package_name ());
5374      static const cmt_string PACKAGE_template = "<PACKAGE>";
5375      s.replace_all (PACKAGE_template, prefix);
5376      static const cmt_string revision_template = "<revision>";
5377      s.replace_all (revision_template.c_str (), "[0-9]*");
5378      if (0 != s.size ())
5379        {
5380          if ('^' != s[0]) s = "^" + s;
5381          if ('$' != s[s.size () - 1]) s = s + "$";
5382        }
5383      else
5384        {
5385          s = "^(HEAD|head)$";
5386        }
5387      m_head_version.set (s);
5388      if (!m_head_version.is_valid ())
5389        {
5390          CmtMessage::warning
5391            (CmtError::get_error_name (CmtError::configuration_error)
5392             + ": CMTHEADVERSION regular expression invalid `" + s + "'");
5393        }
5394    }
5395
5396  return m_head_version.match (version);
5397}
Note: See TracBrowser for help on using the repository browser.