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

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

Preparing support for projects in CVS - See CL 270

  • Property svn:eol-style set to native
File size: 97.8 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//----------------------------------------------------------
2879void Use::fill_includes_macro (cmt_string& buffer) const
2880{
2881  if (include_path == "")
2882    {
2883      buffer += "$(ppcmd)\"$(";
2884      buffer += get_package_name ();
2885      buffer += "_root)";
2886      buffer += CmtSystem::file_separator ();
2887      buffer += "src\" ";
2888    }
2889  else if (include_path != "none")
2890    {
2891      buffer += "$(ppcmd)\"";
2892      buffer += include_path;
2893      buffer += "\" ";
2894    }
2895 
2896  for (int i = 0; i < includes.size (); i++)
2897    {
2898      Include& incl = includes[i];
2899     
2900      buffer += "$(ppcmd)\"";
2901      buffer += incl.name;
2902      buffer += "\" ";
2903    }
2904}
2905
2906//----------------------------------------------------------
2907void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
2908{
2909  buffer += " $(";
2910  buffer += get_package_name ();
2911  buffer += "_";
2912  buffer += suffix;
2913  buffer += ") ";
2914}
2915
2916//----------------------------------------------------------
2917void Use::fill_standard_macros (cmt_string& buffer) const
2918{
2919  static cmt_string fs = CmtSystem::file_separator ();
2920
2921  buffer = "";
2922
2923  cmt_string package_name = get_package_name ();
2924
2925  buffer += "macro ";
2926  buffer += package_name;
2927  buffer += "_tag";
2928  buffer += " \"$(tag)\"";
2929  buffer += "\n";
2930
2931  if (located ())
2932    {
2933      buffer += "macro ";
2934      buffer += prefix;
2935      buffer += "ROOT";
2936      buffer += " \"";
2937      buffer += get_full_path ();
2938      buffer += "\"";
2939      buffer += "\n";
2940
2941      buffer += "macro ";
2942      buffer += package_name;
2943      buffer += "_root";
2944      buffer += " \"";
2945      buffer += real_path;
2946      buffer += fs;
2947      buffer += package_name;
2948      if (style != no_version_style)
2949        {
2950          buffer += fs;
2951          buffer += version;
2952        }
2953      buffer += "\"";
2954      buffer += "\n";
2955    }
2956
2957  buffer += "macro ";
2958  buffer += prefix;
2959  buffer += "VERSION";
2960  buffer += " \"";
2961  buffer += version;
2962  buffer += "\"";
2963  buffer += "\n";
2964
2965  cmt_string cmtpath = "";
2966  cmt_string offset = "";
2967
2968  get_cmtpath_and_offset (cmtpath, offset);
2969
2970  buffer += "macro ";
2971  buffer += package_name;
2972  buffer += "_cmtpath";
2973  buffer += " \"";
2974  buffer += cmtpath;
2975  buffer += "\"";
2976  buffer += "\n";
2977
2978  buffer += "macro ";
2979  buffer += package_name;
2980  buffer += "_offset";
2981  buffer += " \"";
2982  buffer += offset;
2983  buffer += "\"";
2984  buffer += "\n";
2985 
2986  Project* p = Project::find_by_cmtpath (cmtpath);
2987
2988  buffer += "macro ";
2989  buffer += package_name;
2990  buffer += "_project";
2991  buffer += " \"";
2992  if (p != 0)
2993    {
2994      buffer += p->get_name ();
2995    }
2996  buffer += "\"";
2997
2998  buffer += "macro ";
2999  buffer += package_name;
3000  buffer += "_project_release";
3001  buffer += " \"";
3002  if (p != 0)
3003    {
3004      buffer += p->get_release ();
3005    }
3006  buffer += "\"";
3007}
3008
3009
3010//----------------------------------------------------------
3011static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
3012{
3013  bool result = false;
3014
3015  cmt_string here = CmtSystem::pwd ();
3016
3017  cmt_string h1;
3018  if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
3019
3020  CmtSystem::cd (here);
3021
3022  cmt_string h2;
3023  if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
3024
3025  result = (h1 == h2);
3026
3027  CmtSystem::cd (here);
3028
3029  return (result);
3030}
3031
3032//----------------------------------------------------------
3033static bool install_library (const cmt_string& source_library_name, 
3034                             const cmt_string& dest_library_name, 
3035                             const cmt_string& cmtinstallarea, 
3036                             const cmt_string& tag, 
3037                             const cmt_string& symlinkcmd)
3038{
3039  cmt_string libname = source_library_name;
3040  cmt_string name = dest_library_name;
3041  cmt_string s;
3042  Use& current_use = Use::current ();
3043
3044  Symbol::expand (name);
3045  Symbol::expand (libname);
3046
3047  if (cmtinstallarea != "")
3048    {
3049      s = cmtinstallarea;
3050      s += CmtSystem::file_separator ();
3051      s += tag;
3052      s += CmtSystem::file_separator ();
3053      s += "lib";
3054      s += CmtSystem::file_separator ();
3055      s += name;
3056     
3057      // Now creating the reference file
3058
3059      cmt_string ref_file = s;
3060      ref_file += ".cmtref";
3061
3062      cmt_string text = libname;
3063      text += "\n";
3064
3065      Symbol::expand (ref_file);
3066      Symbol::expand (text);
3067
3068      if (!Cmt::get_quiet ()) cout << "   Creating the reference file " << ref_file << endl;
3069      text.write (ref_file);
3070    }
3071  else
3072    {
3073      s = "../$(";
3074      s += current_use.get_package_name ();
3075      s += "_tag)/";
3076      s += name;
3077    }
3078
3079  Symbol::expand (s);
3080
3081  cmt_string source;
3082  cmt_string dest;
3083
3084  CmtSystem::dirname (libname, source);
3085  CmtSystem::dirname (s, dest);
3086
3087  if (same_dirs (source, dest))
3088    {
3089      return (false);
3090    }
3091
3092  //if (!Cmt::get_quiet ())
3093  cout << "   Symlinking " << libname << " to " << s << endl;
3094
3095  if (symlinkcmd == "")
3096    {
3097      if (!CmtSystem::create_symlink (libname, s))
3098        {
3099          cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3100          return (false);
3101        }
3102    }
3103  else
3104    {
3105      cmt_string cmd = symlinkcmd;
3106      cmd += " ";
3107      cmd += libname;
3108      cmd += " ";
3109      cmd += s;
3110     
3111      int status = CmtSystem::execute (cmd);
3112     
3113      if (status != 0)
3114        {
3115          cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3116          return (false);
3117        }
3118    }
3119
3120  return (true);
3121}
3122
3123
3124/**
3125   Centralize the construction of library links for this Use.
3126*/
3127void Use::build_library_links (const cmt_string& cmtinstallarea, 
3128                               const cmt_string& tag, 
3129                               const cmt_string& shlibsuffix, 
3130                               const cmt_string& symlinkcmd) const
3131{
3132  if (!located ())
3133    {
3134      if (!Cmt::get_quiet ())
3135        {
3136          cout << "# package " << get_package_name () <<
3137            " " << version << " " << path << 
3138            " not found" <<
3139            endl;
3140        }
3141      return;
3142    }
3143
3144  cmt_string s;
3145
3146  s = get_package_name ();
3147  s += "_libraries";
3148
3149  Symbol* libraries_macro = Symbol::find (s);
3150
3151  if (libraries_macro == 0) return;
3152
3153  cmt_string libraries = libraries_macro->build_macro_value ();
3154  Symbol::expand (libraries);
3155  static CmtSystem::cmt_string_vector values;
3156
3157  CmtSystem::split (libraries, " \t", values);
3158
3159  for (int j = 0; j < values.size (); j++)
3160    {
3161      const cmt_string& library = values[j];
3162
3163      static cmt_string libname;
3164      static cmt_string name;
3165
3166      // Is it a simple name or a complete path?
3167
3168      libname = library;
3169      Symbol::expand (libname);
3170
3171      bool is_absolute = false;
3172
3173      is_absolute = CmtSystem::absolute_path (libname);
3174
3175      if (is_absolute)
3176        {
3177          /**
3178           *   We assume here that "library" contains a complete path.
3179           *   (including the complete syntax libxxx.so)
3180           */
3181
3182          cmt_string suffix;
3183          CmtSystem::basename (library, name);
3184        }
3185      else
3186        {
3187          /**
3188           *   Here we expect that only the base name of the library
3189           *   is given : ie it should not contain the "lib" prefix,
3190           *   nor the suffix .so, nor any path prefix.
3191           *    This of course should generally correspond to a constituent name.
3192           */
3193         
3194          libname = "${";
3195          libname += prefix;
3196          libname += "ROOT}/${";
3197          libname += get_package_name ();
3198          libname += "_tag}/";
3199          libname += "$(library_prefix)";
3200          libname += library;
3201          libname += "$(library_suffix)";
3202          libname += ".";
3203          libname += shlibsuffix;
3204
3205          name = "$(library_prefix)";
3206          name += library;
3207          name += "$(library_suffix)";
3208          name += ".";
3209          name += shlibsuffix;
3210        }
3211
3212      if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3213        {
3214          continue;
3215        }
3216
3217#ifdef __APPLE__
3218      if (!is_absolute)
3219        {
3220          libname = "${";
3221          libname += prefix;
3222          libname += "ROOT}/${";
3223          libname += get_package_name ();
3224          libname += "_tag}/";
3225          libname += library;
3226          libname += ".bundle";
3227
3228          name = library;
3229          name += ".bundle";
3230         
3231          if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3232            {
3233              continue;
3234            }
3235        }
3236#endif
3237    }
3238}
3239
3240/**
3241 *   This function tries to get the replacement of a Use when it has
3242 *  been discarded by a better match to version constraints.
3243 */
3244Use* Use::get_selected_version ()
3245{
3246    //cout << "get_selected_version for package " << get_package_name () << endl;
3247
3248  if (!discarded) return (this);
3249
3250  Package* p = m_package;
3251
3252  Use::UsePtrVector& uses = p->get_uses ();
3253
3254  bool dbg = Cmt::get_debug ();
3255
3256  int size = uses.size ();
3257
3258  for (int i = 0; i < size; i++)
3259    {
3260      Use* u = uses[i];
3261      if (u == 0) continue;
3262      if (u->discarded) continue;
3263      if (dbg)
3264        {
3265          cout << "Use::get_selected_version> for package " << get_package_name ()
3266               << "  got a version " << u << endl;
3267        }
3268      return (u);
3269    }
3270
3271  return (0);
3272}
3273
3274/**
3275   Switching from one use to another one, (better wrt
3276   various criteria).
3277
3278   When switching, m_index and auto_imports are
3279   transfered from the un-selected to the newly selected.
3280 */
3281Use* Use::set_selected_version (Use* selected_use)
3282{
3283  if (this == selected_use) return (this);
3284
3285  static UsePtrVector& uses = get_ordered_uses ();
3286
3287  if (m_index >= 0)
3288    {
3289      // This discarded package was registered. We have to substitute
3290      // it with the new one.
3291
3292      selected_use->m_index = m_index;
3293      selected_use->auto_imports = auto_imports;
3294
3295      selected_use->undiscard ();
3296
3297      m_index = -1;
3298
3299      uses[selected_use->m_index] = selected_use;
3300    }
3301
3302  discard ();
3303
3304  return (selected_use);
3305}
3306
3307void Use::set_auto_imports (State new_state)
3308{
3309  if (Cmt::get_debug ())
3310    {
3311      cout << "Use::set_auto_imports>(" << get_package_name () << ") " 
3312           << auto_imports << " -> " << new_state << endl;
3313    }
3314
3315  if (auto_imports == new_state) return;
3316 
3317  State old_state = auto_imports;
3318 
3319  auto_imports = new_state;
3320
3321    // We propagate only when we switch from Off to On
3322
3323  if ((old_state == Off) && (new_state == On))
3324    {
3325      cmt_string s;
3326      static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
3327
3328      if (Cmt::get_debug ())
3329        {
3330          s = "Use::set_auto_imports>(";
3331          s += get_package_name ();
3332          s += ") ";
3333
3334          cout << s << endl;
3335        }
3336
3337      for (int i = 0; i < sub_uses.size (); i++)
3338        {
3339          Use* u = sub_uses[i];
3340          State state = sub_use_auto_imports[i];
3341         
3342          if (Cmt::get_debug ())
3343            {
3344              s += " ";
3345              s += u->get_package_name ();
3346              s += "(";
3347              s += state_text[state];
3348              s += ")";
3349            }
3350
3351          if (state == Unspecified)
3352            {
3353              u->set_auto_imports (On);
3354            }
3355        }
3356         
3357      if (Cmt::get_debug ())
3358        {
3359          cout << s << endl;
3360        }
3361    }
3362}
3363
3364void Use::set_native_version (bool state)
3365{
3366  m_has_native_version = state;
3367}
3368
3369bool Use::has_native_version () const
3370{
3371  return (m_has_native_version);
3372}
3373
3374Package* Use::get_package () const
3375{
3376  return (m_package);
3377}
3378
3379const cmt_string& Use::get_package_name () const
3380{
3381  static const cmt_string null = "";
3382
3383  Package* p = m_package;
3384  if (p == 0) return (null);
3385
3386  return (p->get_name ());
3387}
3388
3389void Use::set_package_name (const cmt_string& name)
3390{
3391  Package* p = Package::add (name);
3392
3393  m_package = p;
3394  p->add_use (this);
3395}
3396
3397int Use::get_index () const
3398{
3399  return (m_index);
3400}
3401
3402//----------------------------------------------------------
3403bool Use::get_all_clients (const cmt_string& to_name)
3404{
3405  Use::UsePtrVector& uses = Use::get_ordered_uses ();
3406
3407  Use* use = Use::find (to_name);
3408
3409  if (use == 0)
3410    {
3411      cerr << "#CMT> No access to " << to_name << endl;
3412      return (false);
3413    }
3414
3415  cmt_map <cmt_string, Use*> all_clients;
3416  cmt_map <cmt_string, Use*> all_clients_ok;
3417
3418  const cmt_string& name = get_package_name ();
3419
3420  Use* me = this;
3421
3422  all_clients.add (name, me);
3423  all_clients_ok.add (name, me);
3424
3425  bool status = get_all_clients (use, to_name, all_clients, all_clients_ok); 
3426
3427  return (status);
3428}
3429
3430//----------------------------------------------------------
3431bool Use::get_all_clients (Use* to, 
3432                           const cmt_string& result, 
3433                           cmt_map <cmt_string, Use*>& all_clients, 
3434                           cmt_map <cmt_string, Use*>& all_clients_ok)
3435{
3436  if (this == to)
3437    {
3438      cout << result << endl;
3439      return (true);
3440    }
3441
3442  const cmt_string& to_name = to->get_package_name ();
3443  const cmt_string& to_version = to->version;
3444
3445  //cout << "gac> from " << get_package_name () << " to " << to_name << " -> " << result << endl;
3446
3447  if (all_clients.has (to_name))
3448    {
3449      if (all_clients_ok.has (to_name))
3450        {
3451          cout << "   ..." << result << endl;
3452          return (true);
3453        }
3454      else
3455        {
3456          return (false);
3457        }
3458    }
3459
3460  all_clients.add (to_name, to);
3461
3462  bool status = false;
3463
3464  Use::UsePtrVector& uses = Use::get_ordered_uses ();
3465  Use* use = 0;
3466
3467  for (int n = 0; n < uses.size (); ++n)
3468    {
3469      use = uses[n];
3470
3471      if (use->discarded) continue;
3472
3473      if (!use->located ()) continue;
3474
3475      if (use == to) continue;
3476
3477      if (use->is_client (to_name, to_version))
3478        {
3479          const cmt_string& n = use->get_package_name ();
3480
3481          cmt_string r;
3482
3483          if ((use->initial_scope != ScopeUnspecified) &&
3484              (use->initial_scope != ScopePublic)) 
3485            {
3486              r += "(private)";
3487            }
3488         
3489          if (use->auto_imports == Off) r += "(no_auto_imports)";
3490
3491          r += n;
3492          r += ".";
3493          r += result;
3494
3495          //cout << "gac> " << n << " is client of " << to_name << endl;
3496
3497          if (get_all_clients (use, r, all_clients, all_clients_ok))
3498            {
3499              all_clients_ok.add (n, use);
3500              status = true;
3501            }
3502        }
3503    }
3504
3505  use = this;
3506
3507  if (use->is_client (to_name, to_version))
3508    {
3509      const cmt_string& n = use->get_package_name ();
3510     
3511      cmt_string r;
3512
3513      if ((use->initial_scope != ScopeUnspecified) &&
3514          (use->initial_scope != ScopePublic)) 
3515        {
3516          r += "(private)";
3517        }
3518     
3519      if (use->auto_imports == Off) r += "(no_auto_imports)";
3520
3521      r += n;
3522      r += ".";
3523      r += result;
3524     
3525      //cout << "gac> " << n << " is client of " << to_name << endl;
3526     
3527      if (get_all_clients (use, r, all_clients, all_clients_ok))
3528        {
3529          all_clients_ok.add (n, use);
3530          status = true;
3531        }
3532    }
3533
3534  return (status);
3535}
3536
3537/**
3538   Let's consider two packages in the use graph "this" and "to"
3539   This function finds all packages that are reached in between
3540   following all possible paths between "this" and "to"
3541
3542   Result s accumulated into "list"
3543 */
3544bool Use::get_paths (Use* to, UsePtrVector& list)
3545{
3546  bool is_in_path = false;
3547  bool cycle = false;
3548  bool already_in_path = false;
3549  bool dbg = Cmt::get_debug ();
3550
3551  static int level = 0;
3552
3553  int size = 0;
3554
3555  if (level == 0)
3556    {
3557      unselect_all ();
3558      selected = false;
3559    }
3560
3561  if (selected) 
3562    {
3563      /**
3564         If this use is already in the list, we don't duplicate the entry.
3565         (protection duplicate paths in the graph)
3566      */
3567
3568      size = list.size ();
3569
3570      for (int m = 0; m < size; m++)
3571        {
3572          Use* u = list[m];
3573          if (u == this)
3574            {
3575              if (dbg)
3576                {
3577                  for (int lll = 0; lll < level; lll++) cout << "  ";
3578                  cout << "  Use::get_paths." << level << "> try1.2 sub="
3579                       << get_package_name () << " already_in_path " << endl;
3580                }
3581             
3582              return (true);
3583            }
3584        }
3585
3586      return (false);
3587    }
3588
3589  selected = true;
3590
3591  if (dbg)
3592    {
3593      for (int lll = 0; lll < level; lll++) cout << "  ";
3594      cout << "Use::get_paths." << level << ">" << get_package_name ()
3595           << " to=" << to->get_package_name () 
3596           << " list=[";
3597
3598      for (int m = 0; m < list.size (); m++)
3599        {
3600          Use* u = list[m];
3601          cout << u->get_package_name () << " ";
3602        }
3603
3604      cout << "]" << endl;
3605    }
3606
3607  /**
3608     Now "this" is a candidate new entry in the list
3609   */
3610
3611  // First figure out whether 'to' is used by 'this'.
3612
3613  if (this->get_package_name () == to->get_package_name ())
3614    {
3615      // We've reached the goal (for the first time)
3616      is_in_path = true;
3617    }
3618  else
3619    {
3620      /**
3621         Let's scan sub_uses now
3622       */
3623      size = sub_uses.size ();
3624
3625      if (dbg)
3626        {
3627          for (int lll = 0; lll < level; lll++) cout << "  ";
3628          cout << "  Use::get_paths." << level << "> size=" << size << endl;
3629        }
3630
3631      for (int n = 0; n < size; n++)
3632        {
3633          Use* use = sub_uses[n];
3634
3635          if (use == 0) continue;
3636
3637          if (dbg)
3638            {
3639              for (int lll = 0; lll < level; lll++) cout << "  ";
3640              cout << "  Use::get_paths." << level << "> try1 sub="
3641                   << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
3642            }
3643
3644          if (use->discarded)
3645            {
3646              Use* u;
3647
3648              u = use->get_selected_version ();
3649              if (u == 0) 
3650                {
3651                  /**
3652                     No way to find a valid use for this used package.
3653                     Is that a bug?
3654                     Anyway we don't pursue on that branch.
3655                   */
3656                  continue;
3657                }
3658
3659              use = u;
3660            }
3661
3662          if (dbg)
3663            {
3664              for (int lll = 0; lll < level; lll++) cout << "  ";
3665              cout << "  Use::get_paths." << level << "> try2 sub="
3666                   << use->get_package_name () << " " << use->discarded << endl;
3667            }
3668
3669          level++;
3670          bool r = use->get_paths (to, list);
3671          level--;
3672
3673          if (r)
3674            {
3675              is_in_path = true;
3676            }
3677        }
3678    }
3679
3680  if (is_in_path)
3681    {
3682      if (dbg)
3683        {
3684          for (int lll = 0; lll < level; lll++) cout << "  ";
3685          cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
3686        }
3687      list.push_back (this);
3688    }
3689
3690  return (is_in_path);
3691}
3692
3693//----------------------------------------------------------
3694bool Use::located () const
3695{
3696  return (m_located);
3697}
3698
3699//----------------------------------------------------------
3700void Use::show_sub_uses (const cmt_string& request, bool skip_discarded)
3701{
3702  Use* current = &(Use::current ());
3703  int n;
3704  Use* use;
3705  static int level = 0;
3706
3707  if (skip_discarded && discarded) return;
3708
3709  if (level > 0)
3710    {
3711      cout << "# ";
3712      for (n = 0; n < (level-1); n++) cout << "  ";
3713
3714      if (request == "")
3715        {
3716          cout << "use " << get_package_name () << " " << specified_version;
3717
3718          if (this == current) 
3719            {
3720              cout << " (current)";
3721            }
3722          else
3723            {
3724              if (specified_path != "") cout << " " << specified_path;
3725            }
3726        }
3727      else
3728        {
3729          cout << "use " << request;
3730        }
3731
3732      if (version_alias != "")
3733        {
3734          cout << " | " << version_alias << " " << path_alias;
3735        }
3736
3737      if (initial_scope == ScopeUnspecified) cout << " (unspecified)";
3738      else if (initial_scope != ScopePublic) cout << " (private)";
3739
3740      if (auto_imports == Off) cout << " (no_auto_imports)";
3741
3742      if (style == no_version_style) cout << " (no_version_directory)";
3743
3744      if (m_has_native_version)
3745        {
3746          cmt_string n = get_package_name ();
3747          n += "_native_version";
3748
3749          Symbol* s = Symbol::find (n);
3750          if (s != 0)
3751            {
3752              cmt_string value = s->resolve_macro_value ();
3753              cout << " (native_version=" << value << ")";
3754            }
3755        }
3756
3757      cout << endl;
3758    }
3759
3760  if (selected) return;
3761  selected = true;
3762
3763  level++;
3764  for (n = 0; n < sub_uses.size (); n++)
3765    {
3766      use = sub_uses[n];
3767      if (use == 0) continue;
3768
3769      const cmt_string& request = requests[n];
3770
3771      ScopeType saved_scope = use->initial_scope;
3772      State saved_state = use->auto_imports;
3773
3774      use->initial_scope = sub_use_scopes[n];
3775      use->auto_imports = sub_use_auto_imports[n];
3776
3777      use->show_sub_uses (request, skip_discarded);
3778
3779      use->initial_scope = saved_scope;
3780      use->auto_imports = saved_state;
3781    }
3782  level--;
3783}
3784
3785//----------------------------------------------------------
3786Use& Use::current ()
3787{
3788  static UseVector& instances = get_instances ();
3789  static Use* current_use = 0;
3790
3791  if ((current_use == 0) || (instances.size () == 0))
3792    {
3793      Use& use_object = instances.add ();
3794      current_use = &use_object;
3795    }
3796
3797  return (*current_use);
3798}
3799
3800//----------------------------------------------------------
3801const Use& Use::const_current ()
3802{
3803  const Use& use = Use::current ();
3804
3805  return (use);
3806}
3807
3808//----------------------------------------------------------
3809Use::UseVector& Use::get_instances ()
3810{
3811  static Database& db = Database::instance ();
3812  static UseVector& instances = db.all_uses ();
3813
3814  return (instances);
3815}
3816
3817//----------------------------------------------------------
3818Use::UsePtrVector& Use::get_ordered_uses ()
3819{
3820  static Database& db = Database::instance ();
3821  static UsePtrVector& uses = db.uses ();
3822
3823  return (uses);
3824}
3825
3826//----------------------------------------------------------
3827
3828//----------------------------------------------------------
3829//
3830//  Check if the specified version is better than the
3831//  current one.
3832//
3833//----------------------------------------------------------
3834Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
3835{
3836  Use* selected = ref_use;
3837
3838  int ref_v = -1;
3839  int ref_r = -1;
3840  int ref_p = -1;
3841  cmt_string ref_pp;
3842
3843  int new_v = -1;
3844  int new_r = -1;
3845  int new_p = -1;
3846  cmt_string new_pp;
3847
3848  int alias_v = -1;
3849  int alias_r = -1;
3850  int alias_p = -1;
3851  cmt_string alias_pp;
3852
3853  enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
3854
3855  // First analyze specified versions
3856  cmt_string ref_version = ref_use->specified_version;
3857  cmt_string new_version = new_use->specified_version;
3858
3859  CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
3860  ref_pp = ref_use->path;
3861
3862  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
3863  new_pp = new_use->path;
3864
3865  if (new_use->version_alias != "")
3866    {
3867      has_alias = new_has_alias;
3868      CmtSystem::is_version_directory (new_use->version_alias, 
3869                                       alias_v, alias_r, alias_p);
3870      alias_pp = new_use->path_alias;
3871    }
3872  else if (ref_use->version_alias != "")
3873    {
3874      has_alias = ref_has_alias;
3875      CmtSystem::is_version_directory (ref_use->version_alias, 
3876                                       alias_v, alias_r, alias_p);
3877      alias_pp = ref_use->path_alias;
3878    }
3879
3880  ref_use->undiscard ();
3881  new_use->undiscard ();
3882
3883  if (new_v != ref_v)
3884    {
3885      if (has_alias != no_alias)
3886        {
3887          if (has_alias == new_has_alias)
3888            {
3889              new_v = alias_v;
3890              new_r = alias_r;
3891              new_p = alias_p;
3892              new_pp = alias_pp;
3893            }
3894          else if (has_alias == ref_has_alias)
3895            {
3896              ref_v = alias_v;
3897              ref_r = alias_r;
3898              ref_p = alias_p;
3899              ref_pp = alias_pp;
3900            }
3901        }
3902    }
3903
3904  bool ref_v_wildcarded = ((ref_v) == -1);
3905  bool ref_r_wildcarded = ((ref_r) == -1);
3906  bool ref_p_wildcarded = ((ref_p) == -1);
3907
3908  bool ref_v_explicit = !ref_v_wildcarded;
3909  bool ref_r_explicit = !ref_r_wildcarded;
3910  bool ref_p_explicit = !ref_p_wildcarded;
3911
3912  bool new_v_wildcarded = ((new_v) == -1);
3913  bool new_r_wildcarded = ((new_r) == -1);
3914  bool new_p_wildcarded = ((new_p) == -1);
3915
3916  bool new_v_explicit = !new_v_wildcarded;
3917  bool new_r_explicit = !new_r_wildcarded;
3918  bool new_p_explicit = !new_p_wildcarded;
3919
3920  bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
3921
3922  cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
3923  cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
3924  cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
3925 
3926  cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
3927  cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
3928  cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
3929
3930  // Now compute effective version identifiers
3931  CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
3932  CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
3933
3934  cmt_string new_selected_version = new_use->version;
3935
3936  if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
3937    {
3938      /*
3939      if (verbose && !Cmt::get_quiet ())
3940        {
3941          cerr << "# Required explicit version " << new_version
3942               << " of package " << ref_use->get_package_name ()
3943               << " incompatible with selected explicit version " << ref_version
3944               << endl;
3945        }
3946
3947      CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
3948
3949      if (ref_use != new_use) new_use->discard ();
3950      */
3951
3952      if (new_v > ref_v)
3953        {
3954          if (verbose && !Cmt::get_quiet ())
3955            {
3956              cerr << "# Select " << new_vc << " version " << new_version
3957                   << " of package " << ref_use->get_package_name () 
3958                   << " instead of existing " << ref_vc << " " << ref_version
3959                   << endl;
3960            } 
3961         
3962          if (ref_use != new_use) ref_use->discard ();
3963          selected = new_use;
3964          selected->done = false; // Will read the new requirements
3965        }
3966    }
3967  else if (new_v_wildcarded || ref_v_wildcarded)
3968    {
3969      // at least one of ref or new is wildcarded
3970
3971      //
3972      // we plan to discard new_use, but if it was specified as explicit
3973      // and ref_use was wildcarded then new_use will win !!
3974      //
3975      // So then we'll have to understand where are the wild
3976      // cards... If they are on v or r, then we consider them.
3977      //
3978      //
3979
3980      if (ref_v_wildcarded && new_v_explicit)
3981        {
3982          if ((ref_use->real_path != new_use->real_path) ||
3983              (ref_use->version != new_use->version))
3984            {
3985              if (ref_use != new_use) ref_use->discard ();
3986              selected = new_use;
3987              selected->done = false; // Will read the new requirements
3988
3989              if (verbose && !Cmt::get_quiet ())
3990                {
3991                  cerr << "# Select explicit version " << new_version
3992                       << "(" << new_use->version << ")" 
3993                       << " of package " << ref_use->get_package_name () 
3994                       << " instead of existing wildcarded " << ref_version
3995                       << "(" << ref_use->version << ")" 
3996                       << endl;
3997                }
3998            }
3999          else
4000            {
4001              if (ref_use != new_use) new_use->discard ();
4002              //ref_use->version = new_selected_version;
4003            }
4004        }
4005      else
4006        {
4007          // ref is explicit or new is wildcarded
4008
4009          /*
4010          if (verbose && !Cmt::get_quiet ())
4011            {
4012              cerr << "# keep " << ref_vc << " version " << ref_version
4013                   << " of package " << ref_use->get_package_name ()
4014                   << " (ignore " << new_vc << " version " << new_version << ")"
4015                   << endl;
4016            }
4017          */
4018
4019          if (ref_use != new_use) new_use->discard ();
4020        }
4021    }
4022  else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
4023    {
4024      //
4025      // we plan to discard new_use, but if it was specified as explicit
4026      // and ref_use was wildcarded then new_use will win !!
4027      //
4028      // So then we'll have to understand where are the wild
4029      // cards... If they are on v or r, then we consider them.
4030      //
4031      //
4032
4033      if (ref_r_wildcarded && new_r_explicit)
4034        {
4035          // ref has wild card and new has not => new wins
4036
4037          if ((ref_use->real_path != new_use->real_path) ||
4038              (ref_use->version != new_use->version))
4039            {
4040              if (ref_use != new_use) ref_use->discard ();
4041              selected = new_use;
4042              selected->done = false; // Will read the new requirements
4043
4044              if (verbose && !Cmt::get_quiet ())
4045                {
4046                  cerr << "# Select explicit release " << new_version
4047                       << " of package " << ref_use->get_package_name ()
4048                       << " instead of existing wildcarded " << ref_version
4049                       << endl;
4050                } 
4051            }
4052          else
4053            {
4054              // Just adapt version with new one.
4055
4056              if (ref_use != new_use) new_use->discard ();
4057              //ref_use->version = new_selected_version;
4058            }
4059        }
4060      else
4061        {
4062          /*
4063          if (verbose &&!Cmt::get_quiet ())
4064            {
4065              cerr << "# keep " << ref_rc << " release " << ref_version
4066                   << " of package " << ref_use->get_package_name ()
4067                   << " (ignore " << new_rc << " release " << new_version << ")"
4068                   << endl;
4069            }
4070          */
4071
4072          if (ref_use != new_use) new_use->discard ();
4073        }
4074    }
4075  else if (new_r > ref_r)
4076    {
4077      if (verbose && !Cmt::get_quiet ())
4078        {
4079          cerr << "# Select " << new_rc << " release " << new_version
4080               << " of package " << ref_use->get_package_name () 
4081               << " instead of existing " << ref_rc << " " << ref_version
4082               << endl;
4083        } 
4084
4085      if (ref_use != new_use) ref_use->discard ();
4086      selected = new_use;
4087      selected->done = false; // Will read the new requirements
4088    }
4089  else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
4090    {
4091      //
4092      // we plan to discard new_use, but if it was specified as explicit
4093      // and ref_use was wildcarded then new_use will win !!
4094      //
4095
4096      if (ref_p_wildcarded && new_p_explicit)
4097        {
4098          if ((ref_use->real_path != new_use->real_path) ||
4099              (ref_use->version != new_use->version))
4100            {
4101              if (ref_use != new_use) ref_use->discard ();
4102              selected = new_use;
4103              selected->done = false; // Will read the new requirements
4104
4105              if (verbose && !Cmt::get_quiet ())
4106                {
4107                  cerr << "# Select explicit patch " << new_version
4108                       << " of package " << ref_use->get_package_name () 
4109                       << " instead of existing wildcarded " << ref_version
4110                       << endl;
4111                }
4112            }
4113          else
4114            {
4115              if (ref_use != new_use) new_use->discard ();
4116              ref_use->version = new_selected_version;
4117            }
4118        }
4119      else
4120        {
4121          /*
4122          if (verbose && !Cmt::get_quiet ())
4123            {
4124              cerr << "# keep " << ref_pc << " patch " << ref_version
4125                   << " [" << ref_use->specified_version << "]"
4126                   << " of package " << ref_use->get_package_name ()
4127                   << " (ignore " << new_pc << " version " << new_version << ")"
4128                   << " [" << new_use->specified_version << "]"
4129                   << endl;
4130            }
4131          */
4132
4133          if (ref_use != new_use) new_use->discard ();
4134        }
4135    }
4136  else if (new_p > ref_p)
4137    {
4138      if (verbose && !Cmt::get_quiet ())
4139        {
4140          cerr << "# Select " << new_pc << " patch " << new_version
4141               << " of package " << ref_use->get_package_name () 
4142               << " instead of existing " << ref_pc << " " << ref_version
4143               << endl;
4144        }
4145
4146      if (ref_use != new_use) ref_use->discard ();
4147      selected = new_use;
4148      selected->done = false; // Will read the new requirements
4149    }
4150  else if (new_pp != ref_pp) // same version-r-p but from different path
4151    {
4152      if (ref_use != new_use) ref_use->discard ();
4153      selected = new_use;
4154      selected->done = false; // Will read the new requirements
4155    }
4156
4157  return (selected);
4158}
4159
4160
4161
4162
4163
4164
4165Package* Package::find (const cmt_string& name)
4166{
4167  static PackageMap& PackageMap = package_map ();
4168
4169  Package* result = 0;
4170
4171  result = PackageMap.find (name);
4172
4173  return (result);
4174}
4175
4176Package* Package::add (const cmt_string& name)
4177{
4178  static PackageVector& Packages = packages ();
4179  static PackageMap& PackageMap = package_map ();
4180
4181  {
4182    Package* package;
4183
4184    package = find (name);
4185    if (package != 0) return (package);
4186  }
4187
4188  Package& package = Packages.add ();
4189  PackageMap.add (name, package);
4190
4191  package.m_name = name;
4192
4193  if (name == "CMT")
4194    {
4195      package.m_is_cmt = true;
4196    }
4197  else if (name == "methods")
4198    {
4199      package.m_is_cmt = true;
4200    }
4201
4202  if (Cmt::get_debug ())
4203    {
4204      cout << "Package::add (" << name << ")" << endl;
4205    }
4206
4207  return (&package);
4208}
4209
4210Package::PackageVector& Package::packages ()
4211{
4212  static Database& db = Database::instance ();
4213  static PackageVector& Packages = db.packages ();
4214
4215  return (Packages);
4216}
4217
4218Package::PackageMap& Package::package_map ()
4219{
4220  static Database& db = Database::instance ();
4221  static PackageMap& PackageMap = db.package_map ();
4222
4223  return (PackageMap);
4224}
4225
4226void Package::clear_all ()
4227{
4228  static PackageVector& Packages = packages ();
4229  static PackageMap& PackageMap = package_map ();
4230
4231  PackageMap.clear ();
4232  Packages.clear ();
4233}
4234
4235Package::Package () : m_is_cmt (false)
4236{
4237  if (Cmt::get_debug ())
4238    {
4239      cout << "Package::Package" << endl;
4240    }
4241}
4242
4243Package::~Package ()
4244{
4245  m_name = "";
4246}
4247
4248const cmt_string& Package::get_name () const
4249{
4250  return (m_name);
4251}
4252
4253void Package::add_use (Use* use)
4254{
4255  for (int i = 0; i < m_uses.size (); i++)
4256    {
4257      Use* u = m_uses[i];
4258      if (u == use) return;
4259    }
4260
4261  m_uses.push_back (use);
4262}
4263
4264void Package::remove_use (Use* use)
4265{
4266  if (Cmt::get_debug ())
4267    {
4268      cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
4269      cout << "  name=" << m_name
4270           << " uses=" << m_uses.size () << endl;
4271    }
4272
4273  Use::UsePtrVector temp;
4274
4275  temp = m_uses;
4276
4277  m_uses.clear ();
4278
4279  for (int i = 0; i < temp.size (); i++)
4280    {
4281      Use* u = temp[i];
4282      if (u != use)
4283        {
4284          m_uses.push_back (u);
4285        }
4286    }
4287}
4288
4289Use::UsePtrVector& Package::get_uses ()
4290{
4291  return (m_uses);
4292}
4293
4294bool Package::is_cmt ()
4295{
4296  return (m_is_cmt);
4297}
4298
4299static void show_packages ()
4300{
4301  Package::PackageVector& vector = Package::packages ();
4302
4303  int i;
4304  int j;
4305
4306  cout << "### Packages: ";
4307  for (i = 0; i < vector.size (); i++)
4308    {
4309      Package& p = vector[i];
4310      cout << p.get_name () << "[";
4311      Use::UsePtrVector& uses = p.get_uses ();
4312      for (j = 0; j < uses.size (); j++)
4313        {
4314          Use* u = uses[j];
4315          cout << u << ",";
4316        }
4317
4318      cout << "] ";
4319    }
4320  cout << endl;
4321
4322  {
4323    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
4324
4325    cout << "### Uses: ";
4326    for (i = 0; i < uses.size (); i++)
4327      {
4328        Use* u = uses[i];
4329        cout << "[" << u << "]" << u->get_package_name () << " ";
4330      }
4331  }
4332
4333  cout << endl;
4334}
4335
Note: See TracBrowser for help on using the repository browser.