source: CMT/v1r18p20050501/source/cmt_use.cxx @ 51

Last change on this file since 51 was 51, checked in by arnault, 19 years ago

fix bug in standard macro settings - see CL 272-1

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