source: CMT/v1r18p20051101/source/cmt_use.cxx

Last change on this file was 81, checked in by arnault, 19 years ago

moving get_strategy to cmt_use - see CL#276

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