source: CMT/v1r20p20070208/source/cmt_use.cxx

Last change on this file was 344, checked in by garonne, 17 years ago

remove no-auto-imports treatment

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