source: CMT/v1r20p20070720/source/cmt_use.cxx

Last change on this file was 400, checked in by arnault, 17 years ago

Text formatting
Sending warnings & errors to stderr
Using internally PWD for every cd/pwd
CL 327

  • Property svn:eol-style set to native
File size: 99.1 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// Modified by garonne@lal.in2p3.fr
5// See the complete license in cmt_license.txt "http://www.cecill.info".
6//-----------------------------------------------------------
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include "cmt_use.h"
13#include "cmt_system.h"
14#include "cmt_symbol.h"
15#include "cmt_error.h"
16#include "cmt_database.h"
17#include "cmt_syntax.h"
18
19static void show_packages ();
20
21/*
22 *   Design.
23 *
24 *   There is one central database of all Use objects. This in the Database using:
25 *       Database::instance().get_instances ();
26 *
27 *   There is also a list of selected Use pointers available from
28 *       Database::instance().get_ordered_uses ();
29 *
30 *   A new Use object is created when a new use statement requires it:
31 *     o if the specified version is specified for the first time
32 *     o if the specified path is specified for the first time
33 *
34 */
35
36static bool add_request (const cmt_string& path,
37                         const cmt_string& package_name,
38                         const cmt_string& version)
39{
40  static cmt_map <cmt_string, bool> requests;
41
42  cmt_string request = package_name;
43  request += " ";
44  request += version;
45  request += " ";
46  request += path;
47  static bool b = true;
48
49  bool new_request = false;
50
51  if (!requests.has ((const cmt_string&) request))
52    {
53      new_request = true;
54      requests.add ((const cmt_string&) request, b);
55    }
56
57  return (new_request);
58}
59
60class UseContext
61{
62public:
63
64  static UseContext& current ()
65  {
66    static UseContext me;
67
68    return (me);
69  }
70
71  UseContext ()
72  {
73    m_auto_imports = On;
74  }
75
76  UseContext (const UseContext& other)
77  {
78    m_auto_imports = other.m_auto_imports;
79  }
80
81  UseContext& operator = (const UseContext& other)
82  {
83    m_auto_imports = other.m_auto_imports;
84
85    return (*this);
86  }
87
88  static void set_current (State auto_imports)
89  {
90    UseContext& c = current ();
91
92    c.m_auto_imports = auto_imports;
93  }
94
95  static State get_current_auto_imports ()
96  {
97    UseContext& c = current ();
98
99    return (c.m_auto_imports);
100  }
101
102private:
103  State m_auto_imports;
104};
105
106
107class BestFitSelector
108{
109public:
110  Use* operate (Use* ref_use, Use* new_use);
111};
112
113//----------------------------------------------------------
114
115typedef enum
116  {
117    IdenticalIds,
118
119    IncompatibleMajorIds,
120    NewMajorIdGreaterThanOld,
121    OldMajorIdGreaterThanNew,
122    ExplicitOldMajorIdWinsAgainstWildarded,
123    ExplicitNewMajorIdWinsAgainstWildarded,
124
125    ExplicitOldMinorIdWinsAgainstWildarded,
126    ExplicitNewMinorIdWinsAgainstWildarded,
127    NewMinorIdGreaterThanOld,
128
129    ExplicitOldPatchIdWinsAgainstWildarded,
130    ExplicitNewPatchIdWinsAgainstWildarded,
131    NewPatchIdGreaterThanOld
132  } CompareStatus;
133
134static CompareStatus compare_versions (const cmt_string& ref_version, const cmt_string& new_version)
135{
136  CompareStatus result = IdenticalIds;
137
138  int old_v = -1;
139  int old_r = -1;
140  int old_p = -1;
141
142  int new_v = -1;
143  int new_r = -1;
144  int new_p = -1;
145
146  CmtSystem::is_version_directory (ref_version, old_v, old_r, old_p);
147
148  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
149
150  if ((new_v != -1) && (old_v != -1) && (new_v != old_v))
151    {
152      /*
153        if (!Cmt::get_quiet ())
154        {
155        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
2905  if (cmtpath != "")
2906    {
2907      CmtSystem::compress_path (cmtpath);
2908
2909      static const cmt_string empty_string;
2910      static const cmt_string fs = CmtSystem::file_separator ();
2911     
2912      offset = real_path;
2913      offset.replace (cmtpath, empty_string);
2914
2915      /**
2916         try to remove this current CMTPATH entry from path.  This
2917         has a meaning when the specified path already contains an
2918         absolute path.
2919      */
2920     
2921      if (offset[0] == CmtSystem::file_separator ())
2922        {
2923          // Just in case there is a part left after removing the cmtpath entry
2924               
2925          offset.replace (fs, empty_string);
2926        }
2927    }
2928}
2929
2930//------------------------------------------------------------
2931bool Use::get_strategy (const cmt_string& name) const
2932{
2933  Project* p = Project::find_by_cmtpath (real_path);
2934
2935  bool strategy;
2936
2937  if (p == 0)
2938    {
2939      static const Project::ProjectVector& projects = Project::projects ();
2940
2941      if (projects.size () == 0) strategy = StrategyMgr::get_default_strategy (name);
2942      else
2943        {
2944          p = &(projects[0]);
2945          strategy = p->get_strategy (name);
2946        }
2947    }
2948  else
2949    {
2950      strategy = p->get_strategy (name);
2951    }
2952
2953  return (strategy);
2954}
2955
2956//----------------------------------------------------------
2957void Use::fill_includes_macro (cmt_string& buffer) const
2958{
2959  if (include_path == "")
2960    {
2961      buffer += "$(ppcmd)\"$(";
2962      buffer += get_package_name ();
2963      buffer += "_root)";
2964      buffer += CmtSystem::file_separator ();
2965      buffer += "src\" ";
2966    }
2967  else if (include_path != "none")
2968    {
2969      buffer += "$(ppcmd)\"";
2970      buffer += include_path;
2971      buffer += "\" ";
2972    }
2973 
2974  for (int i = 0; i < includes.size (); i++)
2975    {
2976      Include& incl = includes[i];
2977
2978      if (incl.name == "") continue;
2979     
2980      buffer += "$(ppcmd)\"";
2981      buffer += incl.name;
2982      buffer += "\" ";
2983    }
2984}
2985
2986//----------------------------------------------------------
2987void Use::fill_macro (cmt_string& buffer, const cmt_string& suffix) const
2988{
2989  buffer += " $(";
2990  buffer += get_package_name ();
2991  buffer += "_";
2992  buffer += suffix;
2993  buffer += ") ";
2994}
2995
2996//----------------------------------------------------------
2997void Use::fill_standard_macros (cmt_string& buffer) const
2998{
2999  static cmt_string fs = CmtSystem::file_separator ();
3000
3001  buffer = "";
3002
3003  cmt_string package_name = get_package_name ();
3004
3005  buffer += "macro ";
3006  buffer += package_name;
3007  buffer += "_tag";
3008  buffer += " \"$(tag)\"";
3009  buffer += "\n";
3010
3011  if (located ())
3012    {
3013      buffer += "macro ";
3014      buffer += prefix;
3015      buffer += "ROOT";
3016      buffer += " \"";
3017      buffer += get_full_path ();
3018      buffer += "\"";
3019      buffer += "\n";
3020
3021      buffer += "macro ";
3022      buffer += package_name;
3023      buffer += "_root";
3024      buffer += " \"";
3025      buffer += real_path;
3026      buffer += fs;
3027      buffer += package_name;
3028      if (style != no_version_style)
3029        {
3030          buffer += fs;
3031          buffer += version;
3032        }
3033      buffer += "\"";
3034      buffer += "\n";
3035    }
3036
3037  buffer += "macro ";
3038  buffer += prefix;
3039  buffer += "VERSION";
3040  buffer += " \"";
3041  buffer += version;
3042  buffer += "\"";
3043  buffer += "\n";
3044
3045  cmt_string cmtpath = "";
3046  cmt_string offset = "";
3047
3048  get_cmtpath_and_offset (cmtpath, offset);
3049
3050  buffer += "macro ";
3051  buffer += package_name;
3052  buffer += "_cmtpath";
3053  buffer += " \"";
3054  buffer += cmtpath;
3055  buffer += "\"";
3056  buffer += "\n";
3057
3058  buffer += "macro ";
3059  buffer += package_name;
3060  buffer += "_offset";
3061  buffer += " \"";
3062  buffer += offset;
3063  buffer += "\"";
3064  buffer += "\n";
3065 
3066  Project* p = Project::find_by_cmtpath (cmtpath);
3067
3068  buffer += "macro ";
3069  buffer += package_name;
3070  buffer += "_project";
3071  buffer += " \"";
3072  if (p != 0)
3073    {
3074      buffer += p->get_name ();
3075    }
3076  buffer += "\"";
3077  buffer += "\n";
3078
3079  buffer += "macro ";
3080  buffer += package_name;
3081  buffer += "_project_release";
3082  buffer += " \"";
3083  if (p != 0)
3084    {
3085      buffer += p->get_release ();
3086    }
3087  buffer += "\"";
3088}
3089
3090
3091//----------------------------------------------------------
3092static bool same_dirs (const cmt_string& d1, const cmt_string& d2)
3093{
3094  bool result = false;
3095
3096  cmt_string here = CmtSystem::pwd ();
3097
3098  cmt_string h1;
3099  if (CmtSystem::cd (d1)) h1 = CmtSystem::pwd ();
3100
3101  CmtSystem::cd (here);
3102
3103  cmt_string h2;
3104  if (CmtSystem::cd (d2)) h2 = CmtSystem::pwd ();
3105
3106  result = (h1 == h2);
3107
3108  CmtSystem::cd (here);
3109
3110  return (result);
3111}
3112
3113//----------------------------------------------------------
3114static bool install_library (const cmt_string& source_library_name, 
3115                             const cmt_string& dest_library_name, 
3116                             const cmt_string& cmtinstallarea, 
3117                             const cmt_string& tag, 
3118                             const cmt_string& symlinkcmd)
3119{
3120  cmt_string libname = source_library_name;
3121  cmt_string name = dest_library_name;
3122  cmt_string s;
3123  Use& current_use = Use::current ();
3124
3125  Symbol::expand (name);
3126  Symbol::expand (libname);
3127
3128  if (cmtinstallarea != "")
3129    {
3130      s = cmtinstallarea;
3131      s += CmtSystem::file_separator ();
3132      s += tag;
3133      s += CmtSystem::file_separator ();
3134      s += "lib";
3135      s += CmtSystem::file_separator ();
3136      s += name;
3137     
3138      // Now creating the reference file
3139
3140      cmt_string ref_file = s;
3141      ref_file += ".cmtref";
3142
3143      cmt_string text = libname;
3144      text += "\n";
3145
3146      Symbol::expand (ref_file);
3147      Symbol::expand (text);
3148
3149      if (!Cmt::get_quiet ()) cerr << "   Creating the reference file " << ref_file << endl;
3150      text.write (ref_file);
3151    }
3152  else
3153    {
3154      s = "../$(";
3155      s += current_use.get_package_name ();
3156      s += "_tag)/";
3157      s += name;
3158    }
3159
3160  Symbol::expand (s);
3161
3162  cmt_string source;
3163  cmt_string dest;
3164
3165  CmtSystem::dirname (libname, source);
3166  CmtSystem::dirname (s, dest);
3167
3168  if (same_dirs (source, dest))
3169    {
3170      return (false);
3171    }
3172
3173  //if (!Cmt::get_quiet ())
3174  cerr << "   Symlinking " << libname << " to " << s << endl;
3175
3176  if (symlinkcmd == "")
3177    {
3178      if (!CmtSystem::create_symlink (libname, s))
3179        {
3180          cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3181          return (false);
3182        }
3183    }
3184  else
3185    {
3186      cmt_string cmd = symlinkcmd;
3187      cmd += " ";
3188      cmd += libname;
3189      cmd += " ";
3190      cmd += s;
3191     
3192      int status = CmtSystem::execute (cmd);
3193     
3194      if (status != 0)
3195        {
3196          cerr << "#CMT> Cannot create a symbolic link to " << libname << endl;
3197          return (false);
3198        }
3199    }
3200
3201  return (true);
3202}
3203
3204
3205/**
3206   Centralize the construction of library links for this Use.
3207*/
3208void Use::build_library_links (const cmt_string& cmtinstallarea, 
3209                               const cmt_string& tag, 
3210                               const cmt_string& shlibsuffix, 
3211                               const cmt_string& symlinkcmd) const
3212{
3213  if (!located ())
3214    {
3215      if (!Cmt::get_quiet ())
3216        {
3217          cerr << "# package " << get_package_name () <<
3218            " " << version << " " << path << 
3219            " not found" <<
3220            endl;
3221        }
3222      return;
3223    }
3224
3225  cmt_string s;
3226
3227  s = get_package_name ();
3228  s += "_libraries";
3229
3230  Symbol* libraries_macro = Symbol::find (s);
3231
3232  if (libraries_macro == 0) return;
3233
3234  cmt_string libraries = libraries_macro->build_macro_value ();
3235  Symbol::expand (libraries);
3236  static CmtSystem::cmt_string_vector values;
3237
3238  CmtSystem::split (libraries, " \t", values);
3239
3240  for (int j = 0; j < values.size (); j++)
3241    {
3242      const cmt_string& library = values[j];
3243
3244      static cmt_string libname;
3245      static cmt_string name;
3246
3247      // Is it a simple name or a complete path?
3248
3249      libname = library;
3250      Symbol::expand (libname);
3251
3252      bool is_absolute = false;
3253
3254      is_absolute = CmtSystem::absolute_path (libname);
3255
3256      if (is_absolute)
3257        {
3258          /**
3259           *   We assume here that "library" contains a complete path.
3260           *   (including the complete syntax libxxx.so)
3261           */
3262
3263          cmt_string suffix;
3264          CmtSystem::basename (library, name);
3265        }
3266      else
3267        {
3268          /**
3269           *   Here we expect that only the base name of the library
3270           *   is given : ie it should not contain the "lib" prefix,
3271           *   nor the suffix .so, nor any path prefix.
3272           *    This of course should generally correspond to a constituent name.
3273           */
3274         
3275          libname = "${";
3276          libname += prefix;
3277          libname += "ROOT}/${";
3278          libname += get_package_name ();
3279          libname += "_tag}/";
3280          libname += "$(library_prefix)";
3281          libname += library;
3282          libname += "$(library_suffix)";
3283          libname += ".";
3284          libname += shlibsuffix;
3285
3286          name = "$(library_prefix)";
3287          name += library;
3288          name += "$(library_suffix)";
3289          name += ".";
3290          name += shlibsuffix;
3291        }
3292
3293      if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3294        {
3295          continue;
3296        }
3297
3298#ifdef __APPLE__
3299      if (!is_absolute)
3300        {
3301          libname = "${";
3302          libname += prefix;
3303          libname += "ROOT}/${";
3304          libname += get_package_name ();
3305          libname += "_tag}/";
3306          libname += library;
3307          libname += ".bundle";
3308
3309          name = library;
3310          name += ".bundle";
3311         
3312          if (!install_library (libname, name, cmtinstallarea, tag, symlinkcmd))
3313            {
3314              continue;
3315            }
3316        }
3317#endif
3318    }
3319}
3320
3321/**
3322 *   This function tries to get the replacement of a Use when it has
3323 *  been discarded by a better match to version constraints.
3324 */
3325Use* Use::get_selected_version ()
3326{
3327  if (!discarded) return (this);
3328
3329  Package* p = m_package;
3330
3331  Use::UsePtrVector& uses = p->get_uses ();
3332
3333  bool dbg = Cmt::get_debug ();
3334
3335  int size = uses.size ();
3336
3337  for (int i = 0; i < size; i++)
3338    {
3339      Use* u = uses[i];
3340      if (u == 0) continue;
3341      if (u->discarded) continue;
3342      if (dbg)
3343        {
3344          cout << "Use::get_selected_version> for package " << get_package_name ()
3345               << "  got a version " << u << endl;
3346        }
3347      return (u);
3348    }
3349
3350  return (0);
3351}
3352
3353/**
3354   Switching from one use to another one, (better wrt
3355   various criteria).
3356
3357   When switching, m_index and auto_imports are
3358   transfered from the un-selected to the newly selected.
3359*/
3360Use* Use::set_selected_version (Use* selected_use)
3361{
3362  if (this == selected_use) return (this);
3363
3364  static UsePtrVector& uses = get_ordered_uses ();
3365
3366  if (m_index >= 0)
3367    {
3368      // This discarded package was registered. We have to substitute
3369      // it with the new one.
3370
3371      selected_use->m_index = m_index;
3372      selected_use->auto_imports = auto_imports;
3373
3374      selected_use->undiscard ();
3375
3376      m_index = -1;
3377
3378      uses[selected_use->m_index] = selected_use;
3379    }
3380
3381  discard ();
3382
3383  return (selected_use);
3384}
3385
3386void Use::set_auto_imports (State new_state)
3387{
3388  if (Cmt::get_debug ())
3389    {
3390      cout << "Use::set_auto_imports>(" << get_package_name () << ") " 
3391           << auto_imports << " -> " << new_state << endl;
3392    }
3393
3394  if (auto_imports == new_state) return;
3395 
3396  State old_state = auto_imports;
3397 
3398  auto_imports = new_state;
3399
3400  // We propagate only when we switch from Off to On
3401
3402  if ((old_state == Off) && (new_state == On))
3403    {
3404      cmt_string s;
3405      static const cmt_string state_text[] = {"Unspecified", "Off", "On"};
3406
3407      if (Cmt::get_debug ())
3408        {
3409          s = "Use::set_auto_imports>(";
3410          s += get_package_name ();
3411          s += ") ";
3412
3413          cout << s << endl;
3414        }
3415
3416      for (int i = 0; i < sub_uses.size (); i++)
3417        {
3418          Use* u = sub_uses[i];
3419          State state = sub_use_auto_imports[i];
3420         
3421          if (Cmt::get_debug ())
3422            {
3423              s += " ";
3424              s += u->get_package_name ();
3425              s += "(";
3426              s += state_text[state];
3427              s += ")";
3428            }
3429
3430          if (state == Unspecified)
3431            {
3432              u->set_auto_imports (On);
3433            }
3434        }
3435         
3436      if (Cmt::get_debug ())
3437        {
3438          cout << s << endl;
3439        }
3440    }
3441}
3442
3443void Use::set_native_version (bool state)
3444{
3445  m_has_native_version = state;
3446}
3447
3448bool Use::has_native_version () const
3449{
3450  return (m_has_native_version);
3451}
3452
3453Package* Use::get_package () const
3454{
3455  return (m_package);
3456}
3457
3458const cmt_string& Use::get_package_name () const
3459{
3460  static const cmt_string null = "";
3461
3462  Package* p = m_package;
3463  if (p == 0) return (null);
3464
3465  return (p->get_name ());
3466}
3467
3468void Use::set_package_name (const cmt_string& name)
3469{
3470  Package* p = Package::add (name);
3471
3472  m_package = p;
3473  p->add_use (this);
3474}
3475
3476int Use::get_index () const
3477{
3478  return (m_index);
3479}
3480
3481//----------------------------------------------------------
3482bool Use::get_all_clients (const cmt_string& to_name)
3483{
3484  Use::UsePtrVector& uses = Use::get_ordered_uses ();
3485
3486  Use* use = Use::find (to_name);
3487
3488  if (use == 0)
3489    {
3490      cerr << "#CMT> No access to " << to_name << endl;
3491      return (false);
3492    }
3493
3494  cmt_map <cmt_string, Use*> all_clients;
3495  cmt_map <cmt_string, Use*> all_clients_ok;
3496
3497  const cmt_string& name = get_package_name ();
3498
3499  Use* me = this;
3500
3501  all_clients.add (name, me);
3502  all_clients_ok.add (name, me);
3503
3504  bool status = get_all_clients (use, to_name, all_clients, all_clients_ok); 
3505
3506  return (status);
3507}
3508
3509//----------------------------------------------------------
3510bool Use::get_all_clients (Use* to, 
3511                           const cmt_string& result, 
3512                           cmt_map <cmt_string, Use*>& all_clients, 
3513                           cmt_map <cmt_string, Use*>& all_clients_ok)
3514{
3515  if (this == to)
3516    {
3517      cout << result << endl;
3518      return (true);
3519    }
3520
3521  const cmt_string& to_name = to->get_package_name ();
3522  const cmt_string& to_version = to->version;
3523
3524  //cout << "gac> from " << get_package_name () << " to " << to_name << " -> " << result << endl;
3525
3526  if (all_clients.has (to_name))
3527    {
3528      if (all_clients_ok.has (to_name))
3529        {
3530          cout << "   ..." << result << endl;
3531          return (true);
3532        }
3533      else
3534        {
3535          return (false);
3536        }
3537    }
3538
3539  all_clients.add (to_name, to);
3540
3541  bool status = false;
3542
3543  Use::UsePtrVector& uses = Use::get_ordered_uses ();
3544  Use* use = 0;
3545
3546  for (int n = 0; n < uses.size (); ++n)
3547    {
3548      use = uses[n];
3549
3550      if (use->discarded) continue;
3551      if (use->m_hidden) continue;
3552
3553      if (!use->located ()) continue;
3554
3555      if (use == to) continue;
3556
3557      if (use->is_client (to_name, to_version))
3558        {
3559          const cmt_string& n = use->get_package_name ();
3560
3561          cmt_string r;
3562
3563          if ((use->initial_scope != ScopeUnspecified) &&
3564              (use->initial_scope != ScopePublic)) 
3565            {
3566              r += "(private)";
3567            }
3568         
3569          if (use->auto_imports == Off) r += "(no_auto_imports)";
3570
3571          r += n;
3572          r += ".";
3573          r += result;
3574
3575          //cout << "gac> " << n << " is client of " << to_name << endl;
3576
3577          if (get_all_clients (use, r, all_clients, all_clients_ok))
3578            {
3579              all_clients_ok.add (n, use);
3580              status = true;
3581            }
3582        }
3583    }
3584
3585  use = this;
3586
3587  if (use->is_client (to_name, to_version))
3588    {
3589      const cmt_string& n = use->get_package_name ();
3590     
3591      cmt_string r;
3592
3593      if ((use->initial_scope != ScopeUnspecified) &&
3594          (use->initial_scope != ScopePublic)) 
3595        {
3596          r += "(private)";
3597        }
3598     
3599      if (use->auto_imports == Off) r += "(no_auto_imports)";
3600
3601      r += n;
3602      r += ".";
3603      r += result;
3604     
3605      //cout << "gac> " << n << " is client of " << to_name << endl;
3606     
3607      if (get_all_clients (use, r, all_clients, all_clients_ok))
3608        {
3609          all_clients_ok.add (n, use);
3610          status = true;
3611        }
3612    }
3613
3614  return (status);
3615}
3616
3617/**
3618   Let's consider two packages in the use graph "this" and "to"
3619   This function finds all packages that are reached in between
3620   following all possible paths between "this" and "to"
3621
3622   Result s accumulated into "list"
3623*/
3624bool Use::get_paths (Use* to, UsePtrVector& list)
3625{
3626  bool is_in_path = false;
3627  bool cycle = false;
3628  bool already_in_path = false;
3629  bool dbg = Cmt::get_debug ();
3630
3631  static int level = 0;
3632
3633  int size = 0;
3634
3635  if (level == 0)
3636    {
3637      unselect_all ();
3638      selected = false;
3639    }
3640
3641  if (selected) 
3642    {
3643      /**
3644         If this use is already in the list, we don't duplicate the entry.
3645         (protection duplicate paths in the graph)
3646      */
3647
3648      size = list.size ();
3649
3650      for (int m = 0; m < size; m++)
3651        {
3652          Use* u = list[m];
3653          if (u == this)
3654            {
3655              if (dbg)
3656                {
3657                  for (int lll = 0; lll < level; lll++) cout << "  ";
3658                  cout << "  Use::get_paths." << level << "> try1.2 sub="
3659                       << get_package_name () << " already_in_path " << endl;
3660                }
3661             
3662              return (true);
3663            }
3664        }
3665
3666      return (false);
3667    }
3668
3669  selected = true;
3670
3671  if (dbg)
3672    {
3673      for (int lll = 0; lll < level; lll++) cout << "  ";
3674      cout << "Use::get_paths." << level << ">" << get_package_name ()
3675           << " to=" << to->get_package_name () 
3676           << " list=[";
3677
3678      for (int m = 0; m < list.size (); m++)
3679        {
3680          Use* u = list[m];
3681          cout << u->get_package_name () << " ";
3682        }
3683
3684      cout << "]" << endl;
3685    }
3686
3687  /**
3688     Now "this" is a candidate new entry in the list
3689  */
3690
3691  // First figure out whether 'to' is used by 'this'.
3692
3693  if (this->get_package_name () == to->get_package_name ())
3694    {
3695      // We've reached the goal (for the first time)
3696      is_in_path = true;
3697    }
3698  else
3699    {
3700      /**
3701         Let's scan sub_uses now
3702      */
3703      size = sub_uses.size ();
3704
3705      if (dbg)
3706        {
3707          for (int lll = 0; lll < level; lll++) cout << "  ";
3708          cout << "  Use::get_paths." << level << "> size=" << size << endl;
3709        }
3710
3711      for (int n = 0; n < size; n++)
3712        {
3713          Use* use = sub_uses[n];
3714
3715          if (use == 0) continue;
3716
3717          if (dbg)
3718            {
3719              for (int lll = 0; lll < level; lll++) cout << "  ";
3720              cout << "  Use::get_paths." << level << "> try1 sub="
3721                   << use->get_package_name () << "(" << use << ") " << use->discarded << endl;
3722            }
3723
3724          if (use->discarded)
3725            {
3726              Use* u;
3727
3728              u = use->get_selected_version ();
3729              if (u == 0) 
3730                {
3731                  /**
3732                     No way to find a valid use for this used package.
3733                     Is that a bug?
3734                     Anyway we don't pursue on that branch.
3735                  */
3736                  continue;
3737                }
3738
3739              use = u;
3740            }
3741
3742          if (dbg)
3743            {
3744              for (int lll = 0; lll < level; lll++) cout << "  ";
3745              cout << "  Use::get_paths." << level << "> try2 sub="
3746                   << use->get_package_name () << " " << use->discarded << endl;
3747            }
3748
3749          level++;
3750          bool r = use->get_paths (to, list);
3751          level--;
3752
3753          if (r)
3754            {
3755              is_in_path = true;
3756            }
3757        }
3758    }
3759
3760  if (is_in_path)
3761    {
3762      if (dbg)
3763        {
3764          for (int lll = 0; lll < level; lll++) cout << "  ";
3765          cout << "Use::get_paths." << level << "> push " << get_package_name () << endl;
3766        }
3767      list.push_back (this);
3768    }
3769
3770  return (is_in_path);
3771}
3772
3773//----------------------------------------------------------
3774bool Use::located () const
3775{
3776  return (m_located);
3777}
3778
3779//----------------------------------------------------------
3780void Use::show_sub_uses (const cmt_string& request, bool skip_discarded)
3781{
3782  Use* current = &(Use::current ());
3783  int n;
3784  Use* use;
3785  static int level = 0;
3786
3787  if (skip_discarded && discarded) return;
3788  if (m_hidden) return;
3789
3790  if (level > 0)
3791    {
3792      cout << "# ";
3793      for (n = 0; n < (level-1); n++) cout << "  ";
3794
3795      if (request == "")
3796        {
3797          cout << "use " << get_package_name () << " " << specified_version;
3798
3799          if (this == current) 
3800            {
3801              cout << " (current)";
3802            }
3803          else
3804            {
3805              if (specified_path != "") cout << " " << specified_path;
3806            }
3807        }
3808      else
3809        {
3810          cout << "use " << request;
3811        }
3812
3813      if (version_alias != "")
3814        {
3815          cout << " | " << version_alias << " " << path_alias;
3816        }
3817
3818      if (initial_scope == ScopeUnspecified) cout << " (unspecified)";
3819      else if (initial_scope != ScopePublic) cout << " (private)";
3820
3821      if (auto_imports == Off) cout << " (no_auto_imports)";
3822
3823      if (style == no_version_style) cout << " (no_version_directory)";
3824
3825      if (m_has_native_version)
3826        {
3827          cmt_string n = get_package_name ();
3828          n += "_native_version";
3829
3830          Symbol* s = Symbol::find (n);
3831          if (s != 0)
3832            {
3833              cmt_string value = s->resolve_macro_value ();
3834              cout << " (native_version=" << value << ")";
3835            }
3836        }
3837
3838      cout << endl;
3839    }
3840
3841  if (selected) return;
3842  selected = true;
3843
3844  level++;
3845  for (n = 0; n < sub_uses.size (); n++)
3846    {
3847      use = sub_uses[n];
3848      if (use == 0) continue;
3849
3850      const cmt_string& request = requests[n];
3851
3852      ScopeType saved_scope = use->initial_scope;
3853      State saved_state = use->auto_imports;
3854
3855      use->initial_scope = sub_use_scopes[n];
3856      use->auto_imports = sub_use_auto_imports[n];
3857
3858      use->show_sub_uses (request, skip_discarded);
3859
3860      use->initial_scope = saved_scope;
3861      use->auto_imports = saved_state;
3862    }
3863  level--;
3864}
3865
3866//----------------------------------------------------------
3867Use& Use::current ()
3868{
3869  static UseVector& instances = get_instances ();
3870  static Use* current_use = 0;
3871
3872  if ((current_use == 0) || (instances.size () == 0))
3873    {
3874      Use& use_object = instances.add ();
3875      current_use = &use_object;
3876    }
3877
3878  return (*current_use);
3879}
3880
3881//----------------------------------------------------------
3882const Use& Use::const_current ()
3883{
3884  const Use& use = Use::current ();
3885
3886  return (use);
3887}
3888
3889//----------------------------------------------------------
3890Use::UseVector& Use::get_instances ()
3891{
3892  static Database& db = Database::instance ();
3893  static UseVector& instances = db.all_uses ();
3894
3895  return (instances);
3896}
3897
3898//----------------------------------------------------------
3899Use::UsePtrVector& Use::get_ordered_uses ()
3900{
3901  static Database& db = Database::instance ();
3902  static UsePtrVector& uses = db.uses ();
3903
3904  return (uses);
3905}
3906
3907//----------------------------------------------------------
3908
3909//----------------------------------------------------------
3910//
3911//  Check if the specified version is better than the
3912//  current one.
3913//
3914//----------------------------------------------------------
3915Use* BestFitSelector::operate (Use* ref_use, Use* new_use)
3916{
3917  Use* selected = ref_use;
3918
3919  int ref_v = -1;
3920  int ref_r = -1;
3921  int ref_p = -1;
3922  cmt_string ref_pp;
3923
3924  int new_v = -1;
3925  int new_r = -1;
3926  int new_p = -1;
3927  cmt_string new_pp;
3928
3929  int alias_v = -1;
3930  int alias_r = -1;
3931  int alias_p = -1;
3932  cmt_string alias_pp;
3933
3934  enum { no_alias, new_has_alias, ref_has_alias } has_alias = no_alias;
3935
3936  // First analyze specified versions
3937  cmt_string ref_version = ref_use->specified_version;
3938  cmt_string new_version = new_use->specified_version;
3939
3940  CmtSystem::is_version_directory (ref_version, ref_v, ref_r, ref_p);
3941  ref_pp = ref_use->path;
3942
3943  CmtSystem::is_version_directory (new_version, new_v, new_r, new_p);
3944  new_pp = new_use->path;
3945
3946  if (new_use->version_alias != "")
3947    {
3948      has_alias = new_has_alias;
3949      CmtSystem::is_version_directory (new_use->version_alias, 
3950                                       alias_v, alias_r, alias_p);
3951      alias_pp = new_use->path_alias;
3952    }
3953  else if (ref_use->version_alias != "")
3954    {
3955      has_alias = ref_has_alias;
3956      CmtSystem::is_version_directory (ref_use->version_alias, 
3957                                       alias_v, alias_r, alias_p);
3958      alias_pp = ref_use->path_alias;
3959    }
3960
3961  ref_use->undiscard ();
3962  new_use->undiscard ();
3963
3964  if (new_v != ref_v)
3965    {
3966      if (has_alias != no_alias)
3967        {
3968          if (has_alias == new_has_alias)
3969            {
3970              new_v = alias_v;
3971              new_r = alias_r;
3972              new_p = alias_p;
3973              new_pp = alias_pp;
3974            }
3975          else if (has_alias == ref_has_alias)
3976            {
3977              ref_v = alias_v;
3978              ref_r = alias_r;
3979              ref_p = alias_p;
3980              ref_pp = alias_pp;
3981            }
3982        }
3983    }
3984
3985  bool ref_v_wildcarded = ((ref_v) == -1);
3986  bool ref_r_wildcarded = ((ref_r) == -1);
3987  bool ref_p_wildcarded = ((ref_p) == -1);
3988
3989  bool ref_v_explicit = !ref_v_wildcarded;
3990  bool ref_r_explicit = !ref_r_wildcarded;
3991  bool ref_p_explicit = !ref_p_wildcarded;
3992
3993  bool new_v_wildcarded = ((new_v) == -1);
3994  bool new_r_wildcarded = ((new_r) == -1);
3995  bool new_p_wildcarded = ((new_p) == -1);
3996
3997  bool new_v_explicit = !new_v_wildcarded;
3998  bool new_r_explicit = !new_r_wildcarded;
3999  bool new_p_explicit = !new_p_wildcarded;
4000
4001  bool verbose = (CmtSystem::getenv ("CMTVERBOSE") != "");
4002
4003  cmt_string ref_vc = ref_v_wildcarded ? "wildcarded" : "explicit";
4004  cmt_string ref_rc = ref_r_wildcarded ? "wildcarded" : "explicit";
4005  cmt_string ref_pc = ref_p_wildcarded ? "wildcarded" : "explicit";
4006 
4007  cmt_string new_vc = new_v_wildcarded ? "wildcarded" : "explicit";
4008  cmt_string new_rc = new_r_wildcarded ? "wildcarded" : "explicit";
4009  cmt_string new_pc = new_p_wildcarded ? "wildcarded" : "explicit";
4010
4011  // Now compute effective version identifiers
4012  CmtSystem::is_version_directory (ref_use->version, ref_v, ref_r, ref_p);
4013  CmtSystem::is_version_directory (new_use->version, new_v, new_r, new_p);
4014
4015  cmt_string new_selected_version = new_use->version;
4016
4017  if (new_v_explicit && ref_v_explicit && (new_v != ref_v))
4018    {
4019      /*
4020        if (verbose && !Cmt::get_quiet ())
4021        {
4022        cerr << "# Required explicit version " << new_version
4023        << " of package " << ref_use->get_package_name ()
4024        << " incompatible with selected explicit version " << ref_version
4025        << endl;
4026        }
4027
4028        CmtError::set (CmtError::version_conflict, "BestFitSelector::operate> ");
4029
4030        if (ref_use != new_use) new_use->discard ();
4031      */
4032
4033      if (new_v > ref_v)
4034        {
4035          if (verbose && !Cmt::get_quiet ())
4036            {
4037              cerr << "# Select " << new_vc << " version " << new_version
4038                   << " of package " << ref_use->get_package_name () 
4039                   << " instead of existing " << ref_vc << " " << ref_version
4040                   << endl;
4041            } 
4042         
4043          if (ref_use != new_use) ref_use->discard ();
4044          selected = new_use;
4045          selected->done = false; // Will read the new requirements
4046        }
4047    }
4048  else if (new_v_wildcarded || ref_v_wildcarded)
4049    {
4050      // at least one of ref or new is wildcarded
4051
4052      //
4053      // we plan to discard new_use, but if it was specified as explicit
4054      // and ref_use was wildcarded then new_use will win !!
4055      //
4056      // So then we'll have to understand where are the wild
4057      // cards... If they are on v or r, then we consider them.
4058      //
4059      //
4060
4061      if (ref_v_wildcarded && new_v_explicit)
4062        {
4063          if ((ref_use->real_path != new_use->real_path) ||
4064              (ref_use->version != new_use->version))
4065            {
4066              if (ref_use != new_use) ref_use->discard ();
4067              selected = new_use;
4068              selected->done = false; // Will read the new requirements
4069
4070              if (verbose && !Cmt::get_quiet ())
4071                {
4072                  cerr << "# Select explicit version " << new_version
4073                       << "(" << new_use->version << ")" 
4074                       << " of package " << ref_use->get_package_name () 
4075                       << " instead of existing wildcarded " << ref_version
4076                       << "(" << ref_use->version << ")" 
4077                       << endl;
4078                }
4079            }
4080          else
4081            {
4082              if (ref_use != new_use) new_use->discard ();
4083              //ref_use->version = new_selected_version;
4084            }
4085        }
4086      else
4087        {
4088          // ref is explicit or new is wildcarded
4089
4090          /*
4091            if (verbose && !Cmt::get_quiet ())
4092            {
4093            cerr << "# keep " << ref_vc << " version " << ref_version
4094            << " of package " << ref_use->get_package_name ()
4095            << " (ignore " << new_vc << " version " << new_version << ")"
4096            << endl;
4097            }
4098          */
4099
4100          if (ref_use != new_use) new_use->discard ();
4101        }
4102    }
4103  else if (new_r_wildcarded || ref_r_wildcarded || (new_r < ref_r))
4104    {
4105      //
4106      // we plan to discard new_use, but if it was specified as explicit
4107      // and ref_use was wildcarded then new_use will win !!
4108      //
4109      // So then we'll have to understand where are the wild
4110      // cards... If they are on v or r, then we consider them.
4111      //
4112      //
4113
4114      if (ref_r_wildcarded && new_r_explicit)
4115        {
4116          // ref has wild card and new has not => new wins
4117
4118          if ((ref_use->real_path != new_use->real_path) ||
4119              (ref_use->version != new_use->version))
4120            {
4121              if (ref_use != new_use) ref_use->discard ();
4122              selected = new_use;
4123              selected->done = false; // Will read the new requirements
4124
4125              if (verbose && !Cmt::get_quiet ())
4126                {
4127                  cerr << "# Select explicit release " << new_version
4128                       << " of package " << ref_use->get_package_name ()
4129                       << " instead of existing wildcarded " << ref_version
4130                       << endl;
4131                } 
4132            }
4133          else
4134            {
4135              // Just adapt version with new one.
4136
4137              if (ref_use != new_use) new_use->discard ();
4138              //ref_use->version = new_selected_version;
4139            }
4140        }
4141      else
4142        {
4143          /*
4144            if (verbose &&!Cmt::get_quiet ())
4145            {
4146            cerr << "# keep " << ref_rc << " release " << ref_version
4147            << " of package " << ref_use->get_package_name ()
4148            << " (ignore " << new_rc << " release " << new_version << ")"
4149            << endl;
4150            }
4151          */
4152
4153          if (ref_use != new_use) new_use->discard ();
4154        }
4155    }
4156  else if (new_r > ref_r)
4157    {
4158      if (verbose && !Cmt::get_quiet ())
4159        {
4160          cerr << "# Select " << new_rc << " release " << new_version
4161               << " of package " << ref_use->get_package_name () 
4162               << " instead of existing " << ref_rc << " " << ref_version
4163               << endl;
4164        } 
4165
4166      if (ref_use != new_use) ref_use->discard ();
4167      selected = new_use;
4168      selected->done = false; // Will read the new requirements
4169    }
4170  else if (new_p_wildcarded || ref_p_wildcarded || (new_p < ref_p))
4171    {
4172      //
4173      // we plan to discard new_use, but if it was specified as explicit
4174      // and ref_use was wildcarded then new_use will win !!
4175      //
4176
4177      if (ref_p_wildcarded && new_p_explicit)
4178        {
4179          if ((ref_use->real_path != new_use->real_path) ||
4180              (ref_use->version != new_use->version))
4181            {
4182              if (ref_use != new_use) ref_use->discard ();
4183              selected = new_use;
4184              selected->done = false; // Will read the new requirements
4185
4186              if (verbose && !Cmt::get_quiet ())
4187                {
4188                  cerr << "# Select explicit patch " << new_version
4189                       << " of package " << ref_use->get_package_name () 
4190                       << " instead of existing wildcarded " << ref_version
4191                       << endl;
4192                }
4193            }
4194          else
4195            {
4196              if (ref_use != new_use) new_use->discard ();
4197              ref_use->version = new_selected_version;
4198            }
4199        }
4200      else
4201        {
4202          /*
4203            if (verbose && !Cmt::get_quiet ())
4204            {
4205            cerr << "# keep " << ref_pc << " patch " << ref_version
4206            << " [" << ref_use->specified_version << "]"
4207            << " of package " << ref_use->get_package_name ()
4208            << " (ignore " << new_pc << " version " << new_version << ")"
4209            << " [" << new_use->specified_version << "]"
4210            << endl;
4211            }
4212          */
4213
4214          if (ref_use != new_use) new_use->discard ();
4215        }
4216    }
4217  else if (new_p > ref_p)
4218    {
4219      if (verbose && !Cmt::get_quiet ())
4220        {
4221          cerr << "# Select " << new_pc << " patch " << new_version
4222               << " of package " << ref_use->get_package_name () 
4223               << " instead of existing " << ref_pc << " " << ref_version
4224               << endl;
4225        }
4226
4227      if (ref_use != new_use) ref_use->discard ();
4228      selected = new_use;
4229      selected->done = false; // Will read the new requirements
4230    }
4231  else if (new_pp != ref_pp) // same version-r-p but from different path
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
4238  return (selected);
4239}
4240
4241
4242Package* Package::find (const cmt_string& name)
4243{
4244  static PackageMap& PackageMap = package_map ();
4245
4246  Package* result = 0;
4247
4248  result = PackageMap.find (name);
4249
4250  return (result);
4251}
4252
4253Package* Package::add (const cmt_string& name)
4254{
4255  static PackageVector& Packages = packages ();
4256  static PackageMap& PackageMap = package_map ();
4257
4258  {
4259    Package* package;
4260
4261    package = find (name);
4262    if (package != 0) return (package);
4263  }
4264
4265  Package& package = Packages.add ();
4266  PackageMap.add (name, package);
4267
4268  package.m_name = name;
4269
4270  if (name == "CMT")
4271    {
4272      package.m_is_cmt = true;
4273    }
4274  else if (name == "methods")
4275    {
4276      package.m_is_cmt = true;
4277    }
4278
4279  if (Cmt::get_debug ())
4280    {
4281      cout << "Package::add (" << name << ")" << endl;
4282    }
4283
4284  return (&package);
4285}
4286
4287Package::PackageVector& Package::packages ()
4288{
4289  static Database& db = Database::instance ();
4290  static PackageVector& Packages = db.packages ();
4291
4292  return (Packages);
4293}
4294
4295Package::PackageMap& Package::package_map ()
4296{
4297  static Database& db = Database::instance ();
4298  static PackageMap& PackageMap = db.package_map ();
4299
4300  return (PackageMap);
4301}
4302
4303void Package::clear_all ()
4304{
4305  static PackageVector& Packages = packages ();
4306  static PackageMap& PackageMap = package_map ();
4307
4308  PackageMap.clear ();
4309  Packages.clear ();
4310}
4311
4312Package::Package () : m_is_cmt (false)
4313{
4314  if (Cmt::get_debug ())
4315    {
4316      cout << "Package::Package" << endl;
4317    }
4318}
4319
4320Package::~Package ()
4321{
4322  m_name = "";
4323}
4324
4325const cmt_string& Package::get_name () const
4326{
4327  return (m_name);
4328}
4329
4330void Package::add_use (Use* use)
4331{
4332  for (int i = 0; i < m_uses.size (); i++)
4333    {
4334      Use* u = m_uses[i];
4335      if (u == use) return;
4336    }
4337
4338  m_uses.push_back (use);
4339}
4340
4341void Package::remove_use (Use* use)
4342{
4343  if (Cmt::get_debug ())
4344    {
4345      cout << "Package::remove_use (" << use->get_package_name () << ")" << endl;
4346      cout << "  name=" << m_name
4347           << " uses=" << m_uses.size () << endl;
4348    }
4349
4350  Use::UsePtrVector temp;
4351
4352  temp = m_uses;
4353
4354  m_uses.clear ();
4355
4356  for (int i = 0; i < temp.size (); i++)
4357    {
4358      Use* u = temp[i];
4359      if (u != use)
4360        {
4361          m_uses.push_back (u);
4362        }
4363    }
4364}
4365
4366Use::UsePtrVector& Package::get_uses ()
4367{
4368  return (m_uses);
4369}
4370
4371bool Package::is_cmt ()
4372{
4373  return (m_is_cmt);
4374}
4375
4376static void show_packages ()
4377{
4378  Package::PackageVector& vector = Package::packages ();
4379
4380  int i;
4381  int j;
4382
4383  cout << "### Packages: ";
4384  for (i = 0; i < vector.size (); i++)
4385    {
4386      Package& p = vector[i];
4387      cout << p.get_name () << "[";
4388      Use::UsePtrVector& uses = p.get_uses ();
4389      for (j = 0; j < uses.size (); j++)
4390        {
4391          Use* u = uses[j];
4392          cout << u << ",";
4393        }
4394
4395      cout << "] ";
4396    }
4397  cout << endl;
4398
4399  {
4400    static Use::UsePtrVector& uses = Use::get_ordered_uses ();
4401
4402    cout << "### Uses: ";
4403    for (i = 0; i < uses.size (); i++)
4404      {
4405        Use* u = uses[i];
4406        cout << "[" << u << "]" << u->get_package_name () << " ";
4407      }
4408  }
4409
4410  cout << endl;
4411}
4412
4413Project* Use::get_project ()
4414{   
4415  Project* p;
4416  cmt_string cmtpath = "";
4417  cmt_string offset  = "";   
4418  get_cmtpath_and_offset (cmtpath, offset);
4419  p = Project::find_by_cmtpath (cmtpath);
4420  return p;   
4421}
Note: See TracBrowser for help on using the repository browser.