source: CMT/v1r19/source/cmt_use.cxx

Last change on this file was 295, checked in by garonne, 18 years ago

beta development 1

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