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

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

See C.L. 460

  • Property svn:eol-style set to native
File size: 128.6 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{
1255  if (0 == uses.size ()) return;
1256
1257  static int level (0);
1258  if (level == 0)
1259    {
1260      unselect_all ();
1261      Use::current().select ();
1262    }
1263
1264  if (Cmt::get_debug ())
1265    {
1266      cout << "Use::set_auto_imports_state>|";
1267      for (int i = level; i > 0; i--) cout << "-";
1268      for (int i = 0; i < uses.size (); i++)
1269      //for (int i = uses.size () - 1; i >= 0; i--)
1270        {
1271          cout << " " << uses[i]->get_package_name ()
1272               << "(" << uses[i]->auto_imports << ")";
1273        }
1274      cout << ">" << endl;
1275    }
1276
1277  for (int i = 0; i < uses.size (); i++)
1278  //for (int i = uses.size () - 1; i >= 0; i--)
1279    {
1280      const Use* use = uses[i];
1281      if (!auto_imports_states[use->m_index])
1282        auto_imports_states[use->m_index] = true;
1283    }
1284
1285  Use::UsePtrVector subuses;
1286  for (int k = 0; k < uses.size (); k++)
1287  //for (int i = uses.size () - 1; i >= 0; i--)
1288    {
1289      Use* use = uses[k];
1290      if (use->is_selected ()) continue;
1291      use->select ();
1292      for (int i = 0; i < use->sub_uses.size (); i++)
1293        {
1294          if (use->sub_uses[i]->m_index >= 0 && !use->sub_uses[i]->discarded)
1295            {
1296              if (use->sub_use_auto_imports[i] != Off
1297                  && !use->sub_uses[i]->is_selected ())
1298                {
1299                  subuses.push_back (use->sub_uses[i]);
1300                }
1301            }
1302          else
1303            {
1304              if (Cmt::get_debug ())
1305                {
1306                  cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1307                       << " -> sub_use " << use->sub_uses[i]->get_package_name ()
1308                       << "[" << use->sub_uses[i] << ", discarded="
1309                       << use->sub_uses[i]->discarded << ", m_index="
1310                       << use->sub_uses[i]->m_index << " : invalid]" << endl;
1311                }
1312              Use* au (find_valid (use->sub_uses[i]->get_package_name ()));
1313              if (au)
1314                {
1315                  if (Cmt::get_debug ())
1316                    {
1317                      cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1318                           << " -> sub_use " << au->get_package_name ()
1319                           << "[" << au << ", discarded="
1320                           << au->discarded << ", m_index="
1321                           << au->m_index << " : valid]" << endl;
1322                    }
1323                  if (use->sub_use_auto_imports[i] != Off
1324                      && !au->is_selected ())
1325                    {
1326                      subuses.push_back (au);
1327                    }
1328                }
1329              else
1330                {
1331                  use->sub_uses[i]->select ();
1332                }
1333            }
1334        }
1335    }
1336
1337  level++;
1338  Use::set_auto_imports_state (subuses, auto_imports_states);
1339  level--;
1340
1341  if (Cmt::get_debug ())
1342    {
1343      cout << "Use::set_auto_imports_state><";
1344      for (int i = level; i > 0; i--) cout << "-";
1345      for (int i = 0; i < uses.size (); i++)
1346      //for (int i = uses.size () - 1; i >= 0; i--)
1347        {
1348          cout << " " << uses[i]->get_package_name ()
1349               << "(" << (auto_imports_states[uses[i]->m_index] ? "+" : "-") << ")";
1350        }
1351      cout << "|" << endl;
1352    }
1353
1354  return;
1355}
1356
1357//----------------------------------------------------------
1358void Use::set_auto_imports_state (const Use::UsePtrVector& uses,
1359                                  cmt_vector<bool>& auto_imports_states,
1360                                  cmt_map <Use*, bool>& visited)
1361{
1362  if (0 == uses.size ()) return;
1363  static bool yes (true);
1364
1365  static int level (-1);
1366  level++;
1367  if (level == 0)
1368    {
1369      unselect_all ();
1370    }
1371
1372  if (Cmt::get_debug ())
1373    {
1374      cout << "Use::set_auto_imports_state>|";
1375      for (int i = level; i > 0; i--) cout << "-";
1376      for (int i = 0; i < uses.size (); i++)
1377      //for (int i = uses.size () - 1; i >= 0; i--)
1378        {
1379          cout << " " << uses[i]->get_package_name ()
1380               << "(" << uses[i]->auto_imports << ")";
1381        }
1382      cout << ">" << endl;
1383    }
1384
1385  for (int i = 0; i < uses.size (); i++)
1386  //for (int i = uses.size () - 1; i >= 0; i--)
1387    {
1388      Use* use = uses[i];
1389      if (visited.has (use) &&
1390          (0 != level || use->is_selected ()))
1391        // revisit uses specified explicitly with -import=<package> (level == 0)
1392        // encountered in constituent specification for the first time (selected == false)
1393        // to ensure <package> is imported
1394        {
1395          continue;
1396        }
1397
1398      visited.add (use, yes);
1399      if (0 == level) use->select ();
1400
1401      if (!auto_imports_states[use->m_index])
1402        auto_imports_states[use->m_index] = true;
1403      //if (0 == level && use->is_selected ()) continue;
1404
1405      Use::UsePtrVector subuses;
1406      for (int i = 0; i < use->sub_uses.size (); i++)
1407        {
1408          if (use->sub_uses[i]->m_index >= 0 && !use->sub_uses[i]->discarded)
1409            {
1410              if (use->sub_use_auto_imports[i] != Off)
1411                {
1412                  subuses.push_back (use->sub_uses[i]);
1413                }
1414              else
1415                {
1416                  visited.add (use->sub_uses[i], yes);
1417                }
1418            }
1419          else
1420            {
1421              if (Cmt::get_debug ())
1422                {
1423                  cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1424                       << " -> sub_use " << use->sub_uses[i]->get_package_name ()
1425                       << "[" << use->sub_uses[i] << ", discarded="
1426                       << use->sub_uses[i]->discarded << ", m_index="
1427                       << use->sub_uses[i]->m_index << " : invalid]" << endl;
1428                }
1429              Use* au (find_valid (use->sub_uses[i]->get_package_name ()));
1430              if (au)
1431                {
1432                  if (Cmt::get_debug ())
1433                    {
1434                      cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1435                           << " -> sub_use " << au->get_package_name ()
1436                           << "[" << au << ", discarded="
1437                           << au->discarded << ", m_index="
1438                           << au->m_index << " : valid]" << endl;
1439                    }
1440                  if (use->sub_use_auto_imports[i] != Off)
1441                    {
1442                      subuses.push_back (au);
1443                    }
1444                  else
1445                    {
1446                      visited.add (au, yes);
1447                    }
1448                }
1449              else
1450                {
1451                  visited.add (use->sub_uses[i], yes);
1452                }
1453            }
1454        }
1455      Use::set_auto_imports_state (subuses, auto_imports_states, visited);
1456    }
1457
1458  if (Cmt::get_debug ())
1459    {
1460      cout << "Use::set_auto_imports_state><";
1461      for (int i = level; i > 0; i--) cout << "-";
1462      for (int i = 0; i < uses.size (); i++)
1463      //for (int i = uses.size () - 1; i >= 0; i--)
1464        {
1465          cout << " " << uses[i]->get_package_name ()
1466               << "(" << (auto_imports_states[uses[i]->m_index] ? "+" : "-") << ")";
1467        }
1468      cout << "|" << endl;
1469    }
1470
1471  level--;
1472  return;
1473}
1474
1475/**
1476 *   1) Given a Use object identified by its index in the ordered_uses() array,
1477 *   2) Given a vector of states containing the auto_imports states of all uses,
1478 *
1479 *     we want to switch to 'On' the auto_imports states of all
1480 *     sub_uses of the argument that were Off.
1481 *
1482 */
1483 /*
1484void Use::set_auto_imports_state (int use_index,
1485                                  cmt_vector<bool>& auto_imports_states)
1486{
1487  // check boundaries (this should be an error when out bondaries)
1488  if ((use_index < 0) || (use_index >= auto_imports_states.size ())) return;
1489
1490  Use::UsePtrVector& uses = Use::get_ordered_uses ();
1491
1492  if (Cmt::get_debug ())
1493    {
1494      int i;
1495     
1496      cout << "Use::set_auto_imports_state> use_index=" << use_index << " ";
1497     
1498      for (i = 0; i < auto_imports_states.size (); i++)
1499        {
1500          cout << (auto_imports_states[i] ? "|" : "o");
1501        }
1502
1503      for (i = 0; i < auto_imports_states.size (); i++)
1504        {
1505          cout << " " << (uses[i])->get_package_name ();
1506        }
1507
1508      cout << endl;
1509    }
1510
1511  // check if this is already done (recursivity ending)
1512  if (auto_imports_states[use_index]) return;
1513  auto_imports_states[use_index] = true;
1514
1515  Use* use = uses[use_index];
1516
1517  // We only have to deal with Use objects that were
1518  // actually turned Off
1519  //  if (use->auto_imports != Off) return;
1520  */
1521  /**
1522   *  Here, use points to a Use object which had been declared as
1523   *  no_auto_imports. But we need to switch it On. Therefore,
1524   *
1525   *    1) the state in auto_imports_states has to be set On
1526   *    2) the operation has to be recursively propagated to all
1527   *         sub_uses which also had no_auto_imports. (only to those)
1528   * 
1529   */
1530 
1531  //  auto_imports_states[use_index] = true;
1532  /*
1533  cmt_string s;
1534  static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
1535 
1536  if (Cmt::get_debug ())
1537    {
1538      s = "Use::set_auto_imports_state>(";
1539      s += use->get_package_name ();
1540      s += ")";
1541      //cout << s << endl;
1542    }
1543
1544  int size = use->sub_uses.size ();
1545  for (int i = 0; i < size; i++)
1546    {
1547      Use* u = use->sub_uses[i];
1548
1549      // first find the index of this use.
1550     
1551      int j = u->m_index;
1552
1553      if (Cmt::get_debug ())
1554        {
1555          char num[32]; sprintf (num, "%#x", u);
1556          s += " ";
1557          s += use->sub_uses[i]->get_package_name ();
1558          s += "(";
1559          s += state_text[use->sub_use_auto_imports[i] + 1];
1560          s += ")[p=";
1561          s += num;
1562          s += "]";
1563        }
1564     
1565      if (j >= 0)
1566        {
1567          if (use->sub_use_auto_imports[i] != Off)
1568            {
1569              set_auto_imports_state (j, auto_imports_states);
1570            }
1571  */
1572          /*
1573          if (u->sub_use_auto_imports[i] == Off)
1574            {
1575              set_auto_imports_state (j, auto_imports_states);
1576            }
1577          else
1578            {
1579              auto_imports_states[j] = true;
1580            }
1581            */
1582  /*
1583        }
1584      else
1585        {
1586          if (Cmt::get_debug ())
1587            {
1588              cout << "Use::set_auto_imports_state> " << use->get_package_name ()
1589                   << ": sub_use " << u->get_package_name () << "[" << u
1590                   << "] invalid" << endl;
1591            }
1592        }
1593    }
1594  if (Cmt::get_debug ())
1595    {
1596      cout << s << endl;
1597    }
1598}
1599  */
1600//----------------------------------------------------------
1601//
1602//  Move use to the end
1603//
1604//----------------------------------------------------------
1605void Use::move (Use* use)
1606{
1607  if (use == 0) return;
1608
1609  static UsePtrVector& uses = get_ordered_uses ();
1610
1611  int size = uses.size ();
1612
1613  if (size == 0) return;
1614
1615  //
1616  // On se positionne sur le pointeur.
1617  //
1618
1619  int use_index = use->m_index;
1620
1621  if (use_index < 0) return;
1622
1623  //
1624  // On deplace tous les pointeurs d'une case en arriere
1625  //
1626  for (use_index++; use_index < size; use_index++)
1627    {
1628      Use* u = uses[use_index];
1629      u->m_index--;
1630
1631      uses[use_index - 1] = uses[use_index];
1632    }
1633
1634  //
1635  // use est donc replace en derniere position
1636  //
1637
1638  use->m_index = size - 1;
1639  uses[size - 1] = use;
1640}
1641
1642/**
1643 *   Reorder provider versus client in the UsePtrVector list,
1644 *  so that the order reflects the fact that client makes use of provider.
1645 *   The result should be that provider appears before client in the list.
1646 */
1647void Use::reorder (Use* provider, Use* client)
1648{
1649  static UsePtrVector& uses = get_ordered_uses ();
1650
1651  int use_index;
1652
1653  int size = uses.size ();
1654
1655  if (size == 0) return;
1656  if (provider == client) return;
1657
1658  //
1659  // First locate the two use objects into the uses vector.
1660  //   -> provider_index and client_index
1661  //
1662
1663  int provider_index = -1;
1664  int client_index = -1;
1665
1666  provider_index = provider->m_index;
1667  client_index = client->m_index;
1668
1669  if (Cmt::get_debug ())
1670    {
1671      cout << "Use::reorder> provider=" << provider_index << " client=" << client_index << endl;
1672    }
1673
1674  //
1675  // Both objects must be installed in uses before acting.
1676  //
1677  if (provider_index == -1) return;
1678  if (client_index == -1) return;
1679
1680  if (client_index < provider_index)
1681    {
1682      //
1683      // client is already before provider so job is finished
1684      //
1685      return;
1686    }
1687
1688  //
1689  // before : <a a a P b b b C c c c>
1690  //                 ^       ^
1691  //                 ip      ic
1692  //
1693  //  1) move "P b b b" by one place to the right
1694  // thus :   <a a a P P b b b c c c>
1695  //
1696  //  2) move "C" to [ip]
1697  //
1698  // after  : <a a a C P b b b c c c>
1699  //
1700 
1701  for (use_index = client_index - 1; use_index >= provider_index; use_index--)
1702    {
1703      Use* use = uses[use_index];
1704      use->m_index++;
1705
1706      uses[use_index + 1] = uses[use_index];
1707    }
1708 
1709  uses[provider_index] = client;
1710  client->m_index = provider_index;
1711}
1712
1713//----------------------------------------------------------
1714void Use::clear_all ()
1715{
1716  static UsePtrVector& uses = get_ordered_uses ();
1717  static UseVector& instances = get_instances ();
1718
1719  int use_index;
1720
1721  for (use_index = 0; use_index < instances.size (); use_index++)
1722    {
1723      Use& use = instances[use_index];
1724      use.clear ();
1725    }
1726
1727  uses.clear ();
1728  instances.clear ();
1729}
1730
1731//----------------------------------------------------------
1732void Use::unselect_all ()
1733{
1734  static UsePtrVector& uses = get_ordered_uses ();
1735
1736  int use_index;
1737
1738  int size = uses.size ();
1739
1740  if (size == 0) return;
1741
1742  for (use_index = 0; use_index < size; use_index++)
1743    {
1744      Use* use = uses[use_index];
1745
1746      if (use != 0)
1747        {
1748          use->unselect ();
1749        }
1750    }
1751}
1752
1753//----------------------------------------------------------
1754void Use::undiscard_all ()
1755{
1756  static UsePtrVector& uses = get_ordered_uses ();
1757
1758  int use_index;
1759
1760  if (uses.size () == 0) return;
1761
1762  for (use_index = 0; use_index < uses.size (); use_index++)
1763    {
1764      Use* use = uses[use_index];
1765
1766      if (use != 0)
1767        {
1768          use->undiscard ();
1769        }
1770    }
1771}
1772
1773//----------------------------------------------------------
1774void Use::fill_macro_all (cmt_string& buffer, const cmt_string& suffix)
1775{
1776  UsePtrVector& uses = get_ordered_uses ();
1777
1778  buffer = "macro_append use_";
1779  buffer += suffix;
1780  buffer += " \" ";
1781  (Use::current()).fill_macro (buffer, suffix);
1782
1783  for (int number = 0; number < uses.size (); number++)
1784    {
1785      Use* use = uses[number];
1786     
1787      Package* p = use->get_package ();
1788      if (p->is_cmt ()) continue;
1789
1790      if (use->discarded) continue;
1791      if (use->auto_imports == Off) continue;
1792
1793      use->fill_macro (buffer, suffix);
1794    }
1795 
1796  buffer += "\"";
1797}
1798
1799//----------------------------------------------------------
1800Use::Use ()
1801{
1802  done = false;
1803  discarded = false;
1804  auto_imports = Unspecified;
1805  m_package = 0;
1806  m_index = -1;
1807  native_version = "";
1808
1809  clear ();
1810}
1811
1812//----------------------------------------------------------
1813Use::Use (const cmt_string& new_package,
1814          const cmt_string& new_version,
1815          const cmt_string& new_path)
1816{
1817  auto_imports = Unspecified;
1818  m_located = false;
1819  m_package = 0;
1820  m_index = -1;
1821
1822  set (new_package, new_version, new_path);
1823}
1824
1825//----------------------------------------------------------
1826Use::~Use ()
1827{
1828  clear ();
1829}
1830
1831//----------------------------------------------------------
1832void Use::clear ()
1833{
1834  specified_path = "";
1835  path      = "";
1836
1837  if (m_package != 0)
1838    {
1839      m_package->remove_use (this);
1840      m_package = 0;
1841    }
1842
1843  version   = "";
1844  author    = "";
1845  manager   = "";
1846  real_path = "";
1847
1848  prefix    = "";
1849  style     = mgr_style;
1850  initial_scope = ScopePublic;
1851  done      = false;
1852  discarded = false;
1853  selected  = false;
1854  m_hidden  = false;
1855  auto_imports = Unspecified;
1856
1857  includes.clear ();
1858  include_path = "";
1859  scripts.clear ();
1860  apply_patterns.clear ();
1861  ignore_patterns.clear ();
1862
1863  sub_uses.clear ();
1864  sub_use_scopes.clear ();
1865  sub_use_auto_imports.clear ();
1866
1867  requests.clear ();
1868
1869  alternate_versions.clear ();
1870  alternate_paths.clear ();
1871  alternate_is_head_versions.clear ();
1872
1873  m_head_version.clear (); 
1874
1875  version_alias = "";
1876  path_alias    = "";
1877
1878  m_located = false;
1879  m_has_native_version = false;
1880  m_index = -1;
1881}
1882
1883//----------------------------------------------------------
1884void Use::set (const cmt_string& new_package,
1885               const cmt_string& new_version,
1886               const cmt_string& new_path,
1887               const cmt_string& new_version_alias,
1888               const cmt_string& new_path_alias)
1889{
1890  clear ();
1891
1892  Package* p = Package::add (new_package);
1893
1894  m_package = p;
1895  p->add_use (this);
1896
1897  specified_path    = new_path;
1898  // specified_path.replace_all ("\\", "/");
1899
1900  specified_version = new_version;
1901  version           = new_version;
1902  path              = specified_path;
1903  Symbol::expand (path);
1904  real_path         = "";
1905  style             = mgr_style;
1906  initial_scope     = ScopePublic;
1907  done              = false;
1908  discarded         = false;
1909  Cmt::build_prefix (new_package, prefix);
1910
1911  version_alias = new_version_alias;
1912  path_alias    = new_path_alias;
1913}
1914
1915//----------------------------------------------------------
1916void Use::change_path (const cmt_string& new_path)
1917{
1918  //
1919  // This methods changes real_path after an actual location
1920  // where this package/version has been found.
1921  //
1922
1923  real_path = "";
1924
1925  if (new_path != "")
1926    {
1927      if ((path.size () > 0) &&
1928          (!CmtSystem::absolute_path (path)))
1929        {
1930          real_path = new_path;
1931          real_path += CmtSystem::file_separator ();
1932          real_path += path;
1933        }
1934      else
1935        {
1936          real_path = new_path;
1937        }
1938      // real_path.replace_all ("\\", "/");
1939
1940      CmtSystem::compress_path (real_path);
1941    }
1942 
1943  m_located = true;
1944}
1945
1946//----------------------------------------------------------
1947int Use::reach_package (const cmt_string& from_path, const cmt_string& n_version)
1948{
1949  if (Cmt::get_debug ())
1950    {
1951      cout << "Use::reach_package> " << get_package_name ()
1952           << "(" << version << ") from " << from_path << endl;
1953      cout << "Use::reach_package> native_version required "<<n_version<<endl;
1954    }
1955   
1956  //
1957  // We try to reach a package/version starting from from_path
1958  //
1959
1960  // check if from_path is at least real
1961  if ((from_path != "") && !CmtSystem::cd (from_path)) return (0);
1962
1963  if (Cmt::get_debug ())
1964    {
1965      cout << "Use::reach_package-2>" << endl;
1966    }
1967
1968  // check in case from_path is a new search path
1969  if (from_path != real_path)
1970    {
1971      // Move to that prefix only if it is a relative path.
1972      if ((path.size () > 0) && (!CmtSystem::absolute_path (path)))
1973        {
1974          if (!CmtSystem::cd (path))
1975            {
1976              return (0);
1977            }
1978        }
1979    }
1980
1981  if (Cmt::get_debug ())
1982    {
1983      cout << "Use::reach_package-3>" << endl;
1984    }
1985
1986  // Special treatment for CMTHOME package...
1987  if (get_package_name () == CmtSystem::get_home_package ())
1988    {
1989      discarded = 1;
1990      if (!CmtSystem::test_file ("requirements"))
1991        {
1992          return (0);
1993        }
1994      else
1995        {
1996          return (1);
1997        }
1998    }
1999
2000  if (Cmt::get_debug ())
2001    {
2002      cout << "Use::reach_package-4>" << endl;
2003    }
2004
2005  // Special treatment for CMTUSERCONTEXT package...
2006  if (get_package_name () == CmtSystem::get_user_context_package ())
2007    {
2008      discarded = 1;
2009      if (!CmtSystem::test_file ("requirements"))
2010        {
2011          return (0);
2012        }
2013      else
2014        {
2015          return (1);
2016        }
2017    }
2018
2019  // Special treatment for PROJECT package...
2020  if (get_package_name () == CmtSystem::get_project_package ())
2021    {
2022      discarded = 1;
2023      if (!CmtSystem::test_file ("project"))
2024        {
2025          return (0);
2026        }
2027      else
2028        {
2029          return (1);
2030        }
2031    }
2032
2033  if (Cmt::get_debug ())
2034    {
2035      cout << "Use::reach_package-5>" << endl;
2036    }
2037
2038  // Now from_path exists, try if the package exists there
2039  if (!CmtSystem::cd (get_package_name ()))
2040    {
2041      return (0);
2042    }
2043
2044  if (Cmt::get_debug ())
2045    {
2046      cout << "Use::reach_package-6>" << endl;
2047    }
2048
2049  if (CmtSystem::test_file ("cmt/requirements"))
2050    {
2051      //      CmtSystem::cd ("cmt");
2052
2053      //      style = no_version_style;
2054      if (n_version != "")
2055        {
2056          cmt_string path ("cmt");
2057          path += CmtSystem::file_separator ();
2058          path += "native_version.cmt";       
2059          if (!CmtSystem::test_file (path)) return (0);
2060
2061          cmt_string nv;
2062          if (!nv.read (path))
2063            {
2064              CmtError::set (CmtError::file_access_error,
2065                             CmtSystem::pwd () + CmtSystem::file_separator () + path);
2066              return (0);
2067            }
2068          int pos = nv.find ('\n');
2069          if (pos != cmt_string::npos) nv.erase (pos);
2070          pos = nv.find ('\r');
2071          if (pos != cmt_string::npos) nv.erase (pos);
2072          if (Cmt::get_debug ())
2073            {
2074              cout << "Use::reach_package-6.0> native_version found " << nv << " (required " << n_version << ")" << endl;
2075            }
2076          if (nv != n_version) return (0);
2077          this->native_version   = n_version;
2078        }
2079
2080      cmt_string v;
2081      //      if (Package::get_version (v))
2082      if (Package::get_version (v, "cmt"))
2083        {
2084          CompareStatus s = compare_versions (version, v, true);
2085          if (Cmt::get_debug ())
2086            {
2087              cout << "Use::reach_package-6.1> version=" << version << " v=" << v << " s=" << s << endl;
2088            }
2089
2090          switch (s)
2091            {
2092            case IdenticalIds:
2093            case ExplicitOldMajorIdWinsAgainstWildarded:
2094            case ExplicitOldMinorIdWinsAgainstWildarded:
2095            case ExplicitOldPatchIdWinsAgainstWildarded:
2096              break;
2097            case ExplicitNewMajorIdWinsAgainstWildarded:
2098            case ExplicitNewMinorIdWinsAgainstWildarded:
2099            case NewMinorIdGreaterThanOld:
2100            case ExplicitNewPatchIdWinsAgainstWildarded:
2101            case NewPatchIdGreaterThanOld:
2102              break;
2103            case OldMajorIdGreaterThanNew:
2104            case NewMajorIdGreaterThanOld:
2105              break;
2106            case IncompatibleMajorIds:
2107              if (!is_head_version (v))
2108                return (0);
2109              break;
2110            }
2111          version = v;
2112        }
2113      else if (version == "")
2114        {
2115          version = "v0";
2116        }
2117      CmtSystem::cd ("cmt");
2118      style = cmt_style;
2119      structuring_style = without_version_directory;
2120      return (1);
2121    }
2122  else if (!CmtSystem::cd (version) || (version == ""))
2123    //  else if (!CmtSystem::cd (version))
2124    {
2125      //
2126      // The specified version cannot be found per-se
2127      // There are alternate possibilities when it contains wild cards
2128      //
2129      if ((version.find ("*") != cmt_string::npos) || (version == ""))
2130      //      if ((version == "") || (version.find ("*") != cmt_string::npos))
2131      //      if (version.find ("*") != cmt_string::npos)
2132        {
2133          static CmtSystem::cmt_string_vector versions;
2134          static cmt_string name;
2135
2136          name = ".";
2137          name += CmtSystem::file_separator ();
2138          if (version != "") name += version;
2139          else name += "*";
2140          /*
2141          if (version == "") name += "*";
2142          else name += version;
2143          */
2144          //          name += version;
2145          CmtSystem::scan_dir (name, versions);
2146          if (n_version != "")
2147            {
2148              CmtSystem::cmt_string_vector native_versions;           
2149              for (int i = 0; i < versions.size (); i++)
2150                {
2151                  cmt_string path;
2152                  if (CmtSystem::test_directory (versions[i]))
2153                    {
2154                      path  = versions[i];
2155                      path += CmtSystem::file_separator ();
2156                      path += "cmt";
2157                    }
2158                  else
2159                    {
2160                      path = "cmt";
2161                    }
2162                  path += CmtSystem::file_separator ();
2163                  path += "native_version.cmt";       
2164                                 
2165                  if (CmtSystem::test_file (path))
2166                    {
2167                      cmt_string nv;
2168
2169                      nv.read (path);
2170                      int pos = nv.find ('\n');
2171                      if (pos != cmt_string::npos) nv.erase (pos);
2172
2173                      pos = nv.find ('\r');
2174                      if (pos != cmt_string::npos) nv.erase (pos);
2175
2176                      if (nv == n_version)
2177                        {
2178                          cmt_string& name_entry = native_versions.add ();
2179
2180                          // We have found at least one
2181                          // cout << "native_version :" << n_version << " ,version: " << versions[i] << endl;
2182                          this->native_version   = n_version;
2183                          name_entry            += versions[i];
2184                        }
2185                    }                   
2186                }
2187              versions = native_versions;
2188            }
2189         
2190          int i;
2191          bool found = false;
2192         
2193          for (i = 0; i < versions.size (); i++)
2194            {
2195              const cmt_string& vers = versions[i];
2196             
2197              if (Cmt::get_debug ())
2198                {
2199                  cout << "     ... version " << vers << " exists" << endl;
2200                }
2201
2202              CmtSystem::basename (vers, name);
2203             
2204              int v;
2205              int r;
2206              int p;
2207             
2208              if (CmtSystem::is_version_directory (name, v, r, p))
2209                {
2210                  /*
2211                    This check is not sufficient !! We need to check in addition
2212                    that the selected directory is really the start of a true CMT
2213                    package (ie with either cmt/requirements or mgr/requirements below)
2214                  */
2215
2216                  cmt_string req;
2217
2218                  req = name;
2219                  req += CmtSystem::file_separator ();
2220                  req += "cmt";
2221                  req += CmtSystem::file_separator ();
2222                  req += "requirements";
2223
2224                  if (!CmtSystem::test_file (req))
2225                    {
2226                      req = name;
2227                      req += CmtSystem::file_separator ();
2228                      req += "mgr";
2229                      req += CmtSystem::file_separator ();
2230                      req += "requirements";
2231
2232                      if (!CmtSystem::test_file (req)) continue;
2233                    }
2234
2235                  cmt_string& new_v = alternate_versions.add ();
2236                  new_v = name;
2237                  cmt_string& new_p = alternate_paths.add ();
2238                  new_p = from_path;
2239                  bool& new_i = alternate_is_head_versions.add ();
2240                  new_i = is_head_version (name);
2241
2242                  found = true;
2243                }
2244            }
2245
2246              /*
2247          if (!found)
2248            {
2249              if (CmtSystem::test_file ("cmt/requirements"))
2250                {
2251                  CmtSystem::cd ("cmt");
2252                  style = no_version_style;
2253                  return (1);
2254                }
2255            }
2256              */
2257        }
2258
2259      if (Cmt::get_debug ())
2260        {
2261          cout << "  ... end of version scan" << endl;
2262        }
2263
2264      //
2265      //  We have now the list of possible alternate versions. However
2266      // we return that the expected package/version was not found (yet).
2267      //
2268
2269      return (0);
2270    }
2271
2272  if (Cmt::get_debug ())
2273    {
2274      cout << "Use::reach_package-7>" << endl;
2275    }
2276
2277  //cerr << "  ... version " << version << " exists" << endl;
2278
2279  // Now we have met the exact specified version!
2280  if (CmtSystem::test_file ("cmt/requirements"))
2281    {
2282      CmtSystem::cd ("cmt");
2283      style = cmt_style;
2284      structuring_style = with_version_directory;
2285    }
2286  else if (CmtSystem::test_file ("mgr/requirements"))
2287    {
2288      CmtSystem::cd ("mgr");
2289      style = mgr_style;
2290      structuring_style = with_version_directory;
2291    }
2292  else
2293    {
2294      return (0);
2295    }
2296
2297  if (Cmt::get_debug ())
2298    {
2299      cout << "Use::reach_package-8>" << endl;
2300    }
2301
2302  return (1);
2303}
2304
2305class UseProjectAction : public IProjectAction
2306{
2307public:
2308  UseProjectAction (Use* use, cmt_string n_version="") : m_use (use), m_found (false), native_version(n_version)
2309  {
2310  }
2311
2312  bool found () const
2313  {
2314    return (m_found);
2315  }
2316
2317  bool run (const Project& project)
2318  {
2319    const cmt_string& path = project.get_cmtpath ();
2320     
2321    m_use->alternate_versions.clear ();
2322    m_use->alternate_paths.clear ();
2323    m_use->alternate_is_head_versions.clear ();
2324
2325    if (m_use->reach_package (path, this->native_version))
2326      {
2327        if (Cmt::get_debug ())
2328          {
2329            cout << "move_to4> " << path << endl;
2330          }
2331       
2332        m_use->change_path (path);
2333
2334        m_found = true;
2335
2336        return (false);
2337      }
2338    else if (m_use->alternate_versions.size () > 0)
2339      {
2340        if (m_use->select_alternate ()) 
2341          {
2342            if (Cmt::get_debug ())
2343              {
2344                cout << "move_to5> " << m_use->real_path << endl;
2345              }
2346
2347            m_found = true;
2348
2349            return (false);
2350          }
2351      }
2352   
2353    return (true);
2354  }
2355
2356private:
2357  Use* m_use;
2358  bool m_found;
2359  cmt_string native_version;
2360};
2361
2362//----------------------------------------------------------
2363bool Use::move_to (const cmt_string& native_version, bool curdir)
2364//bool Use::move_to (const cmt_string& native_version)
2365{
2366  if (m_located)
2367    {
2368      //
2369      // The real path where this version/package can be found
2370      // has already been resolved. We thus first go there.
2371      //
2372
2373      if (Cmt::get_debug ())
2374        {
2375          cout << "move_to1> " << real_path << endl;
2376        }
2377
2378      reach_package (real_path, native_version);
2379
2380      return (true);
2381    }
2382
2383  cmt_string expanded_path = path;
2384
2385  //
2386  // If the path specified in this use is a true absolute path,
2387  // then we search the package from there first.
2388  //
2389  if (CmtSystem::absolute_path (expanded_path))
2390    {
2391      if (reach_package (expanded_path,  native_version))
2392        {
2393          if (Cmt::get_debug ())
2394            {
2395              cout << "move_to3> " << expanded_path << endl;
2396            }
2397
2398          change_path (expanded_path);
2399
2400          return (true);
2401        }
2402      else if (alternate_versions.size () > 0)
2403        {
2404          if (select_alternate ()) 
2405            {
2406              if (Cmt::get_debug ())
2407                {
2408                  cout << "move_to5> " << real_path << endl;
2409                }             
2410
2411              return (true);
2412            }
2413        }
2414    }
2415
2416  //
2417  // Try here.
2418  //
2419  if (curdir)
2420    {
2421//   if (expanded_path == "")
2422//     {
2423//       if (reach_package ("", native_version))
2424
2425      cmt_string here = CmtSystem::pwd ();
2426
2427      if (reach_package (here,  native_version))
2428        {
2429          if (Cmt::get_debug ())
2430            {
2431              cout << "move_to2> " << expanded_path << endl;
2432            }
2433
2434          change_path (here);
2435
2436          return (true);
2437        }
2438      else if (alternate_versions.size () > 0)
2439        {
2440          if (select_alternate ()) 
2441            {
2442              if (Cmt::get_debug ())
2443                {
2444                  cout << "move_to5> " << real_path << endl;
2445                }
2446             
2447              return (true);
2448            }
2449        }
2450      return (false);
2451//     }
2452    } // end of curdir     
2453     
2454  //
2455  // Second try is among the CMTPATHs
2456  //
2457  UseProjectAction pa (this, native_version);
2458
2459  Project::broadcast (pa);
2460
2461  if (pa.found ()) return (true);
2462
2463  return (false);
2464}
2465
2466//----------------------------------------------------------
2467bool Use::select_alternate ()
2468{
2469  int i;
2470
2471  int v0 = 0;
2472  int r0 = 0;
2473  int p0 = 0;
2474
2475  int v = 0;
2476  int r = 0;
2477  int p = 0;
2478
2479  int selected_index = -1;
2480
2481  for (i = 0; i < alternate_versions.size (); i++)
2482    {
2483      cmt_string& name = alternate_versions[i];
2484
2485      if (i == 0)
2486        {
2487          CmtSystem::is_version_directory (name, v0, r0, p0);
2488          selected_index = 0;
2489        }
2490      else
2491        {
2492          if (alternate_is_head_versions[selected_index] &&
2493              alternate_is_head_versions[i])
2494            {
2495              if (strcmp(name.c_str (), alternate_versions[selected_index].c_str ()) > 0)
2496                {
2497                  selected_index = i;
2498                }
2499              continue;
2500            }
2501          else if (alternate_is_head_versions[selected_index])
2502            {
2503              continue;
2504            }
2505          else if (alternate_is_head_versions[i])
2506            {
2507              selected_index = i;
2508              continue;
2509            }
2510
2511          CmtSystem::is_version_directory (name, v, r, p);
2512
2513          if (v > v0)
2514            {
2515              selected_index = i;
2516              v0 = v;
2517              r0 = r;
2518              p0 = p;
2519            }
2520          else if (v == v0)
2521            {
2522              if (r > r0)
2523                {
2524                  selected_index = i;
2525                  r0 = r;
2526                  p0 = p;
2527                }
2528              else if (r == r0)
2529                {
2530                  if (p > p0)
2531                    {
2532                      selected_index = i;
2533                      p0 = p;
2534                    }
2535                }
2536            }
2537        }
2538    }
2539
2540  if (selected_index >= 0)
2541    {
2542      if (CmtSystem::cd (alternate_paths[selected_index]))
2543        {
2544          version = alternate_versions[selected_index];
2545          if (reach_package (alternate_paths[selected_index]))
2546            {
2547              if (Cmt::get_debug ())
2548                {
2549                  cout << "select_alternate> " << alternate_paths[selected_index] << endl;
2550                }
2551
2552              change_path (alternate_paths[selected_index]);
2553              return (true);
2554            }
2555        }
2556    }
2557
2558  return (false);
2559}
2560
2561//----------------------------------------------------------
2562bool Use::need_new (const cmt_string& path,
2563                    const cmt_string& package,
2564                    const cmt_string& version,
2565                    const cmt_string& n_version,
2566                    Use** old_use,
2567                    Use* context_use)
2568{
2569  bool new_request = add_request (path, package, version);
2570   
2571  Use& current_use = Use::current ();
2572
2573  if (package == current_use.get_package_name ())
2574    {
2575      if (Cmt::get_debug ())
2576        {
2577          cout << "  ... recursive use to current package" << endl;
2578        }
2579
2580      if (old_use != 0) *old_use = &current_use;
2581      return (false);
2582    }
2583
2584  Package* p = Package::add (package);
2585
2586  UsePtrVector& uses = p->get_uses ();
2587
2588  bool do_need_new = true;
2589  Use* found = 0;
2590  Use* registered = 0;
2591
2592  int req_v = -1;
2593  int req_r = -1;
2594  int req_p = -1;
2595
2596  CmtSystem::is_version_directory (version, req_v, req_r, req_p);
2597
2598  if (Cmt::get_debug ())
2599    {
2600      cout << "need_new> p=" << package << " v=" << version << " v=" << req_v << " r=" << req_r << " p=" << req_p << endl;
2601    }
2602
2603  bool has_wild_card = (req_v == -1) || (req_r == -1) || (req_p == -1);
2604
2605  int new_v = -1;
2606  int new_r = -1;
2607  int new_p = -1;
2608
2609  int use_index;
2610
2611  if (old_use != 0) *old_use = 0;
2612
2613  // Acquire the registered use.
2614  for (use_index = 0; use_index < uses.size (); use_index++)
2615    {
2616      Use& use = (*uses[use_index]);
2617
2618      if (use.m_index < 0) continue;
2619
2620      registered = &use;
2621
2622      break;
2623    }
2624
2625  // Make a first try with the registered use if it exists.
2626
2627  cmt_string decision;
2628
2629  if (registered != 0)
2630    {
2631      Use& use = (*registered);
2632
2633      found = &use;
2634
2635      CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2636
2637      bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2638
2639      if (has_wild_card && !use_has_wild_card)
2640        {
2641          if (Cmt::get_debug ())
2642            {
2643              cout << "  ... wildcarded request loses against existing explicit" << endl;
2644            }
2645         
2646          do_need_new = false; // We don't need a new one
2647        }
2648      else
2649        {
2650          // here either !has_wild_card or use_has_wild_card
2651
2652          if ((version == use.specified_version) &&
2653              (path == use.specified_path))
2654            {
2655             
2656              if (Cmt::get_debug ())
2657                {
2658                  cout << " ... exactly same version and path!" << endl;
2659                }             
2660              do_need_new = false; // We don't need a new one
2661              if (n_version != use.native_version)
2662                {
2663                  if (Cmt::get_debug ())
2664                    {
2665                      cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl; 
2666                    }
2667
2668                  do_need_new = true;   
2669                }             
2670            }
2671          else if (version != use.specified_version)
2672            {
2673              if (Cmt::get_debug ())
2674                {
2675                  cout << "requested explicit wins against existing wildcarded"
2676                       << endl;
2677                }
2678
2679              // The registered use loses against the request
2680            }
2681          else
2682            {
2683              if (Cmt::get_debug ())
2684                {
2685                  cout << "only paths differ, consider the new one."
2686                       << endl;
2687                }
2688
2689              // The registered use loses against the request
2690            }
2691        }
2692
2693
2694      //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2695      if (new_request && !Cmt::get_quiet ())
2696        {
2697          if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2698            {
2699              cerr << "# Required version " << version
2700                   << " of package " << package;
2701
2702              if (context_use != 0)
2703                {
2704                  cerr << " [from " << context_use->get_package_name () << "]";
2705                }
2706
2707              cerr << " incompatible with selected version " << use.version;
2708
2709              if (use.version != use.specified_version)
2710                {
2711                  cerr << " (" << use.specified_version << ")" ;
2712                }
2713
2714              cerr << endl;
2715            }
2716        }
2717
2718      if (Cmt::get_debug ())
2719        {
2720          cout << "# " << package << " " << version;
2721
2722          if (context_use != 0)
2723            {
2724              cout << " [from " << context_use->get_package_name () << "]";
2725            }
2726
2727          if (do_need_new)
2728            {
2729              cout << " > ";
2730            }
2731          else
2732            {
2733              cout << " < ";
2734            }
2735
2736          cout << use.version;
2737          if (use.version != use.specified_version)
2738            {
2739              cout << " (" << use.specified_version << ")" ;
2740            }
2741
2742          cout << " (r) ";
2743
2744          cout << endl;
2745        }
2746    }
2747
2748  if (do_need_new)
2749    {
2750      // Now try unregistered uses, since the registered one is not appropriate.
2751      // to see is any other existing use could match
2752
2753      for (use_index = 0; use_index < uses.size (); use_index++)
2754        {
2755          Use& use = (*uses[use_index]);
2756         
2757          if (use.m_index >= 0) continue;
2758         
2759          // Always save the latest found.
2760         
2761          found = &use;
2762
2763          CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2764
2765          bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2766
2767          if (has_wild_card && !use_has_wild_card)
2768            {
2769              if (Cmt::get_debug ())
2770                {
2771                  cout << "  ... requested wildcarded loses against existing explicit" << endl;
2772                }
2773             
2774              do_need_new = false; // We don't need a new one
2775            }
2776          else
2777            {
2778              // here either !has_wild_card or use_has_wild_card
2779         
2780              if ((version == use.specified_version) &&
2781                  (path == use.specified_path))
2782                {
2783                  if (Cmt::get_debug ())
2784                    {
2785                      cout << " ... exactly same version and path!" << endl;
2786                    }
2787             
2788                  do_need_new = false; // We don't need a new one
2789                  if (n_version != use.native_version)
2790                    {
2791                      if (Cmt::get_debug ())
2792                        {
2793                          cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl;
2794                        }
2795
2796                      do_need_new = true;   
2797                    }
2798                 
2799                }
2800              else if (version != use.specified_version)
2801                {
2802                  if (Cmt::get_debug ())
2803                    {
2804                      cout << "requested explicit wins against existing wildcarded"
2805                           << endl;
2806                    }
2807
2808                  // This use loses against the request
2809                }
2810              else
2811                {
2812                  if (Cmt::get_debug ())
2813                    {
2814                      cout << "only paths differ, consider the new one."
2815                           << endl;
2816                    }
2817
2818                  // This use loses against the request
2819                }
2820            }
2821
2822          //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2823          if (new_request && !Cmt::get_quiet ())
2824            {
2825              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2826                {
2827                  cerr << "# Required version " << version
2828                       << " of package " << package;
2829
2830                  if (context_use != 0)
2831                    {
2832                      cerr << " [from " << context_use->get_package_name () << "]";
2833                    }
2834             
2835                  cerr << " incompatible with selected version " << use.version;
2836
2837                  if (use.version != use.specified_version)
2838                    {
2839                      cerr << " (" << use.specified_version << ")" ;
2840                    }
2841
2842                  cerr << endl;
2843                }
2844            }
2845
2846          if (Cmt::get_debug ())
2847            {
2848              cout << "# " << package << " " << version;
2849             
2850              if (context_use != 0)
2851                {
2852                  cout << " [from " << context_use->get_package_name () << "]";
2853                }
2854             
2855              if (do_need_new)
2856                {
2857                  cout << " > ";
2858                }
2859              else
2860                {
2861                  cout << " < ";
2862                }
2863             
2864              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2865                {
2866                  cout << "(incompatible) ";
2867                }
2868
2869              cout << use.version;
2870              if (use.version != use.specified_version)
2871                {
2872                  cout << " (" << use.specified_version << ")" ;
2873                }
2874              cout << endl;
2875            }
2876        }
2877    }
2878
2879  if (old_use != 0)
2880    {
2881      if (registered != 0) *old_use = registered;
2882      else *old_use = found;
2883    }
2884
2885  return (do_need_new);
2886}
2887
2888//----------------------------------------------------------
2889//
2890//  Here the version which is provided here is the specified version.
2891// It may contain wild cards or it may be simply empty.
2892//
2893//----------------------------------------------------------
2894Use* Use::create (const cmt_string& path,
2895                  const cmt_string& package,
2896                  const cmt_string& version,
2897                  const cmt_string& version_alias,
2898                  const cmt_string& path_alias,
2899                  const cmt_string& n_version)
2900{
2901  Package* p = 0;
2902
2903  p = Package::add (package);
2904
2905  UsePtrVector& vector = p->get_uses ();
2906
2907  // We first look in the database.
2908  for (int use_index = 0; use_index < vector.size (); use_index++)
2909    {
2910      Use* use = vector[use_index];
2911
2912      if ((use->specified_version == version) && 
2913          (use->specified_path == path) && use->native_version==n_version) return (use);
2914    }
2915
2916  // We now really create a new Use entry.
2917
2918  static UseVector& instances = get_instances ();
2919
2920  Use& use_object = instances.add ();
2921
2922  use_object.set (package, version, path, version_alias, path_alias);
2923
2924  return (&use_object);
2925}
2926
2927//----------------------------------------------------------
2928//  Add a use request into the database.
2929//
2930//  o If a use request already exist in the database,
2931//    check the version compatibility
2932//
2933//----------------------------------------------------------
2934Use* Use::add (const cmt_string& path,
2935               const cmt_string& package_name,
2936               const cmt_string& version,
2937               const cmt_string& version_alias,
2938               const cmt_string& path_alias,
2939               const cmt_string& native_version,
2940               Use* context_use,
2941               const State specified_auto_imports)
2942{
2943  bool do_need_new = false;
2944
2945  Use* old_use = 0;
2946  Use* use = 0;
2947
2948  do_need_new = need_new (path, package_name, version, native_version, &old_use, context_use);
2949
2950  if (Cmt::get_debug ())
2951    {
2952      if (old_use != 0 && !do_need_new)
2953        {
2954          cout << "add> old_use " << old_use->get_package_name () <<
2955            " " << old_use->version <<
2956            " " << old_use->path <<
2957            endl;
2958        }
2959    }
2960
2961  if (do_need_new)
2962    {
2963      use = create (path, package_name, version, version_alias, path_alias, native_version);
2964    }
2965  else
2966    {
2967      // Since we don't need a new Use, it means that old_use exists !
2968
2969      use = old_use;
2970      old_use = 0;
2971    }
2972
2973  if (package_name == CmtSystem::get_home_package ())
2974    {
2975      return (use);
2976    }
2977
2978  if (package_name == CmtSystem::get_user_context_package ())
2979    {
2980      return (use);
2981    }
2982
2983  if (package_name == CmtSystem::get_project_package ())
2984    {
2985      return (use);
2986    }
2987
2988  cmt_string here = CmtSystem::pwd ();
2989
2990  //
2991  // Store the specified sub_uses. Some of them may become discarded
2992  // later on.
2993  //
2994  if (context_use != 0)
2995    {
2996      context_use->sub_uses.push_back (use);
2997
2998      context_use->sub_use_scopes.push_back (context_use->get_current_scope ());
2999
3000      context_use->sub_use_auto_imports.push_back (specified_auto_imports);
3001
3002      cmt_string& request = context_use->requests.add ();
3003
3004      request = package_name;
3005      request += " ";
3006      request += version;
3007      request += " ";
3008      request += path;
3009
3010
3011      if (Cmt::get_debug ())
3012        {
3013          cout << "Use::add context(" << context_use->get_package_name () << ") "
3014               << "[u:" << package_name
3015               << " s:" << context_use->get_current_scope ()
3016               << " ai:" << specified_auto_imports
3017               << "]" << endl;
3018        }
3019    }
3020
3021  if (use == &(Use::current ())) 
3022    {
3023      return (use);
3024    }
3025
3026  /*
3027   *   Now we have a Use object. If it is a new one, we have to
3028   *    1) understand if it exists physically
3029   *    2) it is better than the old ones.
3030   *
3031   *   Here, we may have :
3032   *    1) old_use = 0
3033   *         there was no Use object before for this package
3034   *         the existing one is fine
3035   *
3036   *    2) old_use != 0
3037   *         we have created a new Use (which has to be validated)
3038   */
3039  bool found = use->move_to (native_version);
3040
3041  if (Cmt::get_debug ())
3042    {
3043      cout << "add> use [" << use << "] " << use->get_package_name () 
3044           << " " << use->version
3045           << " " << use->path
3046           << " found=" << found
3047           << " done=" << use->done
3048           << endl;
3049
3050      show_packages ();
3051    }
3052     
3053  if (!found)
3054    {
3055      CmtMessage::warning (CmtError::get_error_name (CmtError::package_not_found)
3056                           + ": " + use->get_info ()
3057                           + (native_version != "" ?
3058                              " -native_version=" + native_version : "")
3059                           + ( (context_use != 0) ?
3060                               " (requested by " + context_use->get_package_name () + ")" : "" )
3061                           );
3062      /*
3063      CmtMessage::warning ("package " + use->get_package_name ()
3064                           + " " + use->version + " " + use->path
3065                           + " not found"
3066                           + ( (context_use != 0) ?
3067                               " (requested by " + context_use->get_package_name () + ")" :
3068                               "" )
3069                           );
3070      */
3071      /*
3072      if (!Cmt::get_quiet ())
3073        {
3074          cerr << "#CMT> Warning: package " << use->get_package_name () <<
3075            " " << use->version << " " << use->path <<
3076            " not found";
3077
3078          if (context_use != 0)
3079            {
3080              cerr << " (requested by " << context_use->get_package_name () << ")";
3081            }
3082
3083          cerr << endl;
3084        }
3085      */
3086
3087      //CmtError::set (CmtError::package_not_found, use->get_package_name ());
3088      use->m_located = false;
3089      //use = 0;
3090    }
3091
3092  if ((old_use != 0) && (use != old_use))
3093    {
3094      if (Cmt::get_debug ())
3095        {
3096          cout << "There was another version of this Use. \n"
3097               << "But a new one was created due to some criteria. \n"
3098               << "Now we are going to apply the version strategy to make the final selection"
3099               << endl;
3100        }
3101
3102      /*
3103       *    There was another version of this Use.
3104       *    But a new one was created due to some criteria.
3105       *    Now we are going to apply the version strategy to make the final selection.
3106       */
3107
3108      if (Cmt::get_debug ())
3109        {
3110          cout << "select? [" << use << "] "<< use->version <<" vs old_use[" << old_use << "] "
3111               << old_use->get_package_name ()
3112               << " " << old_use->version
3113               << " " << old_use->path
3114               << endl;
3115        }
3116
3117      if (!found)
3118        {
3119          /*
3120           *  This new Use does not correspond to any physical package.
3121           *  let's simply discard it (and go back to old_use)
3122           */
3123
3124          //if (use != 0) use->discard ();
3125          use->discard ();
3126          use = old_use;
3127          if (context_use != 0)
3128            {
3129              context_use->sub_uses[context_use->sub_uses.size () - 1] = use;
3130            }
3131          found = use->move_to (native_version);
3132        }
3133      else
3134        {
3135          //
3136          //  This new version is different from the old one
3137          // thus we have to choose
3138          //
3139          bool old_use_is_head_version (use->is_head_version (old_use->version));
3140          bool use_is_head_version (use->is_head_version (use->version));
3141          Use* selected_use (old_use);
3142          if (old_use_is_head_version && use_is_head_version)
3143            {
3144              if (strcmp(use->version.c_str (), old_use->version.c_str ()) > 0)
3145                {
3146                  selected_use = use;
3147                  if (Cmt::get_debug ())
3148                    {
3149                      cout << "add> new head version " << use->version
3150                           << " wins old head version " << old_use->version
3151                           << endl;
3152                    }
3153                }
3154            }
3155          else if (old_use_is_head_version)
3156            {
3157            }
3158          else if (use_is_head_version)
3159            {
3160              selected_use = use;
3161              if (Cmt::get_debug ())
3162                {
3163                  cout << "add> new head version " << use->version
3164                       << " wins old version " << old_use->version
3165                       << endl;
3166                }
3167            }
3168          else
3169            {
3170              static BestFitSelector selector;
3171              selected_use = selector.operate (old_use, use);
3172              if (Cmt::get_debug ())
3173                {
3174                  cout << "add> operate on old version " << old_use->version
3175                       << " and new version " << use->version
3176                       << endl;
3177                }
3178            }
3179
3180          if (Cmt::get_debug ())
3181            {
3182              cout << "add> old=" << old_use << "i=" << old_use->m_index
3183                   << " new=" << use << "i=" << use->m_index
3184                   << " => selected=" << selected_use
3185                   << endl;
3186            }
3187
3188          //
3189          // Some situations managed by selector.operate happen
3190          // to fail discarding the rejected Use.
3191          //
3192          if (use != selected_use) 
3193            {
3194              use = use->set_selected_version (selected_use);
3195              if (context_use != 0)
3196                {
3197                  context_use->sub_uses[context_use->sub_uses.size () - 1] = use;
3198                }
3199            }
3200         
3201
3202          /*
3203           *   current directory is moved to the selected one
3204           */
3205          found = use->move_to (native_version);
3206        }
3207    }
3208
3209  //
3210  // The following statement is no longer considered as useful.
3211  // It is commented. But we should clarify why it was really needed!
3212  //
3213  //use->undiscard ();
3214
3215  if (found)
3216    {
3217      static UsePtrVector& uses = get_ordered_uses ();
3218
3219      bool registered = false;
3220      const Use& cu = Use::current ();
3221
3222      Package* package = Package::find (package_name);
3223
3224      //
3225      // A pointer to this new object is also added or replaced.
3226      //
3227      if ((use != &cu) && (package == cu.get_package ()))
3228        {
3229          // This is a recursive call to the current package!!
3230          registered = true;
3231          use->done = true;
3232          use->m_index = -1;
3233        }
3234      else
3235        {
3236          //
3237          // Now sort out the registration in ordered uses
3238          //
3239          //  cases:
3240          //
3241          //   use is not yet registered (m_index < 0)
3242          //     o if another use of the same package is registered,
3243          //       it must be substituted with the new one
3244          //     o otherwise create a new entry at the end (it will be sorted
3245          //       afterwards)
3246          //
3247          //   use is already registered (m_index >= 0)
3248          //     o if another use of the same package is registered,
3249          //       it must be discarded, but this may mean that
3250          //       two versions are simultaneously registered (bug?)
3251          //     o otherwise we keep it in place
3252          //
3253
3254          UsePtrVector& puses = package->get_uses ();
3255
3256          if (use->m_index >= 0) registered = true;
3257
3258          /*
3259            We look for all existing uses in that package.
3260          */
3261          for (int i = 0; i < puses.size(); i++)
3262            {
3263              Use* u = puses[i];
3264             
3265              if (Cmt::get_debug ())
3266                {
3267                  cout << "add> check registering between " << use
3268                       << ":" << use->get_package_name ()
3269                       << "(" << use->m_index << ")"
3270                       << " and " << u
3271                       << ":" << u->get_package_name () 
3272                       << "(" << u->m_index << ")"
3273                       << endl;
3274                }
3275
3276              if ((u != use) && (u->m_index >= 0))
3277                {
3278                  // Another use of that package is already registered
3279
3280                  if (Cmt::get_debug ())
3281                    {
3282                      cout << "add> Another use of that package is already registered " 
3283                           << " use(" << use->m_index << ")";
3284                      if (use->m_index >= 0)
3285                        {
3286                          cout << "[" << (uses[use->m_index])->get_package_name () << "]";
3287                        }
3288                      cout << " u(" << u->m_index << ")";
3289                      if (u->m_index >= 0)
3290                        {
3291                          cout << "[" << (uses[u->m_index])->get_package_name () << "]";
3292                        }
3293                      cout << endl;
3294                    }
3295
3296                  if (use->m_index < 0)
3297                    {
3298                      /*
3299                        the newly selected use (use) should replace the one which was registered (u)
3300                      */
3301
3302                      u->set_selected_version (use);
3303
3304                      registered = true;
3305                    }
3306                  else
3307                    {
3308                      // bug??
3309                      if (Cmt::get_debug ())
3310                        {
3311                          cout << "Duplicate entry in ordered uses" << endl;
3312                        }
3313                    }
3314                }
3315            }
3316
3317          if (Cmt::get_debug ())
3318            {
3319              cout << "add> registering completed" << endl;
3320              //show_packages ();
3321            }
3322        }
3323     
3324      if (!registered) 
3325        {
3326          if (Cmt::get_debug ())
3327            {
3328              cout << "add> We install use at the end the ordered list of uses" << endl;
3329            }
3330
3331          uses.push_back (use);
3332          use->m_index = uses.size () - 1;
3333        }
3334
3335      if (Cmt::get_debug ())
3336        {
3337          for (int use_index = 0; use_index < uses.size (); use_index++)
3338            {
3339              Use* u = (Use*) uses[use_index];
3340              cout << "  use[" << use_index << "] p=(" << u << ")" << u->get_package_name () 
3341                   << " v=" << u->version
3342                   << " discarded=" << u->discarded
3343                   << " selected=" << u->selected
3344                   << " done=" << u->done
3345                   << " index=" << u->m_index
3346                   << endl;
3347            }
3348         
3349        }
3350         
3351      if (!use->done && Cmt::get_recursive ())
3352        {
3353          use->done = true;
3354
3355          if (Cmt::get_debug ())
3356            {
3357              cout << "Parsing requirements file at " << CmtSystem::pwd () << endl;
3358            }
3359
3360          SyntaxParser::parse_requirements ("requirements", use);
3361        }
3362      else
3363        {
3364          if (Cmt::get_debug ())
3365            {
3366              cout << "Requirements file at " << CmtSystem::pwd () << " already parsed" << endl;
3367            }
3368        }
3369    }
3370
3371  CmtSystem::cd (here);
3372
3373  return (use);
3374}
3375
3376//----------------------------------------------------------
3377void Use::discard ()
3378{
3379  discarded = true;
3380}
3381
3382//----------------------------------------------------------
3383void Use::undiscard ()
3384{
3385  discarded = false;
3386}
3387
3388//----------------------------------------------------------
3389void Use::select ()
3390{
3391  selected = true;
3392}
3393
3394//----------------------------------------------------------
3395void Use::unselect ()
3396{
3397  selected = false;
3398}
3399
3400//----------------------------------------------------------
3401bool Use::is_selected ()
3402{
3403  return (selected);
3404}
3405
3406/**
3407 *    Check if the package makes use of the specified package/version
3408 *
3409 *    The seach only considers the first level of uses (thus it is
3410 *   NOT recursive)
3411 */
3412bool Use::is_client (const cmt_string& used_package,
3413                     const cmt_string& used_version)
3414{
3415  // A package is client of itself
3416
3417  Package* package = Package::find (used_package);
3418
3419  if ((get_package () == package) &&
3420      (version == used_version)) return (true);
3421
3422  if (discarded) return (false);
3423
3424  int i;
3425
3426  for (i = 0; i < sub_uses.size (); i++)
3427    {
3428      Use* use = sub_uses[i];
3429      if (use == 0) continue;
3430
3431      if ((use->get_package () == package) &&
3432          (use->version == used_version)) return (true);
3433
3434      /*
3435        if (use->is_client (used_package, used_version))
3436        {
3437        return (true);
3438        }
3439      */
3440    }
3441
3442  return (false);
3443}
3444
3445//----------------------------------------------------------
3446void Use::apply_global_patterns ()
3447{
3448  int i;
3449
3450  Pattern::PatternVector& vector = Pattern::patterns ();
3451
3452  for (i = 0; i < vector.size (); i++)
3453    {
3454      Pattern& p = vector[i];
3455
3456      if (p.global)
3457        {
3458          p.apply (this);
3459        }
3460    }
3461}
3462
3463//----------------------------------------------------------
3464void Use::set_include_path (const cmt_string& new_path)
3465{
3466  include_path = new_path;
3467}
3468
3469/**
3470 *   Compute the full real path of a found package.
3471 *   Takes the structuring style into account
3472 *
3473 *    Result is used to fill in the referenced string
3474 *    Result does NOT include the trailing file_separator
3475 */
3476void Use::get_full_path (cmt_string& s) const
3477{
3478  if (real_path == "") s = CmtSystem::pwd ();
3479  else s = real_path;
3480
3481  if (style != none_style)
3482    {
3483      s += CmtSystem::file_separator ();
3484      s += get_package_name ();
3485    }
3486 
3487  //  if (style != no_version_style)
3488  if (structuring_style == with_version_directory)
3489    {
3490      s += CmtSystem::file_separator ();
3491      s += version;
3492    }
3493}
3494
3495/**
3496 *   Compute the full real path of a found package.
3497 *   Takes the structuring style into account
3498 */
3499cmt_string Use::get_full_path () const
3500{
3501  cmt_string result;
3502
3503  get_full_path (result);
3504
3505  return (result);
3506}
3507
3508/**
3509 *   Considering a given path, try and reduce the part of it
3510 *  that corresponds to the full path of this package into its
3511 *  normal form ${<PACKAGE>ROOT}
3512 *   The argument is modified if the pattern is exactly found.
3513 */
3514void Use::reduce_path (cmt_string& s) const
3515{
3516  cmt_string pattern;
3517  get_full_path (pattern);
3518  pattern += CmtSystem::file_separator ();
3519 
3520  cmt_string replacement = "${";
3521  replacement += prefix;
3522  replacement += "ROOT}";
3523  replacement += CmtSystem::file_separator ();
3524
3525  s.replace (pattern, replacement);
3526}
3527
3528//----------------------------------------------------------
3529void Use::get_cmtpath_and_offset (cmt_string& cmtpath, cmt_string& offset) const
3530{
3531  if (get_package_name () == CmtSystem::get_project_package ())
3532    {
3533      offset = "";
3534      CmtSystem::dirname (path, cmtpath);
3535      return;
3536    }
3537  else if (get_package_name () == CmtSystem::get_home_package ())
3538    {
3539      offset = "";
3540      cmtpath = path;
3541      return;
3542    }
3543  else if (get_package_name () == CmtSystem::get_user_context_package ())
3544    {
3545      offset = "";
3546      cmtpath = path;
3547      return;
3548    }
3549
3550  cmtpath = "";
3551  offset = "";
3552
3553  cmtpath = Project::find_in_cmt_paths (real_path);
3554  Project* p = Project::find_by_cmtpath (cmtpath);
3555
3556  //  if (cmtpath != "")
3557  if (p != 0)
3558    {
3559      CmtSystem::compress_path (cmtpath);
3560
3561      static const cmt_string empty_string;
3562      static const cmt_string fs = CmtSystem::file_separator ();
3563     
3564      // In case there are symlinks
3565      //      offset = real_path;
3566      //      offset.replace (cmtpath, empty_string);
3567      //cerr << "realpath_: get_cmtpath_and_offset" << endl;
3568      CmtSystem::realpath_ (real_path, offset);
3569      offset.replace (p->get_cmtpath_real (), empty_string);
3570
3571      /**
3572         try to remove this current CMTPATH entry from path.  This
3573         has a meaning when the specified path already contains an
3574         absolute path.
3575      */
3576     
3577      if (offset[0] == CmtSystem::file_separator ())
3578        {
3579          // Just in case there is a part left after removing the cmtpath entry
3580               
3581          offset.replace (fs, empty_string);
3582        }
3583    }
3584  else
3585    {
3586      offset = real_path;
3587    }
3588}
3589
3590//------------------------------------------------------------
3591bool Use::get_strategy (const cmt_string& name) const
3592{
3593  const Project* p = Project::find_by_cmtpath (Project::find_in_cmt_paths (real_path));
3594
3595  bool strategy;
3596
3597  if (p == 0)
3598    {
3599      static const Project::ProjectPtrVector Ordered = Project::ordered_projects ();
3600      //static const Project::ProjectVector& projects = Project::projects ();
3601
3602      if (Ordered.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
3603      //if (projects.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
3604      else
3605        {
3606          p = Ordered[0];
3607          //p = &(projects[0]);
3608          strategy = p->get_strategy (name);
3609        }
3610    }
3611  else
3612    {
3613      strategy = p->get_strategy (name);
3614    }
3615
3616  return (strategy);
3617}
3618
3619//----------------------------------------------------------
3620void Use::fill_includes_macro (cmt_string& buffer) const
3621{
3622  if (include_path == "")
3623    {
3624      buffer += "$(ppcmd)\"$(";
3625      buffer += get_package_name ();
3626      buffer += "_root)";
3627      buffer += CmtSystem::file_separator ();
3628      buffer += "src\" ";
3629    }
3630  else if (include_path != "none")
3631    {
3632      buffer += "$(ppcmd)\"";
3633      buffer += include_path;
3634      buffer += "\" ";
3635    }
3636 
3637  for (int i = 0; i < includes.size (); i++)
3638    {
3639      Include& incl = includes[i];
3640
3641      if (incl.name == "") continue;
3642     
3643      buffer += "$(ppcmd)\"";
3644      buffer += incl.name;
3645      buffer += "\" ";
3646    }
3647}
3648
3649//----------------------------------------------------------
3650void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
3651{
3652  buffer += " $(";
3653  buffer += get_package_name ();
3654  buffer += "_";
3655  buffer += suffix;
3656  buffer += ") ";
3657}
3658
3659//----------------------------------------------------------
3660void Use::fill_standard_macros (cmt_string& buffer) const
3661{
3662  static cmt_string fs = CmtSystem::file_separator ();
3663
3664  buffer = "";
3665
3666  cmt_string package_name = get_package_name ();
3667
3668  buffer += "macro ";
3669  buffer += package_name;
3670  buffer += "_tag";
3671  buffer += " \"$(tag)\"";
3672  buffer += "\n";
3673
3674  if (located ())
3675    {
3676      buffer += "macro ";
3677      buffer += prefix;
3678      buffer += "ROOT";
3679      buffer += " \"";
3680      buffer += get_full_path ();
3681      buffer += "\"";
3682      buffer += "\n";
3683
3684      buffer += "macro ";
3685      buffer += package_name;
3686      buffer += "_root";
3687      buffer += " \"";
3688      buffer += real_path;
3689      if (style != none_style)
3690        {
3691          buffer += fs;
3692          buffer += package_name;
3693        }
3694      //      if (style != no_version_style)
3695      if (structuring_style == with_version_directory)
3696        {
3697          buffer += fs;
3698          buffer += version;
3699        }
3700      buffer += "\"";
3701      buffer += "\n";
3702    }
3703
3704  buffer += "macro ";
3705  buffer += prefix;
3706  buffer += "VERSION";
3707  buffer += " \"";
3708  buffer += version;
3709  buffer += "\"";
3710  buffer += "\n";
3711
3712  cmt_string cmtpath = "";
3713  cmt_string offset = "";
3714
3715  get_cmtpath_and_offset (cmtpath, offset);
3716
3717  buffer += "macro ";
3718  buffer += package_name;
3719  buffer += "_cmtpath";
3720  buffer += " \"";
3721  buffer += cmtpath;
3722  buffer += "\"";
3723  buffer += "\n";
3724
3725  buffer += "macro ";
3726  buffer += package_name;
3727  buffer += "_offset";
3728  buffer += " \"";
3729  buffer += offset;
3730  buffer += "\"";
3731  buffer += "\n";
3732 
3733  Project* p = Project::find_by_cmtpath (cmtpath);
3734
3735  buffer += "macro ";
3736  buffer += package_name;
3737  buffer += "_project";
3738  buffer += " \"";
3739  if (p != 0)
3740    {
3741      buffer += p->get_name ();
3742    }
3743  buffer += "\"";
3744  buffer += "\n";
3745
3746  buffer += "macro ";
3747  buffer += package_name;
3748  buffer += "_project_release";
3749  buffer += " \"";
3750  if (p != 0)
3751    {
3752      buffer += p->get_release ();
3753    }
3754  buffer += "\"";
3755}
3756
3757
3758//----------------------------------------------------------
3759static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
3760{
3761  bool result = false;
3762
3763  cmt_string here = CmtSystem::pwd ();
3764
3765  cmt_string h1;
3766  if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
3767
3768  CmtSystem::cd (here);
3769
3770  cmt_string h2;
3771  if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
3772
3773  result = (h1 == h2);
3774
3775  CmtSystem::cd (here);
3776
3777  return (result);
3778}
3779
3780//----------------------------------------------------------
3781static bool install_library (const cmt_string& source_library_name, 
3782                             const cmt_string& dest_library_name, 
3783                             const cmt_string& cmtinstallarea, 
3784                             const cmt_string& tag, 
3785                             const cmt_string& symlinkcmd)
3786{
3787  cmt_string libname = source_library_name;
3788  cmt_string name = dest_library_name;
3789  cmt_string s;
3790  Use& current_use = Use::current ();
3791
3792  Symbol::expand (name);
3793  Symbol::expand (libname);
3794
3795  if (cmtinstallarea != "")
3796    {
3797      s = cmtinstallarea;
3798      s += CmtSystem::file_separator ();
3799      s += tag;
3800      s += CmtSystem::file_separator ();
3801      s += "lib";
3802      s += CmtSystem::file_separator ();
3803      s += name;
3804     
3805      // Now creating the reference file
3806
3807      cmt_string ref_file = s;
3808      ref_file += ".cmtref";
3809
3810      cmt_string text = libname;
3811      text += "\n";
3812
3813      Symbol::expand (ref_file);
3814      Symbol::expand (text);
3815
3816      if (CmtMessage::active (Info))
3817        cerr << "   Creating the reference file " << ref_file << endl;
3818          //      if (!Cmt::get_quiet ()) cerr << "   Creating the reference file " << ref_file << endl;
3819      text.write (ref_file);
3820    }
3821  else
3822    {
3823      if (current_use.style != none_style)
3824        {
3825          s = "../$(";
3826          s += current_use.get_package_name ();
3827          s += "_tag)/";
3828        }
3829      else
3830        {
3831          s = "./";
3832        }
3833      s += name;
3834    }
3835
3836  Symbol::expand (s);
3837
3838  cmt_string source;
3839  cmt_string dest;
3840
3841  CmtSystem::dirname (libname, source);
3842  CmtSystem::dirname (s, dest);
3843
3844  if (same_dirs (source, dest))
3845    {
3846      return (false);
3847    }
3848
3849  //if (!Cmt::get_quiet ())
3850  if (CmtMessage::active (Info))
3851    cerr << "   Symlinking " << libname << " to " << s << endl;
3852
3853  if (symlinkcmd == "")
3854    {
3855      if (!CmtSystem::create_symlink (libname, s))
3856        {
3857          CmtMessage::error ("Cannot create a symbolic link to " + libname);
3858          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3859          return (false);
3860        }
3861    }
3862  else
3863    {
3864      cmt_string cmd = symlinkcmd;
3865      cmd += " ";
3866      cmd += libname;
3867      cmd += " ";
3868      cmd += s;
3869     
3870      int status = CmtSystem::execute (cmd);
3871     
3872      if (status != 0)
3873        {
3874          CmtMessage::error ("Cannot create a symbolic link to " + libname);
3875          //      cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3876          return (false);
3877        }
3878    }
3879
3880  return (true);
3881}
3882
3883
3884/**
3885   Centralize the construction of library links for this Use.
3886*/
3887void Use::build_library_links (const cmt_string& cmtinstallarea, 
3888                               const cmt_string& tag, 
3889                               const cmt_string& shlibsuffix, 
3890                               const cmt_string& symlinkcmd) const
3891{
3892  if (!located ())
3893    {
3894      CmtMessage::warning ("package " + get_package_name ()
3895                           + " " + version + " " + path
3896                           + " not found");
3897      /*
3898      if (!Cmt::get_quiet ())
3899        {
3900          cerr << "# package " << get_package_name () <<
3901            " " << version << " " << path <<
3902            " not found" <<
3903            endl;
3904        }
3905      */
3906      return;
3907    }
3908
3909  cmt_string s;
3910
3911  s = get_package_name ();
3912  s += "_libraries";
3913
3914  Symbol* libraries_macro = Symbol::find (s);
3915
3916  if (libraries_macro == 0) return;
3917
3918  cmt_string libraries = libraries_macro->build_macro_value ();
3919  Symbol::expand (libraries);
3920  static CmtSystem::cmt_string_vector values;
3921
3922  CmtSystem::split (libraries, " \t", values);
3923
3924  for (int j = 0; j < values.size (); j++)
3925    {
3926      const cmt_string& library = values[j];
3927
3928      static cmt_string libname;
3929      static cmt_string name;
3930
3931      // Is it a simple name or a complete path?
3932
3933      libname = library;
3934      Symbol::expand (libname);
3935
3936      bool is_absolute = false;
3937
3938      is_absolute = CmtSystem::absolute_path (libname);
3939
3940      if (is_absolute)
3941        {
3942          /**
3943           *   We assume here that "library" contains a complete path.
3944           *   (including the complete syntax libxxx.so)
3945           */
3946
3947          cmt_string suffix;
3948          CmtSystem::basename (library, name);
3949        }
3950      else
3951        {
3952          /**
3953           *   Here we expect that only the base name of the library
3954           *   is given : ie it should not contain the "lib" prefix,
3955           *   nor the suffix .so, nor any path prefix.
3956           *    This of course should generally correspond to a constituent name.
3957           */
3958         
3959          if (style != none_style)
3960            {
3961          libname = "${";
3962          libname += prefix;
3963          libname += "ROOT}/${";
3964          libname += get_package_name ();
3965          libname += "_tag}/";
3966            }
3967          else
3968            {
3969          libname = "${";
3970          libname += prefix;
3971          libname += "ROOT}/";
3972            }
3973          libname += "$(library_prefix)";
3974          libname += library;
3975          libname += "$(library_suffix)";
3976          libname += ".";
3977          libname += shlibsuffix;
3978
3979          name = "$(library_prefix)";
3980          name += library;
3981          name += "$(library_suffix)";
3982          name += ".";
3983          name += shlibsuffix;
3984        }
3985
3986      if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3987        {
3988          continue;
3989        }
3990
3991#ifdef __APPLE__
3992      if (!is_absolute)
3993        {
3994          if (style != none_style)
3995            {
3996          libname = "${";
3997          libname += prefix;
3998          libname += "ROOT}/${";
3999          libname += get_package_name ();
4000          libname += "_tag}/";
4001            }
4002          else
4003            {
4004          libname = "${";
4005          libname += prefix;
4006          libname += "ROOT}/";
4007            }
4008          libname += library;
4009          libname += ".bundle";
4010
4011          name = library;
4012          name += ".bundle";
4013         
4014          if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
4015            {
4016              continue;
4017            }
4018        }
4019#endif
4020    }
4021}
4022
4023/**
4024 *   This function tries to get the replacement of a Use when it has
4025 *  been discarded by a better match to version constraints.
4026 */
4027Use* Use::get_selected_version ()
4028{
4029  if (!discarded) return (this);
4030
4031  Package* p = m_package;
4032
4033  Use::UsePtrVector& uses = p->get_uses ();
4034
4035  bool dbg = Cmt::get_debug ();
4036
4037  int size = uses.size ();
4038
4039  for (int i = 0; i < size; i++)
4040    {
4041      Use* u = uses[i];
4042      if (u == 0) continue;
4043      if (u->discarded) continue;
4044      if (dbg)
4045        {
4046          cout << "Use::get_selected_version> for package " << get_package_name ()
4047               << "  got a version " << u << endl;
4048        }
4049      return (u);
4050    }
4051
4052  return (0);
4053}
4054
4055/**
4056   Switching from one use to another one, (better wrt
4057   various criteria).
4058
4059   When switching, m_index and auto_imports are
4060   transfered from the un-selected to the newly selected.
4061*/
4062Use* Use::set_selected_version (Use* selected_use)
4063{
4064  if (this == selected_use) return (this);
4065
4066  static UsePtrVector& uses = get_ordered_uses ();
4067
4068  if (m_index >= 0)
4069    {
4070      // This discarded package was registered. We have to substitute
4071      // it with the new one.
4072
4073      if (Cmt::get_debug ())
4074        {
4075          cout << "set_selected_version> Replace "
4076               << get_package_name () << "(" << m_index << ")[" << this << "] with "
4077               << selected_use->get_package_name () << "(" << selected_use->m_index << ")[" << selected_use << "]" << endl;
4078        }
4079
4080      selected_use->m_index = m_index;
4081      selected_use->auto_imports = auto_imports;
4082
4083      selected_use->undiscard ();
4084
4085      m_index = -1;
4086
4087      uses[selected_use->m_index] = selected_use;
4088    }
4089
4090  discard ();
4091
4092  return (selected_use);
4093}
4094
4095//----------------------------------------------------------
4096void Use::set_auto_imports (State context_state, State specified_state,
4097                            cmt_map <Use*, bool>& visited)
4098{
4099  static int level (0);
4100  /*
4101  if (level == 0)
4102    {
4103      unselect_all ();
4104      selected = true;
4105    }
4106  */
4107  switch (context_state)
4108    {
4109    case Unspecified:
4110    case On:
4111      if (!visited.has (this) ||
4112          // revisit uses that may be turned into Off != auto_imports
4113          // via some other use(s)
4114          // policy being use has Off != auto_imports,
4115          // if it is (direct) sub-use without -no_auto_imports of
4116          // either current use or sub-use with Off != auto_imports
4117          (Off == auto_imports && Off != specified_state)
4118          )
4119        {
4120          auto_imports = specified_state;
4121          context_state = UseContext::mask_auto_imports (context_state, auto_imports);
4122        }
4123      else
4124        {
4125          return;
4126        }
4127      break;
4128    case Off:
4129      if (visited.has (this))
4130        {
4131          return;
4132        }
4133      auto_imports = context_state;
4134      break;
4135    }
4136
4137  if (Cmt::get_debug ())
4138    {
4139      cout << "Use::set_auto_imports>|";
4140      for (int i = level; i > 0; i--) cout << "-";
4141      cout << get_package_name () << "> " 
4142           << auto_imports << " -> " 
4143           << "(" << context_state << ")" << specified_state << endl;
4144    }
4145
4146  static bool yes (true);
4147  visited.add (this, yes);
4148
4149  cmt_string s;
4150  static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
4151 
4152  if (Cmt::get_debug ())
4153    {
4154      s = "Use::set_auto_imports><";
4155      for (int i = level; i > 0; i--) s += "-";
4156      s += get_package_name ();
4157      s += "|";
4158      //cout << s << endl;
4159    }
4160 
4161  level++;
4162  for (int i = 0; i < sub_uses.size (); i++)
4163  //for (int i = sub_uses.size () - 1; i >= 0; i--)
4164    {
4165      State state = sub_use_auto_imports[i];
4166      if (Cmt::get_debug ())
4167        {
4168          s += " ";
4169          s += sub_uses[i]->get_package_name ();
4170          s += "(";
4171          s += state_text[state + 1];
4172          s += ")";
4173        }
4174      if (sub_uses[i]->m_index >= 0 && !sub_uses[i]->discarded)
4175        {
4176          sub_uses[i]->set_auto_imports (context_state, state, visited);
4177        }
4178      else
4179        {
4180          if (Cmt::get_debug ())
4181            {
4182              char num[32]; sprintf (num, "%p", sub_uses[i]);
4183              char index[32]; sprintf (index, "%d", sub_uses[i]->m_index);
4184              s += "[";
4185              s += num;
4186              s += ", discarded=";
4187              s += (sub_uses[i]->discarded ? "1" : "0");
4188              s += ", m_index=";
4189              s += index;
4190              s += " : invalid]";
4191            }
4192          Use* au (find_valid (sub_uses[i]->get_package_name ()));
4193          if (au)
4194            {
4195              if (Cmt::get_debug ())
4196                {
4197                  char num[32]; sprintf (num, "%p", au);
4198                  char index[32]; sprintf (index, "%d", au->m_index);
4199                  s += "[";
4200                  s += num;
4201                  s += ", discarded=";
4202                  s += (au->discarded ? "1" : "0");
4203                  s += ", m_index=";
4204                  s += index;
4205                  s += " : valid]";
4206                }
4207              au->set_auto_imports (context_state, state, visited);
4208            }
4209          else
4210            {
4211              visited.add (sub_uses[i], yes);
4212            }
4213        }
4214    }
4215  level--;
4216
4217  if (Cmt::get_debug ())
4218    {
4219      cout << s << endl;
4220    }
4221
4222  return;
4223}
4224/*
4225void Use::set_auto_imports (State new_state)
4226{
4227  if (Cmt::get_debug ())
4228    {
4229      cout << "Use::set_auto_imports>(" << get_package_name () << ") "
4230           << auto_imports << " -> " << new_state << endl;
4231    }
4232
4233  if (auto_imports == new_state) return;
4234 
4235  State old_state = auto_imports;
4236 
4237  auto_imports = new_state;
4238
4239  // We propagate only when we switch from Off to On
4240
4241  if ((old_state == Off) && (new_state == On))
4242    {
4243      cmt_string s;
4244      static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
4245
4246      if (Cmt::get_debug ())
4247        {
4248          s = "Use::set_auto_imports>(";
4249          s += get_package_name ();
4250          s += ") ";
4251
4252          cout << s << endl;
4253        }
4254
4255      for (int i = 0; i < sub_uses.size (); i++)
4256        {
4257          Use* u = sub_uses[i];
4258          State state = sub_use_auto_imports[i];
4259         
4260          if (Cmt::get_debug ())
4261            {
4262              s += " ";
4263              s += u->get_package_name ();
4264              s += "(";
4265              s += state_text[state + 1];
4266              s += ")";
4267            }
4268
4269          if (state == Unspecified)
4270            {
4271              u->set_auto_imports (On);
4272            }
4273        }
4274         
4275      if (Cmt::get_debug ())
4276        {
4277          cout << s << endl;
4278        }
4279    }
4280}
4281*/
4282
4283//----------------------------------------------------------
4284void Use::set_native_version (bool state)
4285{
4286  m_has_native_version = state;
4287}
4288
4289bool Use::has_native_version () const
4290{
4291  return (m_has_native_version);
4292}
4293
4294Package* Use::get_package () const
4295{
4296  return (m_package);
4297}
4298
4299const cmt_string& Use::get_package_name () const
4300{
4301  static const cmt_string null = "";
4302
4303  Package* p = m_package;
4304  if (p == 0) return (null);
4305
4306  return (p->get_name ());
4307}
4308
4309void Use::set_package_name (const cmt_string& name)
4310{
4311  Package* p = Package::add (name);
4312
4313  m_package = p;
4314  p->add_use (this);
4315}
4316
4317int Use::get_index () const
4318{
4319  return (m_index);
4320}
4321
4322//----------------------------------------------------------
4323bool Use::get_all_clients (const cmt_string& to_name)
4324{
4325  Use::UsePtrVector& uses = Use::get_ordered_uses ();
4326
4327  Use* use = Use::find (to_name);
4328
4329  if (use == 0)
4330    {
4331      //      CmtMessage::warning ("No access to " + to_name);
4332      return (false);
4333    }
4334
4335  cmt_map <cmt_string, Use*> all_clients;
4336  cmt_map <cmt_string, Use*> all_clients_ok;
4337
4338  const cmt_string& name = get_package_name ();
4339
4340  Use* me = this;
4341
4342  all_clients.add (name, me);
4343  all_clients_ok.add (name, me);
4344
4345  bool status = get_all_clients (use, to_name, all_clients, all_clients_ok); 
4346
4347  return (status);
4348}
4349
4350//----------------------------------------------------------
4351bool Use::get_all_clients (Use* to, 
4352                           const cmt_string& result, 
4353                           cmt_map <cmt_string, Use*>& all_clients, 
4354                           cmt_map <cmt_string, Use*>& all_clients_ok)
4355{
4356  if (this == to)
4357    {
4358      cout << result << endl;
4359      return (true);
4360    }
4361
4362  const cmt_string& to_name = to->get_package_name ();
4363  const cmt_string& to_version = to->version;
4364
4365  //cout << "gac> from " << get_package_name () << " to " << to_name << " -> " << result << endl;
4366
4367  if (all_clients.has (to_name))
4368    {
4369      if (all_clients_ok.has (to_name))
4370        {
4371          cout << "   ..." << result << endl;
4372          return (true);
4373        }
4374      else
4375        {
4376          return (false);
4377        }
4378    }
4379
4380  all_clients.add (to_name, to);
4381
4382  bool status = false;
4383
4384  Use::UsePtrVector& uses = Use::get_ordered_uses ();
4385  Use* use = 0;
4386
4387  for (int n = 0; n < uses.size (); ++n)
4388    {
4389      use = uses[n];
4390
4391      if (use->discarded) continue;
4392      if (use->m_hidden) continue;
4393
4394      if (!use->located ()) continue;
4395
4396      if (use == to) continue;
4397
4398      if (use->is_client (to_name, to_version))
4399        {
4400          const cmt_string& n = use->get_package_name ();
4401
4402          cmt_string r;
4403
4404          if ((use->initial_scope != ScopeUnspecified) &&
4405              (use->initial_scope != ScopePublic)) 
4406            {
4407              r += "(private)";
4408            }
4409         
4410          if (use->auto_imports == Off) r += "(no_auto_imports)";
4411
4412          r += n;
4413          r += ".";
4414          r += result;
4415
4416          //cout << "gac> " << n << " is client of " << to_name << endl;
4417
4418          if (get_all_clients (use, r, all_clients, all_clients_ok))
4419            {
4420              all_clients_ok.add (n, use);
4421              status = true;
4422            }
4423        }
4424    }
4425
4426  use = this;
4427
4428  if (use->is_client (to_name, to_version))
4429    {
4430      const cmt_string& n = use->get_package_name ();
4431     
4432      cmt_string r;
4433
4434      if ((use->initial_scope != ScopeUnspecified) &&
4435          (use->initial_scope != ScopePublic)) 
4436        {
4437          r += "(private)";
4438        }
4439     
4440      if (use->auto_imports == Off) r += "(no_auto_imports)";
4441
4442      r += n;
4443      r += ".";
4444      r += result;
4445     
4446      //cout << "gac> " << n << " is client of " << to_name << endl;
4447     
4448      if (get_all_clients (use, r, all_clients, all_clients_ok))
4449        {
4450          all_clients_ok.add (n, use);
4451          status = true;
4452        }
4453    }
4454
4455  return (status);
4456}
4457
4458/**
4459   Let's consider two packages in the use graph "this" and "to"
4460   This function finds all packages that are reached in between
4461   following all possible paths between "this" and "to"
4462
4463   Result s accumulated into "list"
4464*/
4465bool Use::get_paths (Use* to, UsePtrVector& list)
4466{
4467  bool is_in_path = false;
4468  bool cycle = false;
4469  bool already_in_path = false;
4470  bool dbg = Cmt::get_debug ();
4471
4472  static int level = 0;
4473
4474  int size = 0;
4475
4476  if (level == 0)
4477    {
4478      unselect_all ();
4479      selected = false;
4480    }
4481
4482  if (selected) 
4483    {
4484      /**
4485         If this use is already in the list, we don't duplicate the entry.
4486         (protection duplicate paths in the graph)
4487      */
4488
4489      size = list.size ();
4490
4491      for (int m = 0; m < size; m++)
4492        {
4493          Use* u = list[m];
4494          if (u == this)
4495            {
4496              if (dbg)
4497                {
4498                  for (int lll = 0; lll < level; lll++) cout << "  ";
4499                  cout << "  Use::get_paths." << level << "> try1.2 sub="
4500                       << get_package_name () << " already_in_path " << endl;
4501                }
4502             
4503              return (true);
4504            }
4505        }
4506
4507      return (false);
4508    }
4509
4510  selected = true;
4511
4512  if (dbg)
4513    {
4514      for (int lll = 0; lll < level; lll++) cout << "  ";
4515      cout << "Use::get_paths." << level << ">" << get_package_name ()
4516           << " to=" << to->get_package_name () 
4517           << " list=[";
4518
4519      for (int m = 0; m < list.size (); m++)
4520        {
4521          Use* u = list[m];
4522          cout << u->get_package_name () << " ";
4523        }
4524
4525      cout << "]" << endl;
4526    }
4527
4528  /**
4529     Now "this" is a candidate new entry in the list
4530  */
4531
4532  // First figure out whether 'to' is used by 'this'.
4533
4534  if (this->get_package_name () == to->get_package_name ())
4535    {
4536      // We've reached the goal (for the first time)
4537      is_in_path = true;
4538    }
4539  else
4540    {
4541      /**
4542         Let's scan sub_uses now
4543      */
4544      size = sub_uses.size ();
4545
4546      if (dbg)
4547        {
4548          for (int lll = 0; lll < level; lll++) cout << "  ";
4549          cout << "  Use::get_paths." << level << "> size=" << size << endl;
4550        }
4551
4552      for (int n = 0; n < size; n++)
4553        {
4554          Use* use = sub_uses[n];
4555
4556          if (use == 0) continue;
4557
4558          if (dbg)
4559            {
4560              for (int lll = 0; lll < level; lll++) cout << "  ";
4561              cout << "  Use::get_paths." << level << "> try1 sub="
4562                   << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
4563            }
4564
4565          if (use->discarded)
4566            {
4567              Use* u;
4568
4569              u = use->get_selected_version ();
4570              if (u == 0) 
4571                {
4572                  /**
4573                     No way to find a valid use for this used package.
4574                     Is that a bug?
4575                     Anyway we don't pursue on that branch.
4576                  */
4577                  continue;
4578                }
4579
4580              use = u;
4581            }
4582
4583          if (dbg)
4584            {
4585              for (int lll = 0; lll < level; lll++) cout << "  ";
4586              cout << "  Use::get_paths." << level << "> try2 sub="
4587                   << use->get_package_name () << " " << use->discarded << endl;
4588            }
4589
4590          level++;
4591          bool r = use->get_paths (to, list);
4592          level--;
4593
4594          if (r)
4595            {
4596              is_in_path = true;
4597            }
4598        }
4599    }
4600
4601  if (is_in_path)
4602    {
4603      if (dbg)
4604        {
4605          for (int lll = 0; lll < level; lll++) cout << "  ";
4606          cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
4607        }
4608      list.push_back (this);
4609    }
4610
4611  return (is_in_path);
4612}
4613
4614//----------------------------------------------------------
4615bool Use::located () const
4616{
4617  return (m_located);
4618}
4619
4620//----------------------------------------------------------
4621void Use::show_sub_uses (cmt_map <Use*, bool>& visited,
4622                         const cmt_string& request, State specified_state,
4623                         bool skip_discarded, ostream& out)
4624//void Use::show_sub_uses (const cmt_string& request, bool skip_discarded, ostream& out)
4625{
4626  if (skip_discarded && discarded) return;
4627  if (m_hidden) return;
4628
4629  Use* current = &(Use::current ());
4630  static State context_state (auto_imports);
4631  static int level (0);
4632
4633  if (level == 0)
4634    {
4635      unselect_all ();
4636      selected = false;
4637    }
4638
4639  if (level > 0)
4640    {
4641      out << "# ";
4642      for (int n = 0; n < (level-1); n++) out << "  ";
4643
4644      if (request == "")
4645        {
4646          out << "use " << get_package_name () << " " << specified_version;
4647
4648          if (this == current) 
4649            {
4650              out << " (current)";
4651            }
4652          else
4653            {
4654              if (specified_path != "") out << " " << specified_path;
4655            }
4656        }
4657      else
4658        {
4659          out << "use " << request;
4660        }
4661
4662      if (version_alias != "")
4663        {
4664          out << " | " << version_alias << " " << path_alias;
4665        }
4666
4667      if (initial_scope == ScopeUnspecified) out << " (unspecified)";
4668      else if (initial_scope != ScopePublic) out << " (private)";
4669
4670      if (specified_state == Off) out << " (no_auto_imports)";
4671      //      if (auto_imports == Off) out << " (no_auto_imports)";
4672
4673      if (structuring_style == without_version_directory) out << " (no_version_directory)";
4674
4675      if (m_has_native_version)
4676        {
4677          cmt_string n = get_package_name ();
4678          n += "_native_version";
4679
4680          Symbol* s = Symbol::find (n);
4681          if (s != 0)
4682            {
4683              cmt_string value = s->resolve_macro_value ();
4684              out << " (native_version=" << value << ")";
4685            }
4686        }
4687
4688      out << endl;
4689    }
4690
4691  //  if (selected) return;
4692  //  selected = true;
4693
4694  State saved_context_state (context_state);
4695
4696  switch (context_state)
4697    {
4698    case Unspecified:
4699    case On:
4700      if (!visited.has (this) ||
4701          !selected)
4702        // selected == true means that
4703        // this use has been shown with its actual auto_imports
4704        // either Off != auto_imports or Off == auto_imports,
4705        // mark selected not to consider use again and thus avoid looping this way
4706        {
4707          switch (specified_state)
4708            {
4709            case Unspecified:
4710            case On:
4711              if (Off != auto_imports)
4712                {
4713                  // this path to use is informative
4714                  // want to revisit sub-uses
4715                  // to possibly find Off != auto_imports paths to them
4716                  selected = true;
4717                }
4718              break;
4719            case Off:
4720              if (Off == auto_imports)
4721                {
4722                  // this path to use is informative
4723                  // no point in revisiting sub-uses
4724                  selected = true;
4725                  if (visited.has (this)) return;
4726                }
4727              else
4728                {
4729                  // this path to use is not informative
4730                  // no point in (re)visiting sub-uses
4731                  return;
4732                }
4733              break;
4734            }
4735          context_state = UseContext::mask_auto_imports (context_state, specified_state);
4736        }
4737      else
4738        {
4739          return;
4740        }
4741      break;
4742    case Off:
4743      if (!visited.has (this) ||
4744          !selected)
4745        {
4746          if (Off == auto_imports)
4747            {
4748              // this path to use is informative
4749              // no point in revisiting sub-uses
4750              selected = true;
4751              if (visited.has (this)) return;
4752            }
4753          else
4754            {
4755              // this path to use is not informative
4756              // no point in (re)visiting sub-uses
4757              return;
4758            }
4759        }
4760      else
4761        {
4762          return;
4763        }
4764      break;
4765    }
4766
4767  static bool yes (true);
4768  visited.add (this, yes);
4769
4770  level++;
4771  for (int i = 0; i < sub_uses.size (); i++)
4772    {
4773      //if (use == 0) continue;
4774      Use* use;
4775      if (sub_uses[i]->m_index >= 0 && !sub_uses[i]->discarded)
4776        {
4777          use = sub_uses[i];
4778        }
4779      else
4780        {
4781          Use* au (find_valid (sub_uses[i]->get_package_name ()));
4782          if (au)
4783            {
4784              use = au;
4785            }
4786          else
4787            {
4788              sub_uses[i]->select ();
4789              visited.add (sub_uses[i], yes);
4790              continue;
4791            }
4792        }
4793
4794      const cmt_string& request = requests[i];
4795
4796      ScopeType saved_scope = use->initial_scope;
4797      //      State saved_state = use->auto_imports;
4798
4799      use->initial_scope = sub_use_scopes[i];
4800      //      use->auto_imports = sub_use_auto_imports[i];
4801
4802      use->show_sub_uses (visited, request, sub_use_auto_imports[i], skip_discarded, out);
4803      //use->show_sub_uses (request, skip_discarded, out);
4804
4805      use->initial_scope = saved_scope;
4806      //      use->auto_imports = saved_state;
4807    }
4808  level--;
4809
4810  context_state = saved_context_state;
4811}
4812
4813//----------------------------------------------------------
4814Use& Use::current ()
4815{
4816  static UseVector& instances = get_instances ();
4817  static Use* current_use = 0;
4818
4819  if ((current_use == 0) || (instances.size () == 0))
4820    {
4821      Use& use_object = instances.add ();
4822      current_use = &use_object;
4823    }
4824
4825  return (*current_use);
4826}
4827
4828//----------------------------------------------------------
4829const Use& Use::const_current ()
4830{
4831  const Use& use = Use::current ();
4832
4833  return (use);
4834}
4835
4836//----------------------------------------------------------
4837Use::UseVector& Use::get_instances ()
4838{
4839  static Database& db = Database::instance ();
4840  static UseVector& instances = db.all_uses ();
4841
4842  return (instances);
4843}
4844
4845//----------------------------------------------------------
4846Use::UsePtrVector& Use::get_ordered_uses ()
4847{
4848  static Database& db = Database::instance ();
4849  static UsePtrVector& uses = db.uses ();
4850
4851  return (uses);
4852}
4853
4854//----------------------------------------------------------
4855
4856//----------------------------------------------------------
4857//
4858//  Check if the specified version is better than the
4859//  current one.
4860//
4861//----------------------------------------------------------
4862Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
4863{
4864  Use* selected = ref_use;
4865
4866  int ref_v = -1;
4867  int ref_r = -1;
4868  int ref_p = -1;
4869  cmt_string ref_pp;
4870
4871  int new_v = -1;
4872  int new_r = -1;
4873  int new_p = -1;
4874  cmt_string new_pp;
4875
4876  int alias_v = -1;
4877  int alias_r = -1;
4878  int alias_p = -1;
4879  cmt_string alias_pp;
4880
4881  enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
4882
4883  // First analyze specified versions
4884  cmt_string ref_version = ref_use->specified_version;
4885  cmt_string new_version = new_use->specified_version;
4886
4887  CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
4888  ref_pp = ref_use->path;
4889
4890  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
4891  new_pp = new_use->path;
4892
4893  if (new_use->version_alias != "")
4894    {
4895      has_alias = new_has_alias;
4896      CmtSystem::is_version_directory (new_use->version_alias, 
4897                                       alias_v, alias_r, alias_p);
4898      alias_pp = new_use->path_alias;
4899    }
4900  else if (ref_use->version_alias != "")
4901    {
4902      has_alias = ref_has_alias;
4903      CmtSystem::is_version_directory (ref_use->version_alias, 
4904                                       alias_v, alias_r, alias_p);
4905      alias_pp = ref_use->path_alias;
4906    }
4907
4908  ref_use->undiscard ();
4909  new_use->undiscard ();
4910
4911  if (new_v != ref_v)
4912    {
4913      if (has_alias != no_alias)
4914        {
4915          if (has_alias == new_has_alias)
4916            {
4917              new_v = alias_v;
4918              new_r = alias_r;
4919              new_p = alias_p;
4920              new_pp = alias_pp;
4921            }
4922          else if (has_alias == ref_has_alias)
4923            {
4924              ref_v = alias_v;
4925              ref_r = alias_r;
4926              ref_p = alias_p;
4927              ref_pp = alias_pp;
4928            }
4929        }
4930    }
4931
4932  bool ref_v_wildcarded = ((ref_v) == -1);
4933  bool ref_r_wildcarded = ((ref_r) == -1);
4934  bool ref_p_wildcarded = ((ref_p) == -1);
4935
4936  bool ref_v_explicit = !ref_v_wildcarded;
4937  bool ref_r_explicit = !ref_r_wildcarded;
4938  bool ref_p_explicit = !ref_p_wildcarded;
4939
4940  bool new_v_wildcarded = ((new_v) == -1);
4941  bool new_r_wildcarded = ((new_r) == -1);
4942  bool new_p_wildcarded = ((new_p) == -1);
4943
4944  bool new_v_explicit = !new_v_wildcarded;
4945  bool new_r_explicit = !new_r_wildcarded;
4946  bool new_p_explicit = !new_p_wildcarded;
4947
4948  bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
4949
4950  cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
4951  cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
4952  cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
4953 
4954  cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
4955  cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
4956  cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
4957
4958  // Now compute effective version identifiers
4959  CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
4960  CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
4961
4962  cmt_string new_selected_version = new_use->version;
4963
4964  if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
4965    {
4966      /*
4967        if (verbose && !Cmt::get_quiet ())
4968        {
4969        cerr << "# Required explicit version " << new_version
4970        << " of package " << ref_use->get_package_name ()
4971        << " incompatible with selected explicit version " << ref_version
4972        << endl;
4973        }
4974
4975        CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
4976
4977        if (ref_use != new_use) new_use->discard ();
4978      */
4979
4980      if (new_v > ref_v)
4981        {
4982          if (verbose && !Cmt::get_quiet ())
4983            {
4984              cerr << "# Select " << new_vc << " version " << new_version
4985                   << " of package " << ref_use->get_package_name () 
4986                   << " instead of existing " << ref_vc << " " << ref_version
4987                   << endl;
4988            } 
4989         
4990          if (ref_use != new_use) ref_use->discard ();
4991          selected = new_use;
4992          selected->done = false; // Will read the new requirements
4993        }
4994    }
4995  else if (new_v_wildcarded || ref_v_wildcarded)
4996    {
4997      // at least one of ref or new is wildcarded
4998
4999      //
5000      // we plan to discard new_use, but if it was specified as explicit
5001      // and ref_use was wildcarded then new_use will win !!
5002      //
5003      // So then we'll have to understand where are the wild
5004      // cards... If they are on v or r, then we consider them.
5005      //
5006      //
5007
5008      if (ref_v_wildcarded && new_v_explicit)
5009        {
5010          if ((ref_use->real_path != new_use->real_path) ||
5011              (ref_use->version != new_use->version))
5012            {
5013              if (ref_use != new_use) ref_use->discard ();
5014              selected = new_use;
5015              selected->done = false; // Will read the new requirements
5016
5017              if (verbose && !Cmt::get_quiet ())
5018                {
5019                  cerr << "# Select explicit version " << new_version
5020                       << "(" << new_use->version << ")" 
5021                       << " of package " << ref_use->get_package_name () 
5022                       << " instead of existing wildcarded " << ref_version
5023                       << "(" << ref_use->version << ")" 
5024                       << endl;
5025                }
5026            }
5027          else
5028            {
5029              if (ref_use != new_use) new_use->discard ();
5030              //ref_use->version = new_selected_version;
5031            }
5032        }
5033      else
5034        {
5035          // ref is explicit or new is wildcarded
5036
5037          /*
5038            if (verbose && !Cmt::get_quiet ())
5039            {
5040            cerr << "# keep " << ref_vc << " version " << ref_version
5041            << " of package " << ref_use->get_package_name ()
5042            << " (ignore " << new_vc << " version " << new_version << ")"
5043            << endl;
5044            }
5045          */
5046
5047          if (ref_use != new_use) new_use->discard ();
5048        }
5049    }
5050  else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
5051    {
5052      //
5053      // we plan to discard new_use, but if it was specified as explicit
5054      // and ref_use was wildcarded then new_use will win !!
5055      //
5056      // So then we'll have to understand where are the wild
5057      // cards... If they are on v or r, then we consider them.
5058      //
5059      //
5060
5061      if (ref_r_wildcarded && new_r_explicit)
5062        {
5063          // ref has wild card and new has not => new wins
5064
5065          if ((ref_use->real_path != new_use->real_path) ||
5066              (ref_use->version != new_use->version))
5067            {
5068              if (ref_use != new_use) ref_use->discard ();
5069              selected = new_use;
5070              selected->done = false; // Will read the new requirements
5071
5072              if (verbose && !Cmt::get_quiet ())
5073                {
5074                  cerr << "# Select explicit release " << new_version
5075                       << " of package " << ref_use->get_package_name ()
5076                       << " instead of existing wildcarded " << ref_version
5077                       << endl;
5078                } 
5079            }
5080          else
5081            {
5082              // Just adapt version with new one.
5083
5084              if (ref_use != new_use) new_use->discard ();
5085              //ref_use->version = new_selected_version;
5086            }
5087        }
5088      else
5089        {
5090          /*
5091            if (verbose &&!Cmt::get_quiet ())
5092            {
5093            cerr << "# keep " << ref_rc << " release " << ref_version
5094            << " of package " << ref_use->get_package_name ()
5095            << " (ignore " << new_rc << " release " << new_version << ")"
5096            << endl;
5097            }
5098          */
5099
5100          if (ref_use != new_use) new_use->discard ();
5101        }
5102    }
5103  else if (new_r > ref_r)
5104    {
5105      if (verbose && !Cmt::get_quiet ())
5106        {
5107          cerr << "# Select " << new_rc << " release " << new_version
5108               << " of package " << ref_use->get_package_name () 
5109               << " instead of existing " << ref_rc << " " << ref_version
5110               << endl;
5111        } 
5112
5113      if (ref_use != new_use) ref_use->discard ();
5114      selected = new_use;
5115      selected->done = false; // Will read the new requirements
5116    }
5117  else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
5118    {
5119      //
5120      // we plan to discard new_use, but if it was specified as explicit
5121      // and ref_use was wildcarded then new_use will win !!
5122      //
5123
5124      if (ref_p_wildcarded && new_p_explicit)
5125        {
5126          if ((ref_use->real_path != new_use->real_path) ||
5127              (ref_use->version != new_use->version))
5128            {
5129              if (ref_use != new_use) ref_use->discard ();
5130              selected = new_use;
5131              selected->done = false; // Will read the new requirements
5132
5133              if (verbose && !Cmt::get_quiet ())
5134                {
5135                  cerr << "# Select explicit patch " << new_version
5136                       << " of package " << ref_use->get_package_name () 
5137                       << " instead of existing wildcarded " << ref_version
5138                       << endl;
5139                }
5140            }
5141          else
5142            {
5143              if (ref_use != new_use) new_use->discard ();
5144              ref_use->version = new_selected_version;
5145            }
5146        }
5147      else
5148        {
5149          /*
5150            if (verbose && !Cmt::get_quiet ())
5151            {
5152            cerr << "# keep " << ref_pc << " patch " << ref_version
5153            << " [" << ref_use->specified_version << "]"
5154            << " of package " << ref_use->get_package_name ()
5155            << " (ignore " << new_pc << " version " << new_version << ")"
5156            << " [" << new_use->specified_version << "]"
5157            << endl;
5158            }
5159          */
5160
5161          if (ref_use != new_use) new_use->discard ();
5162        }
5163    }
5164  else if (new_p > ref_p)
5165    {
5166      if (verbose && !Cmt::get_quiet ())
5167        {
5168          cerr << "# Select " << new_pc << " patch " << new_version
5169               << " of package " << ref_use->get_package_name () 
5170               << " instead of existing " << ref_pc << " " << ref_version
5171               << endl;
5172        }
5173
5174      if (ref_use != new_use) ref_use->discard ();
5175      selected = new_use;
5176      selected->done = false; // Will read the new requirements
5177    }
5178  else if (new_pp != ref_pp) // same version-r-p but from different path
5179    {
5180      if (ref_use != new_use) ref_use->discard ();
5181      selected = new_use;
5182      selected->done = false; // Will read the new requirements
5183    }
5184
5185  return (selected);
5186}
5187
5188
5189//----------------------------------------------------------
5190class VersionReader : public Awk
5191{
5192public:
5193
5194  VersionReader ()
5195  {
5196  }
5197 
5198  const cmt_string& get_version () const
5199  {
5200    return (m_version);
5201  }
5202 
5203  void filter (const cmt_string& line)
5204  {
5205    CmtSystem::cmt_string_vector words;
5206    CmtSystem::split (line, " \t", words);
5207    if (words[0] == "version")
5208      {
5209        m_version = words[1];
5210      }
5211  }
5212 
5213private:
5214  cmt_string m_version;
5215};
5216
5217//----------------------------------------------------------
5218class PackageReader : public Awk
5219{
5220public:
5221
5222  PackageReader ()
5223  {
5224  }
5225 
5226  const cmt_string& get_package () const
5227  {
5228    return (m_package);
5229  }
5230 
5231  void filter (const cmt_string& line)
5232  {
5233    CmtSystem::cmt_string_vector words;
5234    CmtSystem::split (line, " \t", words);
5235    if (words[0] == "package")
5236      {
5237        m_package = words[1];
5238      }
5239  }
5240 
5241private:
5242  cmt_string m_package;
5243};
5244
5245//----------------------------------------------------------
5246Package* Package::find (const cmt_string& name)
5247{
5248  static PackageMap& PackageMap = package_map ();
5249
5250  Package* result = 0;
5251
5252  result = PackageMap.find (name);
5253
5254  return (result);
5255}
5256
5257//----------------------------------------------------------
5258Package* Package::add (const cmt_string& name)
5259{
5260  static PackageVector& Packages = packages ();
5261  static PackageMap& PackageMap = package_map ();
5262
5263  {
5264    Package* package;
5265
5266    package = find (name);
5267    if (package != 0) return (package);
5268  }
5269
5270  Package& package = Packages.add ();
5271  PackageMap.add (name, package);
5272
5273  package.m_name = name;
5274
5275  if (name == "CMT")
5276    {
5277      package.m_is_cmt = true;
5278    }
5279  else if (name == "methods")
5280    {
5281      package.m_is_cmt = true;
5282    }
5283
5284  if (Cmt::get_debug ())
5285    {
5286      cout << "Package::add (" << name << ")" << endl;
5287    }
5288
5289  return (&package);
5290}
5291
5292//----------------------------------------------------------
5293Package::PackageVector& Package::packages ()
5294{
5295  static Database& db = Database::instance ();
5296  static PackageVector& Packages = db.packages ();
5297
5298  return (Packages);
5299}
5300
5301//----------------------------------------------------------
5302Package::PackageMap& Package::package_map ()
5303{
5304  static Database& db = Database::instance ();
5305  static PackageMap& PackageMap = db.package_map ();
5306
5307  return (PackageMap);
5308}
5309
5310//----------------------------------------------------------
5311void Package::clear_all ()
5312{
5313  static PackageVector& Packages = packages ();
5314  static PackageMap& PackageMap = package_map ();
5315
5316  PackageMap.clear ();
5317  Packages.clear ();
5318}
5319
5320//----------------------------------------------------------
5321bool Package::get_version (cmt_string& version, const cmt_string& path)
5322{
5323  cmt_string version_file = path;
5324  version_file += CmtSystem::file_separator ();
5325  version_file += get_version_file_name ();
5326  if (CmtSystem::test_file (version_file))
5327    {
5328      cmt_string v;
5329      if (v.read (version_file))
5330        {
5331          int pos;
5332          pos = v.find ('\n');
5333          if (pos != cmt_string::npos) v.erase (pos);
5334          pos = v.find ('\r');
5335          if (pos != cmt_string::npos) v.erase (pos);
5336          if (v != "")
5337            {
5338              version = v;
5339              return true;
5340            }
5341        }
5342      else
5343        {
5344          CmtMessage::warning ("Could not read `" + version_file + "'.");
5345        }
5346    }
5347
5348  version_file = path;
5349  version_file += CmtSystem::file_separator ();
5350  version_file += "requirements";
5351  cmt_string text;
5352  if (text.read (version_file))
5353    {
5354      VersionReader reader;
5355      reader.run (text);
5356      cmt_string v = reader.get_version ();
5357      if (v != "")
5358        {
5359          version = v;
5360          return true;
5361        }
5362    }
5363  else
5364    {
5365      CmtMessage::warning ("Could not read `" + version_file + "'.");
5366    }
5367
5368  return false;
5369}
5370
5371//----------------------------------------------------------
5372const cmt_string& Package::get_version_file_name ()
5373{
5374  static const cmt_string name = "version.cmt";
5375
5376  return (name);
5377}
5378
5379//----------------------------------------------------------
5380bool Package::get_name (cmt_string& name, const cmt_string& path)
5381{
5382  cmt_string name_file = path;
5383  name_file += CmtSystem::file_separator ();
5384  name_file += "requirements";
5385  cmt_string text;
5386  if (text.read (name_file))
5387    {
5388      PackageReader reader;
5389      reader.run (text);
5390      cmt_string v = reader.get_package ();
5391      if (v != "")
5392        {
5393          name = v;
5394          return true;
5395        }
5396    }
5397  else
5398    {
5399      CmtMessage::warning ("Could not read `" + name_file + "'.");
5400    }
5401
5402  return false;
5403}
5404
5405//----------------------------------------------------------
5406Package::Package () : m_is_cmt (false)
5407{
5408  if (Cmt::get_debug ())
5409    {
5410      cout << "Package::Package" << endl;
5411    }
5412}
5413
5414//----------------------------------------------------------
5415Package::~Package ()
5416{
5417  m_name = "";
5418}
5419
5420//----------------------------------------------------------
5421const cmt_string& Package::get_name () const
5422{
5423  return (m_name);
5424}
5425
5426//----------------------------------------------------------
5427void Package::add_use (Use* use)
5428{
5429  for (int i = 0; i < m_uses.size (); i++)
5430    {
5431      Use* u = m_uses[i];
5432      if (u == use) return;
5433    }
5434
5435  m_uses.push_back (use);
5436}
5437
5438//----------------------------------------------------------
5439void Package::remove_use (Use* use)
5440{
5441  if (Cmt::get_debug ())
5442    {
5443      cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
5444      cout << "  name=" << m_name
5445           << " uses=" << m_uses.size () << endl;
5446    }
5447
5448  Use::UsePtrVector temp;
5449
5450  temp = m_uses;
5451
5452  m_uses.clear ();
5453
5454  for (int i = 0; i < temp.size (); i++)
5455    {
5456      Use* u = temp[i];
5457      if (u != use)
5458        {
5459          m_uses.push_back (u);
5460        }
5461    }
5462}
5463
5464//----------------------------------------------------------
5465Use::UsePtrVector& Package::get_uses ()
5466{
5467  return (m_uses);
5468}
5469
5470//----------------------------------------------------------
5471bool Package::is_cmt ()
5472{
5473  return (m_is_cmt);
5474}
5475
5476//----------------------------------------------------------
5477static void show_packages ()
5478{
5479  Package::PackageVector& vector = Package::packages ();
5480
5481  int i;
5482  int j;
5483
5484  cout << "### Packages: ";
5485  for (i = 0; i < vector.size (); i++)
5486    {
5487      Package& p = vector[i];
5488      cout << p.get_name () << "[";
5489      Use::UsePtrVector& uses = p.get_uses ();
5490      for (j = 0; j < uses.size (); j++)
5491        {
5492          Use* u = uses[j];
5493          cout << u << ",";
5494        }
5495
5496      cout << "] ";
5497    }
5498  cout << endl;
5499
5500  {
5501    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
5502
5503    cout << "### Uses: ";
5504    for (i = 0; i < uses.size (); i++)
5505      {
5506        Use* u = uses[i];
5507        cout << "[" << u << "]" << u->get_package_name () << " ";
5508      }
5509  }
5510
5511  cout << endl;
5512}
5513
5514//----------------------------------------------------------
5515Project* Use::get_project ()
5516{   
5517  Project* p;
5518  cmt_string cmtpath = "";
5519  cmt_string offset  = "";   
5520  get_cmtpath_and_offset (cmtpath, offset);
5521  p = Project::find_by_cmtpath (cmtpath);
5522  return p;   
5523}
5524
5525//----------------------------------------------------------
5526cmt_string Use::get_info () const
5527{   
5528  return get_package_name () + " " + (version != "" ? version : "*") +
5529    (path != "" ? " " + path : "") ;
5530  //  return get_package_name () + " " + version + (path != "" ? " " + path : "") ;
5531}
5532
5533//----------------------------------------------------------
5534/**
5535 *    Check whether @version@
5536 *    is head version as specified by CMTHEADVERSION symbol/environment variable
5537 *    or equals HEAD|head
5538 */
5539//----------------------------------------------------------
5540bool Use::is_head_version (const cmt_string& version)
5541{
5542  if (!m_head_version.is_valid ())
5543    {
5544      cmt_string s (Symbol::get_env_value ("CMTHEADVERSION"));
5545      static const cmt_string package_template = "<package>";
5546      s.replace_all (package_template, get_package_name ());
5547      static const cmt_string PACKAGE_template = "<PACKAGE>";
5548      s.replace_all (PACKAGE_template, prefix);
5549      static const cmt_string revision_template = "<revision>";
5550      s.replace_all (revision_template.c_str (), "[0-9]*");
5551      if (0 != s.size ())
5552        {
5553          if ('^' != s[0]) s = "^" + s;
5554          if ('$' != s[s.size () - 1]) s = s + "$";
5555        }
5556      else
5557        {
5558          s = "^(HEAD|head)$";
5559        }
5560      m_head_version.set (s);
5561      if (!m_head_version.is_valid ())
5562        {
5563          CmtMessage::warning
5564            (CmtError::get_error_name (CmtError::configuration_error)
5565             + ": CMTHEADVERSION regular expression invalid `" + s + "'");
5566        }
5567    }
5568
5569  return m_head_version.match (version);
5570}
Note: See TracBrowser for help on using the repository browser.