source: CMT/HEAD/source/cmt_use.cxx @ 595

Last change on this file since 595 was 595, checked in by rybkin, 12 years ago

See C.L. 472

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