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