source: CMT/v1r20p20090520/source/cmt_use.cxx @ 653

Last change on this file since 653 was 461, checked in by rybkin, 16 years ago

See C.L. 362

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