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