source: CMT/v1r18p20041201/source/cmt_use.cxx @ 1

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

Import all tags

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