source: CMT/v1r20p20080222/source/cmt_use.cxx @ 615

Last change on this file since 615 was 437, checked in by rybkin, 16 years ago

See C.L. 342

  • Property svn:eol-style set to native
File size: 99.3 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        cerr << "#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            cerr << "#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            cerr << "#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            cerr << "#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            cerr << "#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        cerr << "#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            cerr << "#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            cerr << "#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        cerr << "#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
1621                      nv.read (path);
1622                      int pos = nv.find ('\n');
1623                      if (pos != cmt_string::npos) nv.erase (pos);
1624
1625                      pos = nv.find ('\r');
1626                      if (pos != cmt_string::npos) nv.erase (pos);
1627
1628                      if (nv == n_version)
1629                        {
1630                          cmt_string& name_entry = native_versions.add ();
1631
1632                          // We have found at least one
1633                          // cout << "native_version :" << n_version << " ,version: " << versions[i] << endl;
1634                          this->native_version   = n_version;
1635                          name_entry            += versions[i];
1636                        }
1637                    }                   
1638                }
1639              versions = native_versions;
1640            }
1641         
1642          int i;
1643          bool found = false;
1644         
1645          for (i = 0; i < versions.size (); i++)
1646            {
1647              const cmt_string& vers = versions[i];
1648             
1649              if (Cmt::get_debug ())
1650                {
1651                  cout << "     ... version " << vers << " exists" << endl;
1652                }
1653
1654              CmtSystem::basename (vers, name);
1655             
1656              int v;
1657              int r;
1658              int p;
1659             
1660              if (CmtSystem::is_version_directory (name, v, r, p))
1661                {
1662                  /*
1663                    This check is not sufficient !! We need to check in addition
1664                    that the selected directory is really the start of a true CMT
1665                    package (ie with either /mgr/requirements or /cmt/requirements below)
1666                  */
1667
1668                  cmt_string req;
1669
1670                  req = name;
1671                  req += CmtSystem::file_separator ();
1672                  req += "mgr";
1673                  req += CmtSystem::file_separator ();
1674                  req += "requirements";
1675
1676                  if (!CmtSystem::test_file (req))
1677                    {
1678                      req = name;
1679                      req += CmtSystem::file_separator ();
1680                      req += "cmt";
1681                      req += CmtSystem::file_separator ();
1682                      req += "requirements";
1683
1684                      if (!CmtSystem::test_file (req)) continue;
1685                    }
1686
1687                  cmt_string& new_v = alternate_versions.add ();
1688                  new_v = name;
1689                  cmt_string& new_p = alternate_paths.add ();
1690                  new_p = from_path;
1691
1692                  found = true;
1693                }
1694            }
1695
1696          if (!found)
1697            {
1698              if (CmtSystem::test_file ("cmt/requirements"))
1699                {
1700                  CmtSystem::cd ("cmt");
1701                  style = no_version_style;
1702                  return (1);
1703                }
1704            }
1705        }
1706
1707      if (Cmt::get_debug ())
1708        {
1709          cout << "  ... end of version scan" << endl;
1710        }
1711
1712      //
1713      //  We have now the list of possible alternate versions. However
1714      // we return that the expected package/version was not found (yet).
1715      //
1716
1717      return (0);
1718    }
1719
1720  if (Cmt::get_debug ())
1721    {
1722      cout << "Use::reach_package-7>" << endl;
1723    }
1724
1725  //cerr << "  ... version " << version << " exists" << endl;
1726
1727  // Now we have met the exact specified version!
1728  if (!CmtSystem::test_file ("cmt/requirements"))
1729    {
1730      if (!CmtSystem::test_file ("mgr/requirements"))
1731        {
1732          return (0);
1733        }
1734      else
1735        {
1736          CmtSystem::cd ("mgr");
1737          style = mgr_style;
1738        }
1739    }
1740  else
1741    {
1742      CmtSystem::cd ("cmt");
1743      style = cmt_style;
1744    }
1745
1746  if (Cmt::get_debug ())
1747    {
1748      cout << "Use::reach_package-8>" << endl;
1749    }
1750
1751  return (1);
1752}
1753
1754class UseProjectAction : public IProjectAction
1755{
1756public:
1757  UseProjectAction (Use* use, cmt_string n_version="") : m_use (use), m_found (false), native_version(n_version)
1758  {
1759  }
1760
1761  bool found () const
1762  {
1763    return (m_found);
1764  }
1765
1766  bool run (const Project& project)
1767  {
1768    const cmt_string& path = project.get_cmtpath ();
1769     
1770    m_use->alternate_versions.clear ();
1771    m_use->alternate_paths.clear ();
1772
1773    if (m_use->reach_package (path, this->native_version))
1774      {
1775        if (Cmt::get_debug ())
1776          {
1777            cout << "move_to4> " << path << endl;
1778          }
1779       
1780        m_use->change_path (path);
1781
1782        m_found = true;
1783
1784        return (false);
1785      }
1786    else if (m_use->alternate_versions.size () > 0)
1787      {
1788        if (m_use->select_alternate ()) 
1789          {
1790            if (Cmt::get_debug ())
1791              {
1792                cout << "move_to5> " << m_use->real_path << endl;
1793              }
1794
1795            m_found = true;
1796
1797            return (false);
1798          }
1799      }
1800   
1801    return (true);
1802  }
1803
1804private:
1805  Use* m_use;
1806  bool m_found;
1807  cmt_string native_version;
1808};
1809
1810//----------------------------------------------------------
1811bool Use::move_to (const cmt_string& native_version)
1812{
1813  if (m_located)
1814    {
1815      //
1816      // The real path where this version/package can be found
1817      // has already been resolved. We thus first go there.
1818      //
1819
1820      if (Cmt::get_debug ())
1821        {
1822          cout << "move_to1> " << real_path << endl;
1823        }
1824
1825      reach_package (real_path, native_version);
1826
1827      return (true);
1828    }
1829
1830  cmt_string expanded_path = path;
1831
1832  //
1833  // Try here.
1834  //
1835  if (expanded_path == "")
1836    {
1837      if (reach_package ("", native_version))
1838        {
1839          if (Cmt::get_debug ())
1840            {
1841              cout << "move_to2> " << expanded_path << endl;
1842            }
1843
1844          change_path (expanded_path);
1845
1846          return (true);
1847        }
1848      else if (alternate_versions.size () > 0)
1849        {
1850          if (select_alternate ()) 
1851            {
1852              if (Cmt::get_debug ())
1853                {
1854                  cout << "move_to5> " << real_path << endl;
1855                }
1856             
1857              return (true);
1858            }
1859        }
1860    }
1861     
1862  //
1863  // If the path specified in this use is a true absolute path,
1864  // then we search the package from there first.
1865  //
1866  if (CmtSystem::absolute_path (expanded_path))
1867    {
1868      if (reach_package (expanded_path,  native_version))
1869        {
1870          if (Cmt::get_debug ())
1871            {
1872              cout << "move_to3> " << expanded_path << endl;
1873            }
1874
1875          change_path (expanded_path);
1876
1877          return (true);
1878        }
1879      else if (alternate_versions.size () > 0)
1880        {
1881          if (select_alternate ()) 
1882            {
1883              if (Cmt::get_debug ())
1884                {
1885                  cout << "move_to5> " << real_path << endl;
1886                }             
1887
1888              return (true);
1889            }
1890        }
1891    }
1892     
1893  //
1894  // Second try is among the CMTPATHs
1895  //
1896  UseProjectAction pa (this, native_version);
1897
1898  Project::broadcast (pa);
1899
1900  if (pa.found ()) return (true);
1901
1902  return (false);
1903}
1904
1905//----------------------------------------------------------
1906bool Use::select_alternate ()
1907{
1908  int i;
1909
1910  int v0 = 0;
1911  int r0 = 0;
1912  int p0 = 0;
1913
1914  int v = 0;
1915  int r = 0;
1916  int p = 0;
1917
1918  int selected_index = -1;
1919
1920  for (i = 0; i < alternate_versions.size (); i++)
1921    {
1922      cmt_string& name = alternate_versions[i];
1923
1924      if (i == 0)
1925        {
1926          CmtSystem::is_version_directory (name, v0, r0, p0);
1927          selected_index = 0;
1928        }
1929      else
1930        {
1931          CmtSystem::is_version_directory (name, v, r, p);
1932
1933          if (v > v0)
1934            {
1935              selected_index = i;
1936              v0 = v;
1937              r0 = r;
1938              p0 = p;
1939            }
1940          else if (v == v0)
1941            {
1942              if (r > r0)
1943                {
1944                  selected_index = i;
1945                  r0 = r;
1946                  p0 = p;
1947                }
1948              else if (r == r0)
1949                {
1950                  if (p > p0)
1951                    {
1952                      selected_index = i;
1953                      p0 = p;
1954                    }
1955                }
1956            }
1957        }
1958    }
1959
1960  if (selected_index >= 0)
1961    {
1962      if (CmtSystem::cd (alternate_paths[selected_index]))
1963        {
1964          version = alternate_versions[selected_index];
1965          if (reach_package (alternate_paths[selected_index]))
1966            {
1967              if (Cmt::get_debug ())
1968                {
1969                  cout << "select_alternate> " << alternate_paths[selected_index] << endl;
1970                }
1971
1972              change_path (alternate_paths[selected_index]);
1973              return (true);
1974            }
1975        }
1976    }
1977
1978  return (false);
1979}
1980
1981//----------------------------------------------------------
1982bool Use::need_new (const cmt_string& path,
1983                    const cmt_string& package,
1984                    const cmt_string& version,
1985                    const cmt_string& n_version,
1986                    Use** old_use,
1987                    Use* context_use)
1988{
1989  bool new_request = add_request (path, package, version);
1990   
1991  Use& current_use = Use::current ();
1992
1993  if (package == current_use.get_package_name ())
1994    {
1995      if (Cmt::get_debug ())
1996        {
1997          cout << "  ... recursive use to current package" << endl;
1998        }
1999
2000      if (old_use != 0) *old_use = &current_use;
2001      return (false);
2002    }
2003
2004  Package* p = Package::add (package);
2005
2006  UsePtrVector& uses = p->get_uses ();
2007
2008  bool do_need_new = true;
2009  Use* found = 0;
2010  Use* registered = 0;
2011
2012  int req_v = -1;
2013  int req_r = -1;
2014  int req_p = -1;
2015
2016  CmtSystem::is_version_directory (version, req_v, req_r, req_p);
2017
2018  if (Cmt::get_debug ())
2019    {
2020      cout << "need_new> p=" << package << " v=" << version << " v=" << req_v << " r=" << req_r << " p=" << req_p << endl;
2021    }
2022
2023  bool has_wild_card = (req_v == -1) || (req_r == -1) || (req_p == -1);
2024
2025  int new_v = -1;
2026  int new_r = -1;
2027  int new_p = -1;
2028
2029  int use_index;
2030
2031  if (old_use != 0) *old_use = 0;
2032
2033  // Acquire the registered use.
2034  for (use_index = 0; use_index < uses.size (); use_index++)
2035    {
2036      Use& use = (*uses[use_index]);
2037
2038      if (use.m_index < 0) continue;
2039
2040      registered = &use;
2041
2042      break;
2043    }
2044
2045  // Make a first try with the registered use if it exists.
2046
2047  cmt_string decision;
2048
2049  if (registered != 0)
2050    {
2051      Use& use = (*registered);
2052
2053      found = &use;
2054
2055      CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2056
2057      bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2058
2059      if (has_wild_card && !use_has_wild_card)
2060        {
2061          if (Cmt::get_debug ())
2062            {
2063              cout << "  ... wildcarded request loses against existing explicit" << endl;
2064            }
2065         
2066          do_need_new = false; // We don't need a new one
2067        }
2068      else
2069        {
2070          // here either !has_wild_card or use_has_wild_card
2071
2072          if ((version == use.specified_version) &&
2073              (path == use.specified_path))
2074            {
2075             
2076              if (Cmt::get_debug ())
2077                {
2078                  cout << " ... exactly same version and path!" << endl;
2079                }             
2080              do_need_new = false; // We don't need a new one
2081              if (n_version != use.native_version)
2082                {
2083                  if (Cmt::get_debug ())
2084                    {
2085                      cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl; 
2086                    }
2087
2088                  do_need_new = true;   
2089                }             
2090            }
2091          else if (version != use.specified_version)
2092            {
2093              if (Cmt::get_debug ())
2094                {
2095                  cout << "requested explicit wins against existing wildcarded"
2096                       << endl;
2097                }
2098
2099              // The registered use loses against the request
2100            }
2101          else
2102            {
2103              if (Cmt::get_debug ())
2104                {
2105                  cout << "only paths differ, consider the new one."
2106                       << endl;
2107                }
2108
2109              // The registered use loses against the request
2110            }
2111        }
2112
2113
2114      //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2115      if (new_request && !Cmt::get_quiet ())
2116        {
2117          if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2118            {
2119              cerr << "# Required version " << version
2120                   << " of package " << package;
2121
2122              if (context_use != 0)
2123                {
2124                  cerr << " [from " << context_use->get_package_name () << "]";
2125                }
2126
2127              cerr << " incompatible with selected version " << use.version;
2128
2129              if (use.version != use.specified_version)
2130                {
2131                  cerr << " (" << use.specified_version << ")" ;
2132                }
2133
2134              cerr << endl;
2135            }
2136        }
2137
2138      if (Cmt::get_debug ())
2139        {
2140          cout << "# " << package << " " << version;
2141
2142          if (context_use != 0)
2143            {
2144              cout << " [from " << context_use->get_package_name () << "]";
2145            }
2146
2147          if (do_need_new)
2148            {
2149              cout << " > ";
2150            }
2151          else
2152            {
2153              cout << " < ";
2154            }
2155
2156          cout << use.version;
2157          if (use.version != use.specified_version)
2158            {
2159              cout << " (" << use.specified_version << ")" ;
2160            }
2161
2162          cout << " (r) ";
2163
2164          cout << endl;
2165        }
2166    }
2167
2168  if (do_need_new)
2169    {
2170      // Now try unregistered uses, since the registered one is not appropriate.
2171      // to see is any other existing use could match
2172
2173      for (use_index = 0; use_index < uses.size (); use_index++)
2174        {
2175          Use& use = (*uses[use_index]);
2176         
2177          if (use.m_index >= 0) continue;
2178         
2179          // Always save the latest found.
2180         
2181          found = &use;
2182
2183          CmtSystem::is_version_directory (use.specified_version, new_v, new_r, new_p);
2184
2185          bool use_has_wild_card = (new_v == -1) || (new_r == -1) || (new_p == -1);
2186
2187          if (has_wild_card && !use_has_wild_card)
2188            {
2189              if (Cmt::get_debug ())
2190                {
2191                  cout << "  ... requested wildcarded loses against existing explicit" << endl;
2192                }
2193             
2194              do_need_new = false; // We don't need a new one
2195            }
2196          else
2197            {
2198              // here either !has_wild_card or use_has_wild_card
2199         
2200              if ((version == use.specified_version) &&
2201                  (path == use.specified_path))
2202                {
2203                  if (Cmt::get_debug ())
2204                    {
2205                      cout << " ... exactly same version and path!" << endl;
2206                    }
2207             
2208                  do_need_new = false; // We don't need a new one
2209                  if (n_version != use.native_version)
2210                    {
2211                      if (Cmt::get_debug ())
2212                        {
2213                          cout << " ... but native_version differs (" << n_version << "!=" << use.native_version << ") !" << endl;
2214                        }
2215
2216                      do_need_new = true;   
2217                    }
2218                 
2219                }
2220              else if (version != use.specified_version)
2221                {
2222                  if (Cmt::get_debug ())
2223                    {
2224                      cout << "requested explicit wins against existing wildcarded"
2225                           << endl;
2226                    }
2227
2228                  // This use loses against the request
2229                }
2230              else
2231                {
2232                  if (Cmt::get_debug ())
2233                    {
2234                      cout << "only paths differ, consider the new one."
2235                           << endl;
2236                    }
2237
2238                  // This use loses against the request
2239                }
2240            }
2241
2242          //if (new_request && !Cmt::get_quiet () && (Cmt::get_action () == action_show_uses))
2243          if (new_request && !Cmt::get_quiet ())
2244            {
2245              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2246                {
2247                  cerr << "# Required version " << version
2248                       << " of package " << package;
2249
2250                  if (context_use != 0)
2251                    {
2252                      cerr << " [from " << context_use->get_package_name () << "]";
2253                    }
2254             
2255                  cerr << " incompatible with selected version " << use.version;
2256
2257                  if (use.version != use.specified_version)
2258                    {
2259                      cerr << " (" << use.specified_version << ")" ;
2260                    }
2261
2262                  cerr << endl;
2263                }
2264            }
2265
2266          if (Cmt::get_debug ())
2267            {
2268              cout << "# " << package << " " << version;
2269             
2270              if (context_use != 0)
2271                {
2272                  cout << " [from " << context_use->get_package_name () << "]";
2273                }
2274             
2275              if (do_need_new)
2276                {
2277                  cout << " > ";
2278                }
2279              else
2280                {
2281                  cout << " < ";
2282                }
2283             
2284              if ((new_v != -1) && (req_v != -1) && (new_v != req_v))
2285                {
2286                  cout << "(incompatible) ";
2287                }
2288
2289              cout << use.version;
2290              if (use.version != use.specified_version)
2291                {
2292                  cout << " (" << use.specified_version << ")" ;
2293                }
2294              cout << endl;
2295            }
2296        }
2297    }
2298
2299  if (old_use != 0)
2300    {
2301      if (registered != 0) *old_use = registered;
2302      else *old_use = found;
2303    }
2304
2305  return (do_need_new);
2306}
2307
2308//----------------------------------------------------------
2309//
2310//  Here the version which is provided here is the specified version.
2311// It may contain wild cards or it may be simply empty.
2312//
2313//----------------------------------------------------------
2314Use* Use::create (const cmt_string& path,
2315                  const cmt_string& package,
2316                  const cmt_string& version,
2317                  const cmt_string& version_alias,
2318                  const cmt_string& path_alias,
2319                  const cmt_string& n_version)
2320{
2321  Package* p = 0;
2322
2323  p = Package::add (package);
2324
2325  UsePtrVector& vector = p->get_uses ();
2326
2327  // We first look in the database.
2328  for (int use_index = 0; use_index < vector.size (); use_index++)
2329    {
2330      Use* use = vector[use_index];
2331
2332      if ((use->specified_version == version) && 
2333          (use->specified_path == path) && use->native_version==n_version) return (use);
2334    }
2335
2336  // We now really create a new Use entry.
2337
2338  static UseVector& instances = get_instances ();
2339
2340  Use& use_object = instances.add ();
2341
2342  use_object.set (package, version, path, version_alias, path_alias);
2343
2344  return (&use_object);
2345}
2346
2347//----------------------------------------------------------
2348//  Add a use request into the database.
2349//
2350//  o If a use request already exist in the database,
2351//    check the version compatibility
2352//
2353//----------------------------------------------------------
2354Use* Use::add (const cmt_string& path,
2355               const cmt_string& package_name,
2356               const cmt_string& version,
2357               const cmt_string& version_alias,
2358               const cmt_string& path_alias,
2359               const cmt_string& native_version,
2360               Use* context_use,
2361               State specified_auto_imports)
2362{
2363  bool do_need_new = false;
2364
2365  Use* old_use = 0;
2366  Use* use = 0;
2367
2368  do_need_new = need_new (path, package_name, version, native_version, &old_use, context_use);
2369
2370  if (Cmt::get_debug ())
2371    {
2372      if (old_use != 0 && !do_need_new)
2373        {
2374          cout << "add> old_use " << old_use->get_package_name () <<
2375            " " << old_use->version <<
2376            " " << old_use->path <<
2377            endl;
2378        }
2379    }
2380
2381  if (do_need_new)
2382    {
2383      use = create (path, package_name, version, version_alias, path_alias, native_version);
2384    }
2385  else
2386    {
2387      // Since we don't need a new Use, it means that old_use exists !
2388
2389      use = old_use;
2390      old_use = 0;
2391    }
2392
2393  if (package_name == CmtSystem::get_home_package ())
2394    {
2395      return (use);
2396    }
2397
2398  if (package_name == CmtSystem::get_user_context_package ())
2399    {
2400      return (use);
2401    }
2402
2403  if (package_name == CmtSystem::get_project_package ())
2404    {
2405      return (use);
2406    }
2407
2408  cmt_string here = CmtSystem::pwd ();
2409
2410  //
2411  // Store the specified sub_uses. Some of them may become discarded
2412  // later on.
2413  //
2414  if (context_use != 0)
2415    {
2416      context_use->sub_uses.push_back (use);
2417
2418      context_use->sub_use_scopes.push_back (context_use->get_current_scope ());
2419
2420      context_use->sub_use_auto_imports.push_back (specified_auto_imports);
2421
2422      cmt_string& request = context_use->requests.add ();
2423
2424      request = package_name;
2425      request += " ";
2426      request += version;
2427      request += " ";
2428      request += path;
2429
2430
2431      if (Cmt::get_debug ())
2432        {
2433          cout << "Use::add context(" << context_use->get_package_name () << ") "
2434               << "[u:" << package_name
2435               << " s:" << context_use->get_current_scope ()
2436               << " ai:" << specified_auto_imports
2437               << "]" << endl;
2438        }
2439    }
2440
2441  if (use == &(Use::current ())) 
2442    {
2443      return (use);
2444    }
2445
2446  /*
2447   *   Now we have a Use object. If it is a new one, we have to
2448   *    1) understand if it exists physically
2449   *    2) it is better than the old ones.
2450   *
2451   *   Here, we may have :
2452   *    1) old_use = 0
2453   *         there was no Use object before for this package
2454   *         the existing one is fine
2455   *
2456   *    2) old_use != 0
2457   *         we have created a new Use (which has to be validated)
2458   */
2459  bool found = use->move_to (native_version);
2460
2461  if (Cmt::get_debug ())
2462    {
2463      cout << "add> use [" << use << "] " << use->get_package_name () 
2464           << " " << use->version
2465           << " " << use->path
2466           << " found=" << found
2467           << " done=" << use->done
2468           << endl;
2469
2470      show_packages ();
2471    }
2472     
2473  if (!found)
2474    {
2475      if (!Cmt::get_quiet ())
2476        {
2477          cerr << "#CMT> Warning: package " << use->get_package_name () <<
2478            " " << use->version << " " << use->path << 
2479            " not found";
2480
2481          if (context_use != 0)
2482            {
2483              cerr << " (requested by " << context_use->get_package_name () << ")";
2484            }
2485
2486          cerr << endl;
2487        }
2488
2489      //CmtError::set (CmtError::package_not_found, use->get_package_name ());
2490      use = 0;
2491    }
2492
2493  if ((old_use != 0) && (use != old_use))
2494    {
2495      if (Cmt::get_debug ())
2496        {
2497          cout << "There was another version of this Use. \n"
2498               << "But a new one was created due to some criteria. \n"
2499               << "Now we are going to apply the version strategy to make the final selection"
2500               << endl;
2501        }
2502
2503      /*
2504       *    There was another version of this Use.
2505       *    But a new one was created due to some criteria.
2506       *    Now we are going to apply the version strategy to make the final selection.
2507       */
2508
2509      if (Cmt::get_debug ())
2510        {
2511          cout << "select? [" << use << "] "<< use->version <<" vs old_use[" << old_use << "] "
2512               << old_use->get_package_name ()
2513               << " " << old_use->version
2514               << " " << old_use->path
2515               << endl;
2516        }
2517
2518      if (!found)
2519        {
2520          /*
2521           *  This new Use does not correspond to any physical package.
2522           *  let's simply discard it (and go back to old_use)
2523           */
2524
2525          if (use != 0) use->discard ();
2526          use = old_use;
2527          found = use->move_to (native_version);
2528        }
2529      else
2530        {
2531          //
2532          //  This new version is different from the old one
2533          // thus we have to choose
2534          //
2535          static BestFitSelector selector;
2536          Use* selected_use = selector.operate (old_use, use);
2537
2538          if (Cmt::get_debug ())
2539            {
2540              cout << "after operate old=" << old_use << "(" << old_use->m_index << ")"
2541                   << " use=" << use << "(" << use->m_index << ")"
2542                   << " => selected=" << selected_use
2543                   << endl;
2544            }
2545
2546          //
2547          // Some situations managed by selector.operate happen
2548          // to fail discarding the rejected Use.
2549          //
2550          if (use != selected_use) 
2551            {
2552              use = use->set_selected_version (selected_use);
2553            }
2554         
2555
2556          /*
2557           *   current directory is moved to the selected one
2558           */
2559          found = use->move_to (native_version);
2560        }
2561    }
2562
2563  //
2564  // The following statement is no longer considered as useful.
2565  // It is commented. But we should clarify why it was really needed!
2566  //
2567  //use->undiscard ();
2568
2569  if (found)
2570    {
2571      static UsePtrVector& uses = get_ordered_uses ();
2572
2573      bool registered = false;
2574      const Use& cu = Use::current ();
2575
2576      Package* package = Package::find (package_name);
2577
2578      //
2579      // A pointer to this new object is also added or replaced.
2580      //
2581      if ((use != &cu) && (package == cu.get_package ()))
2582        {
2583          // This is a recursive call to the current package!!
2584          registered = true;
2585          use->done = true;
2586          use->m_index = -1;
2587        }
2588      else
2589        {
2590          //
2591          // Now sort out the registration in ordered uses
2592          //
2593          //  cases:
2594          //
2595          //   use is not yet registered (m_index < 0)
2596          //     o if another use of the same package is registered,
2597          //       it must be substituted with the new one
2598          //     o otherwise create a new entry at the end (it will be sorted
2599          //       afterwards)
2600          //
2601          //   use is already registered (m_index >= 0)
2602          //     o if another use of the same package is registered,
2603          //       it must be discarded, but this may mean that
2604          //       two versions are simultaneously registered (bug?)
2605          //     o otherwise we keep it in place
2606          //
2607
2608          UsePtrVector& puses = package->get_uses ();
2609
2610          if (use->m_index >= 0) registered = true;
2611
2612          /*
2613            We look for all existing uses in that package.
2614          */
2615          for (int i = 0; i < puses.size(); i++)
2616            {
2617              Use* u = puses[i];
2618             
2619              if (Cmt::get_debug ())
2620                {
2621                  cout << "add> check registering between " << use
2622                       << ":" << use->get_package_name ()
2623                       << "(" << use->m_index << ")"
2624                       << " and " << u
2625                       << ":" << u->get_package_name () 
2626                       << "(" << u->m_index << ")"
2627                       << endl;
2628                }
2629
2630              if ((u != use) && (u->m_index >= 0))
2631                {
2632                  // Another use of that package is already registered
2633
2634                  if (Cmt::get_debug ())
2635                    {
2636                      cout << "add> Another use of that package is already registered " 
2637                           << " use(" << use->m_index << ")";
2638                      if (use->m_index >= 0)
2639                        {
2640                          cout << "[" << (uses[use->m_index])->get_package_name () << "]";
2641                        }
2642                      cout << " u(" << u->m_index << ")";
2643                      if (u->m_index >= 0)
2644                        {
2645                          cout << "[" << (uses[u->m_index])->get_package_name () << "]";
2646                        }
2647                      cout << endl;
2648                    }
2649
2650                  if (use->m_index < 0)
2651                    {
2652                      /*
2653                        the newly selected use (use) should replace the one which was registered (u)
2654                      */
2655
2656                      u->set_selected_version (use);
2657
2658                      registered = true;
2659                    }
2660                  else
2661                    {
2662                      // bug??
2663                      if (Cmt::get_debug ())
2664                        {
2665                          cout << "Duplicate entry in ordered uses" << endl;
2666                        }
2667                    }
2668                }
2669            }
2670
2671          if (Cmt::get_debug ())
2672            {
2673              cout << "add> registering completed" << endl;
2674              show_packages ();
2675            }
2676        }
2677     
2678      if (!registered) 
2679        {
2680          if (Cmt::get_debug ())
2681            {
2682              cout << "add> We install use at the end the ordered list of uses" << endl;
2683            }
2684
2685          uses.push_back (use);
2686          use->m_index = uses.size () - 1;
2687        }
2688
2689      if (Cmt::get_debug ())
2690        {
2691          for (int use_index = 0; use_index < uses.size (); use_index++)
2692            {
2693              Use* u = (Use*) uses[use_index];
2694              cout << "  use[" << use_index << "] p=(" << u << ")" << u->get_package_name () 
2695                   << " v=" << u->version
2696                   << " discarded=" << u->discarded
2697                   << " selected=" << u->selected
2698                   << " done=" << u->done
2699                   << " index=" << u->m_index
2700                   << endl;
2701            }
2702         
2703        }
2704         
2705      if (!use->done && Cmt::get_recursive ())
2706        {
2707          use->done = true;
2708
2709          if (Cmt::get_debug ())
2710            {
2711              cout << "Parsing requirements file at " << CmtSystem::pwd () << endl;
2712            }
2713
2714          SyntaxParser::parse_requirements ("requirements", use);
2715        }
2716      else
2717        {
2718          if (Cmt::get_debug ())
2719            {
2720              cout << "Requirements file at " << CmtSystem::pwd () << " already parsed" << endl;
2721            }
2722        }
2723    }
2724
2725  CmtSystem::cd (here);
2726
2727  return (use);
2728}
2729
2730//----------------------------------------------------------
2731void Use::discard ()
2732{
2733  discarded = true;
2734}
2735
2736//----------------------------------------------------------
2737void Use::undiscard ()
2738{
2739  discarded = false;
2740}
2741
2742//----------------------------------------------------------
2743void Use::select ()
2744{
2745  selected = true;
2746}
2747
2748//----------------------------------------------------------
2749void Use::unselect ()
2750{
2751  selected = false;
2752}
2753
2754//----------------------------------------------------------
2755bool Use::is_selected ()
2756{
2757  return (selected);
2758}
2759
2760/**
2761 *    Check if the package makes use of the specified package/version
2762 *
2763 *    The seach only considers the first level of uses (thus it is
2764 *   NOT recursive)
2765 */
2766bool Use::is_client (const cmt_string& used_package,
2767                     const cmt_string& used_version)
2768{
2769  // A package is client of itself
2770
2771  Package* package = Package::find (used_package);
2772
2773  if ((get_package () == package) &&
2774      (version == used_version)) return (true);
2775
2776  if (discarded) return (false);
2777
2778  int i;
2779
2780  for (i = 0; i < sub_uses.size (); i++)
2781    {
2782      Use* use = sub_uses[i];
2783      if (use == 0) continue;
2784
2785      if ((use->get_package () == package) &&
2786          (use->version == used_version)) return (true);
2787
2788      /*
2789        if (use->is_client (used_package, used_version))
2790        {
2791        return (true);
2792        }
2793      */
2794    }
2795
2796  return (false);
2797}
2798
2799//----------------------------------------------------------
2800void Use::apply_global_patterns ()
2801{
2802  int i;
2803
2804  Pattern::PatternVector& vector = Pattern::patterns ();
2805
2806  for (i = 0; i < vector.size (); i++)
2807    {
2808      Pattern& p = vector[i];
2809
2810      if (p.global)
2811        {
2812          p.apply (this);
2813        }
2814    }
2815}
2816
2817//----------------------------------------------------------
2818void Use::set_include_path (const cmt_string& new_path)
2819{
2820  include_path = new_path;
2821}
2822
2823/**
2824 *   Compute the full real path of a found package.
2825 *   Takes the structuring style into account
2826 *
2827 *    Result is used to fill in the referenced string
2828 *    Result does NOT include the trailing file_separator
2829 */
2830void Use::get_full_path (cmt_string& s) const
2831{
2832  if (real_path == "") s = CmtSystem::pwd ();
2833  else s = real_path;
2834
2835  s += CmtSystem::file_separator ();
2836  s += get_package_name ();
2837 
2838  if (style != no_version_style)
2839    {
2840      s += CmtSystem::file_separator ();
2841      s += version;
2842    }
2843}
2844
2845/**
2846 *   Compute the full real path of a found package.
2847 *   Takes the structuring style into account
2848 */
2849cmt_string Use::get_full_path () const
2850{
2851  cmt_string result;
2852
2853  get_full_path (result);
2854
2855  return (result);
2856}
2857
2858/**
2859 *   Considering a given path, try and reduce the part of it
2860 *  that corresponds to the full path of this package into its
2861 *  normal form ${<PACKAGE>ROOT}
2862 *   The argument is modified if the pattern is exactly found.
2863 */
2864void Use::reduce_path (cmt_string& s) const
2865{
2866  cmt_string pattern;
2867  get_full_path (pattern);
2868  pattern += CmtSystem::file_separator ();
2869 
2870  cmt_string replacement = "${";
2871  replacement += prefix;
2872  replacement += "ROOT}";
2873  replacement += CmtSystem::file_separator ();
2874
2875  s.replace (pattern, replacement);
2876}
2877
2878//----------------------------------------------------------
2879void Use::get_cmtpath_and_offset (cmt_string& cmtpath, cmt_string& offset) const
2880{
2881  if (get_package_name () == CmtSystem::get_project_package ())
2882    {
2883      offset = "";
2884      CmtSystem::dirname (path, cmtpath);
2885      return;
2886    }
2887  else if (get_package_name () == CmtSystem::get_home_package ())
2888    {
2889      offset = "";
2890      cmtpath = path;
2891      return;
2892    }
2893  else if (get_package_name () == CmtSystem::get_user_context_package ())
2894    {
2895      offset = "";
2896      cmtpath = path;
2897      return;
2898    }
2899
2900  cmtpath = "";
2901  offset = "";
2902
2903  cmtpath = Project::find_in_cmt_paths (real_path);
2904  Project* p = Project::find_by_cmtpath (cmtpath);
2905
2906  //  if (cmtpath != "")
2907  if (p != 0)
2908    {
2909      CmtSystem::compress_path (cmtpath);
2910
2911      static const cmt_string empty_string;
2912      static const cmt_string fs = CmtSystem::file_separator ();
2913     
2914      // In case there are symlinks
2915      //      offset = real_path;
2916      //      offset.replace (cmtpath, empty_string);
2917      //cerr << "realpath_: get_cmtpath_and_offset" << endl;
2918      CmtSystem::realpath_ (real_path, offset);
2919      offset.replace (p->get_cmtpath_real (), empty_string);
2920
2921      /**
2922         try to remove this current CMTPATH entry from path.  This
2923         has a meaning when the specified path already contains an
2924         absolute path.
2925      */
2926     
2927      if (offset[0] == CmtSystem::file_separator ())
2928        {
2929          // Just in case there is a part left after removing the cmtpath entry
2930               
2931          offset.replace (fs, empty_string);
2932        }
2933    }
2934}
2935
2936//------------------------------------------------------------
2937bool Use::get_strategy (const cmt_string& name) const
2938{
2939  Project* p = Project::find_by_cmtpath (real_path);
2940
2941  bool strategy;
2942
2943  if (p == 0)
2944    {
2945      static const Project::ProjectVector& projects = Project::projects ();
2946
2947      if (projects.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
2948      else
2949        {
2950          p = &(projects[0]);
2951          strategy = p->get_strategy (name);
2952        }
2953    }
2954  else
2955    {
2956      strategy = p->get_strategy (name);
2957    }
2958
2959  return (strategy);
2960}
2961
2962//----------------------------------------------------------
2963void Use::fill_includes_macro (cmt_string& buffer) const
2964{
2965  if (include_path == "")
2966    {
2967      buffer += "$(ppcmd)\"$(";
2968      buffer += get_package_name ();
2969      buffer += "_root)";
2970      buffer += CmtSystem::file_separator ();
2971      buffer += "src\" ";
2972    }
2973  else if (include_path != "none")
2974    {
2975      buffer += "$(ppcmd)\"";
2976      buffer += include_path;
2977      buffer += "\" ";
2978    }
2979 
2980  for (int i = 0; i < includes.size (); i++)
2981    {
2982      Include& incl = includes[i];
2983
2984      if (incl.name == "") continue;
2985     
2986      buffer += "$(ppcmd)\"";
2987      buffer += incl.name;
2988      buffer += "\" ";
2989    }
2990}
2991
2992//----------------------------------------------------------
2993void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
2994{
2995  buffer += " $(";
2996  buffer += get_package_name ();
2997  buffer += "_";
2998  buffer += suffix;
2999  buffer += ") ";
3000}
3001
3002//----------------------------------------------------------
3003void Use::fill_standard_macros (cmt_string& buffer) const
3004{
3005  static cmt_string fs = CmtSystem::file_separator ();
3006
3007  buffer = "";
3008
3009  cmt_string package_name = get_package_name ();
3010
3011  buffer += "macro ";
3012  buffer += package_name;
3013  buffer += "_tag";
3014  buffer += " \"$(tag)\"";
3015  buffer += "\n";
3016
3017  if (located ())
3018    {
3019      buffer += "macro ";
3020      buffer += prefix;
3021      buffer += "ROOT";
3022      buffer += " \"";
3023      buffer += get_full_path ();
3024      buffer += "\"";
3025      buffer += "\n";
3026
3027      buffer += "macro ";
3028      buffer += package_name;
3029      buffer += "_root";
3030      buffer += " \"";
3031      buffer += real_path;
3032      buffer += fs;
3033      buffer += package_name;
3034      if (style != no_version_style)
3035        {
3036          buffer += fs;
3037          buffer += version;
3038        }
3039      buffer += "\"";
3040      buffer += "\n";
3041    }
3042
3043  buffer += "macro ";
3044  buffer += prefix;
3045  buffer += "VERSION";
3046  buffer += " \"";
3047  buffer += version;
3048  buffer += "\"";
3049  buffer += "\n";
3050
3051  cmt_string cmtpath = "";
3052  cmt_string offset = "";
3053
3054  get_cmtpath_and_offset (cmtpath, offset);
3055
3056  buffer += "macro ";
3057  buffer += package_name;
3058  buffer += "_cmtpath";
3059  buffer += " \"";
3060  buffer += cmtpath;
3061  buffer += "\"";
3062  buffer += "\n";
3063
3064  buffer += "macro ";
3065  buffer += package_name;
3066  buffer += "_offset";
3067  buffer += " \"";
3068  buffer += offset;
3069  buffer += "\"";
3070  buffer += "\n";
3071 
3072  Project* p = Project::find_by_cmtpath (cmtpath);
3073
3074  buffer += "macro ";
3075  buffer += package_name;
3076  buffer += "_project";
3077  buffer += " \"";
3078  if (p != 0)
3079    {
3080      buffer += p->get_name ();
3081    }
3082  buffer += "\"";
3083  buffer += "\n";
3084
3085  buffer += "macro ";
3086  buffer += package_name;
3087  buffer += "_project_release";
3088  buffer += " \"";
3089  if (p != 0)
3090    {
3091      buffer += p->get_release ();
3092    }
3093  buffer += "\"";
3094}
3095
3096
3097//----------------------------------------------------------
3098static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
3099{
3100  bool result = false;
3101
3102  cmt_string here = CmtSystem::pwd ();
3103
3104  cmt_string h1;
3105  if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
3106
3107  CmtSystem::cd (here);
3108
3109  cmt_string h2;
3110  if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
3111
3112  result = (h1 == h2);
3113
3114  CmtSystem::cd (here);
3115
3116  return (result);
3117}
3118
3119//----------------------------------------------------------
3120static bool install_library (const cmt_string& source_library_name, 
3121                             const cmt_string& dest_library_name, 
3122                             const cmt_string& cmtinstallarea, 
3123                             const cmt_string& tag, 
3124                             const cmt_string& symlinkcmd)
3125{
3126  cmt_string libname = source_library_name;
3127  cmt_string name = dest_library_name;
3128  cmt_string s;
3129  Use& current_use = Use::current ();
3130
3131  Symbol::expand (name);
3132  Symbol::expand (libname);
3133
3134  if (cmtinstallarea != "")
3135    {
3136      s = cmtinstallarea;
3137      s += CmtSystem::file_separator ();
3138      s += tag;
3139      s += CmtSystem::file_separator ();
3140      s += "lib";
3141      s += CmtSystem::file_separator ();
3142      s += name;
3143     
3144      // Now creating the reference file
3145
3146      cmt_string ref_file = s;
3147      ref_file += ".cmtref";
3148
3149      cmt_string text = libname;
3150      text += "\n";
3151
3152      Symbol::expand (ref_file);
3153      Symbol::expand (text);
3154
3155      if (!Cmt::get_quiet ()) cerr << "   Creating the reference file " << ref_file << endl;
3156      text.write (ref_file);
3157    }
3158  else
3159    {
3160      s = "../$(";
3161      s += current_use.get_package_name ();
3162      s += "_tag)/";
3163      s += name;
3164    }
3165
3166  Symbol::expand (s);
3167
3168  cmt_string source;
3169  cmt_string dest;
3170
3171  CmtSystem::dirname (libname, source);
3172  CmtSystem::dirname (s, dest);
3173
3174  if (same_dirs (source, dest))
3175    {
3176      return (false);
3177    }
3178
3179  //if (!Cmt::get_quiet ())
3180  cerr << "   Symlinking " << libname << " to " << s << endl;
3181
3182  if (symlinkcmd == "")
3183    {
3184      if (!CmtSystem::create_symlink (libname, s))
3185        {
3186          cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3187          return (false);
3188        }
3189    }
3190  else
3191    {
3192      cmt_string cmd = symlinkcmd;
3193      cmd += " ";
3194      cmd += libname;
3195      cmd += " ";
3196      cmd += s;
3197     
3198      int status = CmtSystem::execute (cmd);
3199     
3200      if (status != 0)
3201        {
3202          cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3203          return (false);
3204        }
3205    }
3206
3207  return (true);
3208}
3209
3210
3211/**
3212   Centralize the construction of library links for this Use.
3213*/
3214void Use::build_library_links (const cmt_string& cmtinstallarea, 
3215                               const cmt_string& tag, 
3216                               const cmt_string& shlibsuffix, 
3217                               const cmt_string& symlinkcmd) const
3218{
3219  if (!located ())
3220    {
3221      if (!Cmt::get_quiet ())
3222        {
3223          cerr << "# package " << get_package_name () <<
3224            " " << version << " " << path << 
3225            " not found" <<
3226            endl;
3227        }
3228      return;
3229    }
3230
3231  cmt_string s;
3232
3233  s = get_package_name ();
3234  s += "_libraries";
3235
3236  Symbol* libraries_macro = Symbol::find (s);
3237
3238  if (libraries_macro == 0) return;
3239
3240  cmt_string libraries = libraries_macro->build_macro_value ();
3241  Symbol::expand (libraries);
3242  static CmtSystem::cmt_string_vector values;
3243
3244  CmtSystem::split (libraries, " \t", values);
3245
3246  for (int j = 0; j < values.size (); j++)
3247    {
3248      const cmt_string& library = values[j];
3249
3250      static cmt_string libname;
3251      static cmt_string name;
3252
3253      // Is it a simple name or a complete path?
3254
3255      libname = library;
3256      Symbol::expand (libname);
3257
3258      bool is_absolute = false;
3259
3260      is_absolute = CmtSystem::absolute_path (libname);
3261
3262      if (is_absolute)
3263        {
3264          /**
3265           *   We assume here that "library" contains a complete path.
3266           *   (including the complete syntax libxxx.so)
3267           */
3268
3269          cmt_string suffix;
3270          CmtSystem::basename (library, name);
3271        }
3272      else
3273        {
3274          /**
3275           *   Here we expect that only the base name of the library
3276           *   is given : ie it should not contain the "lib" prefix,
3277           *   nor the suffix .so, nor any path prefix.
3278           *    This of course should generally correspond to a constituent name.
3279           */
3280         
3281          libname = "${";
3282          libname += prefix;
3283          libname += "ROOT}/${";
3284          libname += get_package_name ();
3285          libname += "_tag}/";
3286          libname += "$(library_prefix)";
3287          libname += library;
3288          libname += "$(library_suffix)";
3289          libname += ".";
3290          libname += shlibsuffix;
3291
3292          name = "$(library_prefix)";
3293          name += library;
3294          name += "$(library_suffix)";
3295          name += ".";
3296          name += shlibsuffix;
3297        }
3298
3299      if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3300        {
3301          continue;
3302        }
3303
3304#ifdef __APPLE__
3305      if (!is_absolute)
3306        {
3307          libname = "${";
3308          libname += prefix;
3309          libname += "ROOT}/${";
3310          libname += get_package_name ();
3311          libname += "_tag}/";
3312          libname += library;
3313          libname += ".bundle";
3314
3315          name = library;
3316          name += ".bundle";
3317         
3318          if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3319            {
3320              continue;
3321            }
3322        }
3323#endif
3324    }
3325}
3326
3327/**
3328 *   This function tries to get the replacement of a Use when it has
3329 *  been discarded by a better match to version constraints.
3330 */
3331Use* Use::get_selected_version ()
3332{
3333  if (!discarded) return (this);
3334
3335  Package* p = m_package;
3336
3337  Use::UsePtrVector& uses = p->get_uses ();
3338
3339  bool dbg = Cmt::get_debug ();
3340
3341  int size = uses.size ();
3342
3343  for (int i = 0; i < size; i++)
3344    {
3345      Use* u = uses[i];
3346      if (u == 0) continue;
3347      if (u->discarded) continue;
3348      if (dbg)
3349        {
3350          cout << "Use::get_selected_version> for package " << get_package_name ()
3351               << "  got a version " << u << endl;
3352        }
3353      return (u);
3354    }
3355
3356  return (0);
3357}
3358
3359/**
3360   Switching from one use to another one, (better wrt
3361   various criteria).
3362
3363   When switching, m_index and auto_imports are
3364   transfered from the un-selected to the newly selected.
3365*/
3366Use* Use::set_selected_version (Use* selected_use)
3367{
3368  if (this == selected_use) return (this);
3369
3370  static UsePtrVector& uses = get_ordered_uses ();
3371
3372  if (m_index >= 0)
3373    {
3374      // This discarded package was registered. We have to substitute
3375      // it with the new one.
3376
3377      selected_use->m_index = m_index;
3378      selected_use->auto_imports = auto_imports;
3379
3380      selected_use->undiscard ();
3381
3382      m_index = -1;
3383
3384      uses[selected_use->m_index] = selected_use;
3385    }
3386
3387  discard ();
3388
3389  return (selected_use);
3390}
3391
3392void Use::set_auto_imports (State new_state)
3393{
3394  if (Cmt::get_debug ())
3395    {
3396      cout << "Use::set_auto_imports>(" << get_package_name () << ") " 
3397           << auto_imports << " -> " << new_state << endl;
3398    }
3399
3400  if (auto_imports == new_state) return;
3401 
3402  State old_state = auto_imports;
3403 
3404  auto_imports = new_state;
3405
3406  // We propagate only when we switch from Off to On
3407
3408  if ((old_state == Off) && (new_state == On))
3409    {
3410      cmt_string s;
3411      static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
3412
3413      if (Cmt::get_debug ())
3414        {
3415          s = "Use::set_auto_imports>(";
3416          s += get_package_name ();
3417          s += ") ";
3418
3419          cout << s << endl;
3420        }
3421
3422      for (int i = 0; i < sub_uses.size (); i++)
3423        {
3424          Use* u = sub_uses[i];
3425          State state = sub_use_auto_imports[i];
3426         
3427          if (Cmt::get_debug ())
3428            {
3429              s += " ";
3430              s += u->get_package_name ();
3431              s += "(";
3432              s += state_text[state];
3433              s += ")";
3434            }
3435
3436          if (state == Unspecified)
3437            {
3438              u->set_auto_imports (On);
3439            }
3440        }
3441         
3442      if (Cmt::get_debug ())
3443        {
3444          cout << s << endl;
3445        }
3446    }
3447}
3448
3449void Use::set_native_version (bool state)
3450{
3451  m_has_native_version = state;
3452}
3453
3454bool Use::has_native_version () const
3455{
3456  return (m_has_native_version);
3457}
3458
3459Package* Use::get_package () const
3460{
3461  return (m_package);
3462}
3463
3464const cmt_string& Use::get_package_name () const
3465{
3466  static const cmt_string null = "";
3467
3468  Package* p = m_package;
3469  if (p == 0) return (null);
3470
3471  return (p->get_name ());
3472}
3473
3474void Use::set_package_name (const cmt_string& name)
3475{
3476  Package* p = Package::add (name);
3477
3478  m_package = p;
3479  p->add_use (this);
3480}
3481
3482int Use::get_index () const
3483{
3484  return (m_index);
3485}
3486
3487//----------------------------------------------------------
3488bool Use::get_all_clients (const cmt_string& to_name)
3489{
3490  Use::UsePtrVector& uses = Use::get_ordered_uses ();
3491
3492  Use* use = Use::find (to_name);
3493
3494  if (use == 0)
3495    {
3496      cerr << "#CMT> No access to " << to_name << endl;
3497      return (false);
3498    }
3499
3500  cmt_map <cmt_string, Use*> all_clients;
3501  cmt_map <cmt_string, Use*> all_clients_ok;
3502
3503  const cmt_string& name = get_package_name ();
3504
3505  Use* me = this;
3506
3507  all_clients.add (name, me);
3508  all_clients_ok.add (name, me);
3509
3510  bool status = get_all_clients (use, to_name, all_clients, all_clients_ok); 
3511
3512  return (status);
3513}
3514
3515//----------------------------------------------------------
3516bool Use::get_all_clients (Use* to, 
3517                           const cmt_string& result, 
3518                           cmt_map <cmt_string, Use*>& all_clients, 
3519                           cmt_map <cmt_string, Use*>& all_clients_ok)
3520{
3521  if (this == to)
3522    {
3523      cout << result << endl;
3524      return (true);
3525    }
3526
3527  const cmt_string& to_name = to->get_package_name ();
3528  const cmt_string& to_version = to->version;
3529
3530  //cout << "gac> from " << get_package_name () << " to " << to_name << " -> " << result << endl;
3531
3532  if (all_clients.has (to_name))
3533    {
3534      if (all_clients_ok.has (to_name))
3535        {
3536          cout << "   ..." << result << endl;
3537          return (true);
3538        }
3539      else
3540        {
3541          return (false);
3542        }
3543    }
3544
3545  all_clients.add (to_name, to);
3546
3547  bool status = false;
3548
3549  Use::UsePtrVector& uses = Use::get_ordered_uses ();
3550  Use* use = 0;
3551
3552  for (int n = 0; n < uses.size (); ++n)
3553    {
3554      use = uses[n];
3555
3556      if (use->discarded) continue;
3557      if (use->m_hidden) continue;
3558
3559      if (!use->located ()) continue;
3560
3561      if (use == to) continue;
3562
3563      if (use->is_client (to_name, to_version))
3564        {
3565          const cmt_string& n = use->get_package_name ();
3566
3567          cmt_string r;
3568
3569          if ((use->initial_scope != ScopeUnspecified) &&
3570              (use->initial_scope != ScopePublic)) 
3571            {
3572              r += "(private)";
3573            }
3574         
3575          if (use->auto_imports == Off) r += "(no_auto_imports)";
3576
3577          r += n;
3578          r += ".";
3579          r += result;
3580
3581          //cout << "gac> " << n << " is client of " << to_name << endl;
3582
3583          if (get_all_clients (use, r, all_clients, all_clients_ok))
3584            {
3585              all_clients_ok.add (n, use);
3586              status = true;
3587            }
3588        }
3589    }
3590
3591  use = this;
3592
3593  if (use->is_client (to_name, to_version))
3594    {
3595      const cmt_string& n = use->get_package_name ();
3596     
3597      cmt_string r;
3598
3599      if ((use->initial_scope != ScopeUnspecified) &&
3600          (use->initial_scope != ScopePublic)) 
3601        {
3602          r += "(private)";
3603        }
3604     
3605      if (use->auto_imports == Off) r += "(no_auto_imports)";
3606
3607      r += n;
3608      r += ".";
3609      r += result;
3610     
3611      //cout << "gac> " << n << " is client of " << to_name << endl;
3612     
3613      if (get_all_clients (use, r, all_clients, all_clients_ok))
3614        {
3615          all_clients_ok.add (n, use);
3616          status = true;
3617        }
3618    }
3619
3620  return (status);
3621}
3622
3623/**
3624   Let's consider two packages in the use graph "this" and "to"
3625   This function finds all packages that are reached in between
3626   following all possible paths between "this" and "to"
3627
3628   Result s accumulated into "list"
3629*/
3630bool Use::get_paths (Use* to, UsePtrVector& list)
3631{
3632  bool is_in_path = false;
3633  bool cycle = false;
3634  bool already_in_path = false;
3635  bool dbg = Cmt::get_debug ();
3636
3637  static int level = 0;
3638
3639  int size = 0;
3640
3641  if (level == 0)
3642    {
3643      unselect_all ();
3644      selected = false;
3645    }
3646
3647  if (selected) 
3648    {
3649      /**
3650         If this use is already in the list, we don't duplicate the entry.
3651         (protection duplicate paths in the graph)
3652      */
3653
3654      size = list.size ();
3655
3656      for (int m = 0; m < size; m++)
3657        {
3658          Use* u = list[m];
3659          if (u == this)
3660            {
3661              if (dbg)
3662                {
3663                  for (int lll = 0; lll < level; lll++) cout << "  ";
3664                  cout << "  Use::get_paths." << level << "> try1.2 sub="
3665                       << get_package_name () << " already_in_path " << endl;
3666                }
3667             
3668              return (true);
3669            }
3670        }
3671
3672      return (false);
3673    }
3674
3675  selected = true;
3676
3677  if (dbg)
3678    {
3679      for (int lll = 0; lll < level; lll++) cout << "  ";
3680      cout << "Use::get_paths." << level << ">" << get_package_name ()
3681           << " to=" << to->get_package_name () 
3682           << " list=[";
3683
3684      for (int m = 0; m < list.size (); m++)
3685        {
3686          Use* u = list[m];
3687          cout << u->get_package_name () << " ";
3688        }
3689
3690      cout << "]" << endl;
3691    }
3692
3693  /**
3694     Now "this" is a candidate new entry in the list
3695  */
3696
3697  // First figure out whether 'to' is used by 'this'.
3698
3699  if (this->get_package_name () == to->get_package_name ())
3700    {
3701      // We've reached the goal (for the first time)
3702      is_in_path = true;
3703    }
3704  else
3705    {
3706      /**
3707         Let's scan sub_uses now
3708      */
3709      size = sub_uses.size ();
3710
3711      if (dbg)
3712        {
3713          for (int lll = 0; lll < level; lll++) cout << "  ";
3714          cout << "  Use::get_paths." << level << "> size=" << size << endl;
3715        }
3716
3717      for (int n = 0; n < size; n++)
3718        {
3719          Use* use = sub_uses[n];
3720
3721          if (use == 0) continue;
3722
3723          if (dbg)
3724            {
3725              for (int lll = 0; lll < level; lll++) cout << "  ";
3726              cout << "  Use::get_paths." << level << "> try1 sub="
3727                   << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
3728            }
3729
3730          if (use->discarded)
3731            {
3732              Use* u;
3733
3734              u = use->get_selected_version ();
3735              if (u == 0) 
3736                {
3737                  /**
3738                     No way to find a valid use for this used package.
3739                     Is that a bug?
3740                     Anyway we don't pursue on that branch.
3741                  */
3742                  continue;
3743                }
3744
3745              use = u;
3746            }
3747
3748          if (dbg)
3749            {
3750              for (int lll = 0; lll < level; lll++) cout << "  ";
3751              cout << "  Use::get_paths." << level << "> try2 sub="
3752                   << use->get_package_name () << " " << use->discarded << endl;
3753            }
3754
3755          level++;
3756          bool r = use->get_paths (to, list);
3757          level--;
3758
3759          if (r)
3760            {
3761              is_in_path = true;
3762            }
3763        }
3764    }
3765
3766  if (is_in_path)
3767    {
3768      if (dbg)
3769        {
3770          for (int lll = 0; lll < level; lll++) cout << "  ";
3771          cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
3772        }
3773      list.push_back (this);
3774    }
3775
3776  return (is_in_path);
3777}
3778
3779//----------------------------------------------------------
3780bool Use::located () const
3781{
3782  return (m_located);
3783}
3784
3785//----------------------------------------------------------
3786void Use::show_sub_uses (const cmt_string& request, bool skip_discarded)
3787{
3788  Use* current = &(Use::current ());
3789  int n;
3790  Use* use;
3791  static int level = 0;
3792
3793  if (skip_discarded && discarded) return;
3794  if (m_hidden) return;
3795
3796  if (level > 0)
3797    {
3798      cout << "# ";
3799      for (n = 0; n < (level-1); n++) cout << "  ";
3800
3801      if (request == "")
3802        {
3803          cout << "use " << get_package_name () << " " << specified_version;
3804
3805          if (this == current) 
3806            {
3807              cout << " (current)";
3808            }
3809          else
3810            {
3811              if (specified_path != "") cout << " " << specified_path;
3812            }
3813        }
3814      else
3815        {
3816          cout << "use " << request;
3817        }
3818
3819      if (version_alias != "")
3820        {
3821          cout << " | " << version_alias << " " << path_alias;
3822        }
3823
3824      if (initial_scope == ScopeUnspecified) cout << " (unspecified)";
3825      else if (initial_scope != ScopePublic) cout << " (private)";
3826
3827      if (auto_imports == Off) cout << " (no_auto_imports)";
3828
3829      if (style == no_version_style) cout << " (no_version_directory)";
3830
3831      if (m_has_native_version)
3832        {
3833          cmt_string n = get_package_name ();
3834          n += "_native_version";
3835
3836          Symbol* s = Symbol::find (n);
3837          if (s != 0)
3838            {
3839              cmt_string value = s->resolve_macro_value ();
3840              cout << " (native_version=" << value << ")";
3841            }
3842        }
3843
3844      cout << endl;
3845    }
3846
3847  if (selected) return;
3848  selected = true;
3849
3850  level++;
3851  for (n = 0; n < sub_uses.size (); n++)
3852    {
3853      use = sub_uses[n];
3854      if (use == 0) continue;
3855
3856      const cmt_string& request = requests[n];
3857
3858      ScopeType saved_scope = use->initial_scope;
3859      State saved_state = use->auto_imports;
3860
3861      use->initial_scope = sub_use_scopes[n];
3862      use->auto_imports = sub_use_auto_imports[n];
3863
3864      use->show_sub_uses (request, skip_discarded);
3865
3866      use->initial_scope = saved_scope;
3867      use->auto_imports = saved_state;
3868    }
3869  level--;
3870}
3871
3872//----------------------------------------------------------
3873Use& Use::current ()
3874{
3875  static UseVector& instances = get_instances ();
3876  static Use* current_use = 0;
3877
3878  if ((current_use == 0) || (instances.size () == 0))
3879    {
3880      Use& use_object = instances.add ();
3881      current_use = &use_object;
3882    }
3883
3884  return (*current_use);
3885}
3886
3887//----------------------------------------------------------
3888const Use& Use::const_current ()
3889{
3890  const Use& use = Use::current ();
3891
3892  return (use);
3893}
3894
3895//----------------------------------------------------------
3896Use::UseVector& Use::get_instances ()
3897{
3898  static Database& db = Database::instance ();
3899  static UseVector& instances = db.all_uses ();
3900
3901  return (instances);
3902}
3903
3904//----------------------------------------------------------
3905Use::UsePtrVector& Use::get_ordered_uses ()
3906{
3907  static Database& db = Database::instance ();
3908  static UsePtrVector& uses = db.uses ();
3909
3910  return (uses);
3911}
3912
3913//----------------------------------------------------------
3914
3915//----------------------------------------------------------
3916//
3917//  Check if the specified version is better than the
3918//  current one.
3919//
3920//----------------------------------------------------------
3921Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
3922{
3923  Use* selected = ref_use;
3924
3925  int ref_v = -1;
3926  int ref_r = -1;
3927  int ref_p = -1;
3928  cmt_string ref_pp;
3929
3930  int new_v = -1;
3931  int new_r = -1;
3932  int new_p = -1;
3933  cmt_string new_pp;
3934
3935  int alias_v = -1;
3936  int alias_r = -1;
3937  int alias_p = -1;
3938  cmt_string alias_pp;
3939
3940  enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
3941
3942  // First analyze specified versions
3943  cmt_string ref_version = ref_use->specified_version;
3944  cmt_string new_version = new_use->specified_version;
3945
3946  CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
3947  ref_pp = ref_use->path;
3948
3949  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
3950  new_pp = new_use->path;
3951
3952  if (new_use->version_alias != "")
3953    {
3954      has_alias = new_has_alias;
3955      CmtSystem::is_version_directory (new_use->version_alias, 
3956                                       alias_v, alias_r, alias_p);
3957      alias_pp = new_use->path_alias;
3958    }
3959  else if (ref_use->version_alias != "")
3960    {
3961      has_alias = ref_has_alias;
3962      CmtSystem::is_version_directory (ref_use->version_alias, 
3963                                       alias_v, alias_r, alias_p);
3964      alias_pp = ref_use->path_alias;
3965    }
3966
3967  ref_use->undiscard ();
3968  new_use->undiscard ();
3969
3970  if (new_v != ref_v)
3971    {
3972      if (has_alias != no_alias)
3973        {
3974          if (has_alias == new_has_alias)
3975            {
3976              new_v = alias_v;
3977              new_r = alias_r;
3978              new_p = alias_p;
3979              new_pp = alias_pp;
3980            }
3981          else if (has_alias == ref_has_alias)
3982            {
3983              ref_v = alias_v;
3984              ref_r = alias_r;
3985              ref_p = alias_p;
3986              ref_pp = alias_pp;
3987            }
3988        }
3989    }
3990
3991  bool ref_v_wildcarded = ((ref_v) == -1);
3992  bool ref_r_wildcarded = ((ref_r) == -1);
3993  bool ref_p_wildcarded = ((ref_p) == -1);
3994
3995  bool ref_v_explicit = !ref_v_wildcarded;
3996  bool ref_r_explicit = !ref_r_wildcarded;
3997  bool ref_p_explicit = !ref_p_wildcarded;
3998
3999  bool new_v_wildcarded = ((new_v) == -1);
4000  bool new_r_wildcarded = ((new_r) == -1);
4001  bool new_p_wildcarded = ((new_p) == -1);
4002
4003  bool new_v_explicit = !new_v_wildcarded;
4004  bool new_r_explicit = !new_r_wildcarded;
4005  bool new_p_explicit = !new_p_wildcarded;
4006
4007  bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
4008
4009  cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
4010  cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
4011  cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
4012 
4013  cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
4014  cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
4015  cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
4016
4017  // Now compute effective version identifiers
4018  CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
4019  CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
4020
4021  cmt_string new_selected_version = new_use->version;
4022
4023  if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
4024    {
4025      /*
4026        if (verbose && !Cmt::get_quiet ())
4027        {
4028        cerr << "# Required explicit version " << new_version
4029        << " of package " << ref_use->get_package_name ()
4030        << " incompatible with selected explicit version " << ref_version
4031        << endl;
4032        }
4033
4034        CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
4035
4036        if (ref_use != new_use) new_use->discard ();
4037      */
4038
4039      if (new_v > ref_v)
4040        {
4041          if (verbose && !Cmt::get_quiet ())
4042            {
4043              cerr << "# Select " << new_vc << " version " << new_version
4044                   << " of package " << ref_use->get_package_name () 
4045                   << " instead of existing " << ref_vc << " " << ref_version
4046                   << endl;
4047            } 
4048         
4049          if (ref_use != new_use) ref_use->discard ();
4050          selected = new_use;
4051          selected->done = false; // Will read the new requirements
4052        }
4053    }
4054  else if (new_v_wildcarded || ref_v_wildcarded)
4055    {
4056      // at least one of ref or new is wildcarded
4057
4058      //
4059      // we plan to discard new_use, but if it was specified as explicit
4060      // and ref_use was wildcarded then new_use will win !!
4061      //
4062      // So then we'll have to understand where are the wild
4063      // cards... If they are on v or r, then we consider them.
4064      //
4065      //
4066
4067      if (ref_v_wildcarded && new_v_explicit)
4068        {
4069          if ((ref_use->real_path != new_use->real_path) ||
4070              (ref_use->version != new_use->version))
4071            {
4072              if (ref_use != new_use) ref_use->discard ();
4073              selected = new_use;
4074              selected->done = false; // Will read the new requirements
4075
4076              if (verbose && !Cmt::get_quiet ())
4077                {
4078                  cerr << "# Select explicit version " << new_version
4079                       << "(" << new_use->version << ")" 
4080                       << " of package " << ref_use->get_package_name () 
4081                       << " instead of existing wildcarded " << ref_version
4082                       << "(" << ref_use->version << ")" 
4083                       << endl;
4084                }
4085            }
4086          else
4087            {
4088              if (ref_use != new_use) new_use->discard ();
4089              //ref_use->version = new_selected_version;
4090            }
4091        }
4092      else
4093        {
4094          // ref is explicit or new is wildcarded
4095
4096          /*
4097            if (verbose && !Cmt::get_quiet ())
4098            {
4099            cerr << "# keep " << ref_vc << " version " << ref_version
4100            << " of package " << ref_use->get_package_name ()
4101            << " (ignore " << new_vc << " version " << new_version << ")"
4102            << endl;
4103            }
4104          */
4105
4106          if (ref_use != new_use) new_use->discard ();
4107        }
4108    }
4109  else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
4110    {
4111      //
4112      // we plan to discard new_use, but if it was specified as explicit
4113      // and ref_use was wildcarded then new_use will win !!
4114      //
4115      // So then we'll have to understand where are the wild
4116      // cards... If they are on v or r, then we consider them.
4117      //
4118      //
4119
4120      if (ref_r_wildcarded && new_r_explicit)
4121        {
4122          // ref has wild card and new has not => new wins
4123
4124          if ((ref_use->real_path != new_use->real_path) ||
4125              (ref_use->version != new_use->version))
4126            {
4127              if (ref_use != new_use) ref_use->discard ();
4128              selected = new_use;
4129              selected->done = false; // Will read the new requirements
4130
4131              if (verbose && !Cmt::get_quiet ())
4132                {
4133                  cerr << "# Select explicit release " << new_version
4134                       << " of package " << ref_use->get_package_name ()
4135                       << " instead of existing wildcarded " << ref_version
4136                       << endl;
4137                } 
4138            }
4139          else
4140            {
4141              // Just adapt version with new one.
4142
4143              if (ref_use != new_use) new_use->discard ();
4144              //ref_use->version = new_selected_version;
4145            }
4146        }
4147      else
4148        {
4149          /*
4150            if (verbose &&!Cmt::get_quiet ())
4151            {
4152            cerr << "# keep " << ref_rc << " release " << ref_version
4153            << " of package " << ref_use->get_package_name ()
4154            << " (ignore " << new_rc << " release " << new_version << ")"
4155            << endl;
4156            }
4157          */
4158
4159          if (ref_use != new_use) new_use->discard ();
4160        }
4161    }
4162  else if (new_r > ref_r)
4163    {
4164      if (verbose && !Cmt::get_quiet ())
4165        {
4166          cerr << "# Select " << new_rc << " release " << new_version
4167               << " of package " << ref_use->get_package_name () 
4168               << " instead of existing " << ref_rc << " " << ref_version
4169               << endl;
4170        } 
4171
4172      if (ref_use != new_use) ref_use->discard ();
4173      selected = new_use;
4174      selected->done = false; // Will read the new requirements
4175    }
4176  else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
4177    {
4178      //
4179      // we plan to discard new_use, but if it was specified as explicit
4180      // and ref_use was wildcarded then new_use will win !!
4181      //
4182
4183      if (ref_p_wildcarded && new_p_explicit)
4184        {
4185          if ((ref_use->real_path != new_use->real_path) ||
4186              (ref_use->version != new_use->version))
4187            {
4188              if (ref_use != new_use) ref_use->discard ();
4189              selected = new_use;
4190              selected->done = false; // Will read the new requirements
4191
4192              if (verbose && !Cmt::get_quiet ())
4193                {
4194                  cerr << "# Select explicit patch " << new_version
4195                       << " of package " << ref_use->get_package_name () 
4196                       << " instead of existing wildcarded " << ref_version
4197                       << endl;
4198                }
4199            }
4200          else
4201            {
4202              if (ref_use != new_use) new_use->discard ();
4203              ref_use->version = new_selected_version;
4204            }
4205        }
4206      else
4207        {
4208          /*
4209            if (verbose && !Cmt::get_quiet ())
4210            {
4211            cerr << "# keep " << ref_pc << " patch " << ref_version
4212            << " [" << ref_use->specified_version << "]"
4213            << " of package " << ref_use->get_package_name ()
4214            << " (ignore " << new_pc << " version " << new_version << ")"
4215            << " [" << new_use->specified_version << "]"
4216            << endl;
4217            }
4218          */
4219
4220          if (ref_use != new_use) new_use->discard ();
4221        }
4222    }
4223  else if (new_p > ref_p)
4224    {
4225      if (verbose && !Cmt::get_quiet ())
4226        {
4227          cerr << "# Select " << new_pc << " patch " << new_version
4228               << " of package " << ref_use->get_package_name () 
4229               << " instead of existing " << ref_pc << " " << ref_version
4230               << endl;
4231        }
4232
4233      if (ref_use != new_use) ref_use->discard ();
4234      selected = new_use;
4235      selected->done = false; // Will read the new requirements
4236    }
4237  else if (new_pp != ref_pp) // same version-r-p but from different path
4238    {
4239      if (ref_use != new_use) ref_use->discard ();
4240      selected = new_use;
4241      selected->done = false; // Will read the new requirements
4242    }
4243
4244  return (selected);
4245}
4246
4247
4248Package* Package::find (const cmt_string& name)
4249{
4250  static PackageMap& PackageMap = package_map ();
4251
4252  Package* result = 0;
4253
4254  result = PackageMap.find (name);
4255
4256  return (result);
4257}
4258
4259Package* Package::add (const cmt_string& name)
4260{
4261  static PackageVector& Packages = packages ();
4262  static PackageMap& PackageMap = package_map ();
4263
4264  {
4265    Package* package;
4266
4267    package = find (name);
4268    if (package != 0) return (package);
4269  }
4270
4271  Package& package = Packages.add ();
4272  PackageMap.add (name, package);
4273
4274  package.m_name = name;
4275
4276  if (name == "CMT")
4277    {
4278      package.m_is_cmt = true;
4279    }
4280  else if (name == "methods")
4281    {
4282      package.m_is_cmt = true;
4283    }
4284
4285  if (Cmt::get_debug ())
4286    {
4287      cout << "Package::add (" << name << ")" << endl;
4288    }
4289
4290  return (&package);
4291}
4292
4293Package::PackageVector& Package::packages ()
4294{
4295  static Database& db = Database::instance ();
4296  static PackageVector& Packages = db.packages ();
4297
4298  return (Packages);
4299}
4300
4301Package::PackageMap& Package::package_map ()
4302{
4303  static Database& db = Database::instance ();
4304  static PackageMap& PackageMap = db.package_map ();
4305
4306  return (PackageMap);
4307}
4308
4309void Package::clear_all ()
4310{
4311  static PackageVector& Packages = packages ();
4312  static PackageMap& PackageMap = package_map ();
4313
4314  PackageMap.clear ();
4315  Packages.clear ();
4316}
4317
4318Package::Package () : m_is_cmt (false)
4319{
4320  if (Cmt::get_debug ())
4321    {
4322      cout << "Package::Package" << endl;
4323    }
4324}
4325
4326Package::~Package ()
4327{
4328  m_name = "";
4329}
4330
4331const cmt_string& Package::get_name () const
4332{
4333  return (m_name);
4334}
4335
4336void Package::add_use (Use* use)
4337{
4338  for (int i = 0; i < m_uses.size (); i++)
4339    {
4340      Use* u = m_uses[i];
4341      if (u == use) return;
4342    }
4343
4344  m_uses.push_back (use);
4345}
4346
4347void Package::remove_use (Use* use)
4348{
4349  if (Cmt::get_debug ())
4350    {
4351      cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
4352      cout << "  name=" << m_name
4353           << " uses=" << m_uses.size () << endl;
4354    }
4355
4356  Use::UsePtrVector temp;
4357
4358  temp = m_uses;
4359
4360  m_uses.clear ();
4361
4362  for (int i = 0; i < temp.size (); i++)
4363    {
4364      Use* u = temp[i];
4365      if (u != use)
4366        {
4367          m_uses.push_back (u);
4368        }
4369    }
4370}
4371
4372Use::UsePtrVector& Package::get_uses ()
4373{
4374  return (m_uses);
4375}
4376
4377bool Package::is_cmt ()
4378{
4379  return (m_is_cmt);
4380}
4381
4382static void show_packages ()
4383{
4384  Package::PackageVector& vector = Package::packages ();
4385
4386  int i;
4387  int j;
4388
4389  cout << "### Packages: ";
4390  for (i = 0; i < vector.size (); i++)
4391    {
4392      Package& p = vector[i];
4393      cout << p.get_name () << "[";
4394      Use::UsePtrVector& uses = p.get_uses ();
4395      for (j = 0; j < uses.size (); j++)
4396        {
4397          Use* u = uses[j];
4398          cout << u << ",";
4399        }
4400
4401      cout << "] ";
4402    }
4403  cout << endl;
4404
4405  {
4406    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
4407
4408    cout << "### Uses: ";
4409    for (i = 0; i < uses.size (); i++)
4410      {
4411        Use* u = uses[i];
4412        cout << "[" << u << "]" << u->get_package_name () << " ";
4413      }
4414  }
4415
4416  cout << endl;
4417}
4418
4419Project* Use::get_project ()
4420{   
4421  Project* p;
4422  cmt_string cmtpath = "";
4423  cmt_string offset  = "";   
4424  get_cmtpath_and_offset (cmtpath, offset);
4425  p = Project::find_by_cmtpath (cmtpath);
4426  return p;   
4427}
Note: See TracBrowser for help on using the repository browser.